From 37b065a097b05fe68502d5bfb113ad06390ecefe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Tue, 19 May 2020 00:28:52 +0200 Subject: [PATCH] Progress. --- .../com/plotsquared/bukkit/BukkitCommand.java | 5 - .../com/plotsquared/bukkit/BukkitMain.java | 51 +-- .../plotsquared/bukkit/command/DebugUUID.java | 323 ----------------- .../bukkit/listener/PaperListener.java | 48 +++ .../bukkit/listener/PlayerEvents.java | 28 +- .../bukkit/placeholder/Placeholders.java | 7 +- .../bukkit/player/BukkitPlayer.java | 6 +- .../bukkit/player/BukkitPlayerManager.java | 28 +- .../plotsquared/bukkit/util/BukkitUtil.java | 11 +- .../plotsquared/bukkit/util/SendChunk.java | 167 --------- .../bukkit/util/uuid/DatFileFilter.java | 36 -- .../bukkit/util/uuid/FileUUIDHandler.java | 289 ---------------- .../util/uuid/LowerOfflineUUIDWrapper.java | 60 ---- .../bukkit/util/uuid/OfflineUUIDWrapper.java | 131 ------- .../bukkit/util/uuid/SQLUUIDHandler.java | 270 --------------- .../java/com/plotsquared/core/IPlotMain.java | 17 +- .../com/plotsquared/core/PlotSquared.java | 34 +- .../com/plotsquared/core/api/PlotAPI.java | 13 - .../com/plotsquared/core/command/Add.java | 104 +++--- .../com/plotsquared/core/command/Alias.java | 49 ++- .../com/plotsquared/core/command/Cluster.java | 177 +++++----- .../com/plotsquared/core/command/Command.java | 6 + .../com/plotsquared/core/command/Comment.java | 8 +- .../core/command/DebugClaimTest.java | 134 -------- .../core/command/DebugImportWorlds.java | 5 +- .../com/plotsquared/core/command/Deny.java | 74 ++-- .../com/plotsquared/core/command/Merge.java | 2 +- .../com/plotsquared/core/command/Visit.java | 204 ++++++----- .../core/configuration/Captions.java | 1 + .../core/listener/PlotListener.java | 5 +- .../plotsquared/core/player/PlotPlayer.java | 17 +- .../java/com/plotsquared/core/plot/Plot.java | 104 +----- .../com/plotsquared/core/util/MainUtil.java | 72 ++-- .../plotsquared/core/util/PlayerManager.java | 120 +++++++ .../core/util/SchematicHandler.java | 2 +- .../plotsquared/core/util/TabCompletions.java | 82 +++++ .../core/util/uuid/UUIDHandler.java | 198 ----------- .../util/uuid/UUIDHandlerImplementation.java | 324 ------------------ .../core/uuid/CacheUUIDService.java | 5 + .../plotsquared/core/uuid/UUIDMapping.java | 3 +- .../plotsquared/core/uuid/UUIDPipeline.java | 45 ++- .../plotsquared/core/uuid/UUIDService.java | 12 + .../util/UUIDHandlerImplementationTest.java | 5 +- 43 files changed, 759 insertions(+), 2523 deletions(-) delete mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/command/DebugUUID.java rename Core/src/main/java/com/plotsquared/core/util/uuid/UUIDWrapper.java => Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayerManager.java (71%) delete mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/SendChunk.java delete mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/DatFileFilter.java delete mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/FileUUIDHandler.java delete mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/LowerOfflineUUIDWrapper.java delete mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/OfflineUUIDWrapper.java delete mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/SQLUUIDHandler.java delete mode 100644 Core/src/main/java/com/plotsquared/core/command/DebugClaimTest.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/PlayerManager.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/TabCompletions.java delete mode 100644 Core/src/main/java/com/plotsquared/core/util/uuid/UUIDHandler.java delete mode 100644 Core/src/main/java/com/plotsquared/core/util/uuid/UUIDHandlerImplementation.java diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitCommand.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitCommand.java index 2d3737ee0..20ab45529 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitCommand.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitCommand.java @@ -25,7 +25,6 @@ */ package com.plotsquared.bukkit; -import com.plotsquared.bukkit.command.DebugUUID; import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.core.command.MainCommand; import com.plotsquared.core.player.ConsolePlayer; @@ -46,10 +45,6 @@ import java.util.List; public class BukkitCommand implements CommandExecutor, TabCompleter { - public BukkitCommand() { - new DebugUUID(); - } - @Override public boolean onCommand(CommandSender commandSender, Command command, String commandLabel, String[] args) { diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index a03ac3218..90a717fd5 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -38,6 +38,7 @@ import com.plotsquared.bukkit.managers.HyperverseWorldManager; import com.plotsquared.bukkit.managers.MultiverseWorldManager; import com.plotsquared.bukkit.placeholder.PlaceholderFormatter; import com.plotsquared.bukkit.placeholder.Placeholders; +import com.plotsquared.bukkit.player.BukkitPlayerManager; import com.plotsquared.bukkit.queue.BukkitLocalQueue; import com.plotsquared.bukkit.schematic.BukkitSchematicHandler; import com.plotsquared.bukkit.util.BukkitChatManager; @@ -50,11 +51,6 @@ import com.plotsquared.bukkit.util.BukkitTaskManager; import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.bukkit.util.SetGenCB; import com.plotsquared.bukkit.util.UpdateUtility; -import com.plotsquared.bukkit.util.uuid.DefaultUUIDWrapper; -import com.plotsquared.bukkit.util.uuid.FileUUIDHandler; -import com.plotsquared.bukkit.util.uuid.LowerOfflineUUIDWrapper; -import com.plotsquared.bukkit.util.uuid.OfflineUUIDWrapper; -import com.plotsquared.bukkit.util.uuid.SQLUUIDHandler; import com.plotsquared.bukkit.uuid.OfflinePlayerUUIDService; import com.plotsquared.bukkit.uuid.PaperUUIDService; import com.plotsquared.bukkit.uuid.SQLiteUUIDService; @@ -69,6 +65,7 @@ import com.plotsquared.core.configuration.ChatFormatter; import com.plotsquared.core.configuration.ConfigurationNode; import com.plotsquared.core.configuration.ConfigurationSection; import com.plotsquared.core.configuration.Settings; +import com.plotsquared.core.database.DBFunc; import com.plotsquared.core.generator.GeneratorWrapper; import com.plotsquared.core.generator.HybridGen; import com.plotsquared.core.generator.HybridUtils; @@ -94,6 +91,7 @@ import com.plotsquared.core.util.EconHandler; import com.plotsquared.core.util.InventoryUtil; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.PlatformWorldManager; +import com.plotsquared.core.util.PlayerManager; import com.plotsquared.core.util.PremiumVerification; import com.plotsquared.core.util.ReflectionUtils; import com.plotsquared.core.util.RegionManager; @@ -102,9 +100,6 @@ import com.plotsquared.core.util.SetupUtils; import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; -import com.plotsquared.core.util.uuid.UUIDHandlerImplementation; -import com.plotsquared.core.util.uuid.UUIDWrapper; import com.plotsquared.core.uuid.CacheUUIDService; import com.plotsquared.core.uuid.UUIDPipeline; import com.plotsquared.core.uuid.offline.OfflineModeUUIDService; @@ -171,6 +166,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain private boolean metricsStarted; @Getter private BackupManager backupManager; @Getter private PlatformWorldManager worldManager; + @Getter private final PlayerManager playerManager = new BukkitPlayerManager(); @Override public int[] getServerVersion() { if (this.version == null) { @@ -265,6 +261,8 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain backgroundPipeline.registerService(backgroundMojangService); } + impromptuPipeline.storeImmediately("*", DBFunc.EVERYONE); + if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { new Placeholders().register(); if (Settings.Enabled_Components.EXTERNAL_PLACEHOLDERS) { @@ -842,39 +840,6 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain return new BukkitInventoryUtil(); } - @Override public UUIDHandlerImplementation initUUIDHandler() { - final UUIDWrapper wrapper; - if (Settings.UUID.OFFLINE) { - if (Settings.UUID.FORCE_LOWERCASE) { - wrapper = new LowerOfflineUUIDWrapper(); - } else { - wrapper = new OfflineUUIDWrapper(); - } - Settings.UUID.OFFLINE = true; - } else { - wrapper = new DefaultUUIDWrapper(); - Settings.UUID.OFFLINE = false; - } - if (!Bukkit.getVersion().contains("git-Spigot")) { - if (wrapper instanceof DefaultUUIDWrapper - || wrapper.getClass() == OfflineUUIDWrapper.class && !Bukkit.getOnlineMode()) { - Settings.UUID.NATIVE_UUID_PROVIDER = true; - } - } - if (Settings.UUID.OFFLINE) { - PlotSquared.log(Captions.PREFIX + "&6" + getPluginName() - + " is using Offline Mode UUIDs either because of user preference, or because you are using an old version of " - + "Bukkit"); - } else { - PlotSquared.log(Captions.PREFIX + "&6" + getPluginName() + " is using online UUIDs"); - } - if (Settings.UUID.USE_SQLUUIDHANDLER) { - return new SQLUUIDHandler(wrapper); - } else { - return new FileUUIDHandler(wrapper); - } - } - @Override public void setGenerator(@NonNull final String worldName) { World world = BukkitUtil.getWorld(worldName); if (world == null) { @@ -925,10 +890,10 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain return BukkitUtil.getPlayer((OfflinePlayer) player); } if (player instanceof String) { - return UUIDHandler.getPlayer((String) player); + return PlotSquared.imp().getPlayerManager().getPlayerIfExists((String) player); } if (player instanceof UUID) { - return UUIDHandler.getPlayer((UUID) player); + return PlotSquared.imp().getPlayerManager().getPlayerIfExists((UUID) player); } return null; } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/command/DebugUUID.java b/Bukkit/src/main/java/com/plotsquared/bukkit/command/DebugUUID.java deleted file mode 100644 index 79b411791..000000000 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/command/DebugUUID.java +++ /dev/null @@ -1,323 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * PlotSquared plot management system for Minecraft - * Copyright (C) 2020 IntellectualSites - * - * 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, see . - */ -package com.plotsquared.bukkit.command; - -import com.google.common.collect.Sets; -import com.plotsquared.bukkit.util.uuid.DatFileFilter; -import com.plotsquared.bukkit.util.uuid.DefaultUUIDWrapper; -import com.plotsquared.bukkit.util.uuid.LowerOfflineUUIDWrapper; -import com.plotsquared.bukkit.util.uuid.OfflineUUIDWrapper; -import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.command.Argument; -import com.plotsquared.core.command.CommandCategory; -import com.plotsquared.core.command.CommandDeclaration; -import com.plotsquared.core.command.RequiredType; -import com.plotsquared.core.command.SubCommand; -import com.plotsquared.core.configuration.Captions; -import com.plotsquared.core.database.DBFunc; -import com.plotsquared.core.player.OfflinePlotPlayer; -import com.plotsquared.core.player.PlotPlayer; -import com.plotsquared.core.plot.Plot; -import com.plotsquared.core.util.MainUtil; -import com.plotsquared.core.util.StringMan; -import com.plotsquared.core.util.StringWrapper; -import com.plotsquared.core.util.WorldUtil; -import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; -import com.plotsquared.core.util.uuid.UUIDWrapper; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map.Entry; -import java.util.UUID; - -@CommandDeclaration(command = "uuidconvert", - permission = "plots.admin", - description = "Debug UUID conversion", - usage = "/plot uuidconvert ", - requiredType = RequiredType.CONSOLE, - category = CommandCategory.DEBUG) -public class DebugUUID extends SubCommand { - - public DebugUUID() { - super(Argument.String); - } - - @Override public boolean onCommand(final PlotPlayer player, String[] args) { - final UUIDWrapper currentUUIDWrapper = UUIDHandler.getUUIDWrapper(); - final UUIDWrapper newWrapper; - - switch (args[0].toLowerCase()) { - case "lower": - newWrapper = new LowerOfflineUUIDWrapper(); - break; - case "offline": - newWrapper = new OfflineUUIDWrapper(); - break; - case "online": - newWrapper = new DefaultUUIDWrapper(); - break; - default: - try { - Class clazz = Class.forName(args[0]); - newWrapper = (UUIDWrapper) clazz.newInstance(); - } catch (ClassNotFoundException | IllegalAccessException | InstantiationException ignored) { - MainUtil.sendMessage(player, Captions.COMMAND_SYNTAX, - "/plot uuidconvert "); - return false; - } - } - - if (args.length != 2 || !"-o".equals(args[1])) { - MainUtil.sendMessage(player, Captions.COMMAND_SYNTAX, - "/plot uuidconvert " + args[0] + " -o"); - MainUtil.sendMessage(player, "&cBe aware of the following!"); - MainUtil.sendMessage(player, - "&8 - &cUse the database command or another method to backup your plots beforehand"); - MainUtil.sendMessage(player, - "&8 - &cIf the process is interrupted, all plots could be deleted"); - MainUtil.sendMessage(player, "&8 - &cIf an error occurs, all plots could be deleted"); - MainUtil.sendMessage(player, "&8 - &cPlot settings WILL be lost upon conversion"); - MainUtil - .sendMessage(player, "&cTO REITERATE: BACK UP YOUR DATABASE BEFORE USING THIS!!!"); - MainUtil.sendMessage(player, - "&7Retype the command with the override parameter when ready :)"); - return false; - } - - if (currentUUIDWrapper.getClass().getCanonicalName() - .equals(newWrapper.getClass().getCanonicalName())) { - MainUtil.sendMessage(player, "&cUUID mode already in use!"); - return false; - } - MainUtil.sendMessage(player, "&6Beginning UUID mode conversion"); - MainUtil.sendMessage(player, "&7 - Disconnecting players"); - for (Entry entry : UUIDHandler.getPlayers().entrySet()) { - entry.getValue() - .kick("UUID conversion has been initiated. You may reconnect when finished."); - } - - MainUtil.sendMessage(player, "&7 - Initializing map"); - - final HashMap uCMap = new HashMap<>(); - final HashMap uCReverse = new HashMap<>(); - - MainUtil.sendMessage(player, "&7 - Collecting playerdata"); - - HashSet worlds = Sets.newHashSet(WorldUtil.IMP.getMainWorld(), "world"); - HashSet uuids = new HashSet<>(); - HashSet names = new HashSet<>(); - for (String worldName : worlds) { - File playerDataFolder = new File(worldName + File.separator + "playerdata"); - String[] dat = playerDataFolder.list(new DatFileFilter()); - if (dat != null) { - for (String current : dat) { - String s = current.replaceAll(".dat$", ""); - try { - UUID uuid = UUID.fromString(s); - uuids.add(uuid); - } catch (Exception ignored) { - MainUtil.sendMessage(player, - Captions.PREFIX + "Invalid playerdata: " + current); - } - } - } - File playersFolder = new File(worldName + File.separator + "players"); - dat = playersFolder.list(new DatFileFilter()); - if (dat != null) { - for (String current : dat) { - names.add(current.replaceAll(".dat$", "")); - } - } - } - - MainUtil.sendMessage(player, "&7 - Populating map"); - UUID uuid2; - UUIDWrapper wrapper = new DefaultUUIDWrapper(); - for (UUID uuid : uuids) { - try { - OfflinePlotPlayer op = wrapper.getOfflinePlayer(uuid); - uuid = currentUUIDWrapper.getUUID(op); - uuid2 = newWrapper.getUUID(op); - if (!uuid.equals(uuid2) && !uCMap.containsKey(uuid) && !uCReverse - .containsKey(uuid2)) { - uCMap.put(uuid, uuid2); - uCReverse.put(uuid2, uuid); - } - } catch (Throwable ignored) { - MainUtil.sendMessage(player, - Captions.PREFIX + "&6Invalid playerdata: " + uuid.toString() + ".dat"); - } - } - for (String name : names) { - UUID uuid = currentUUIDWrapper.getUUID(name); - uuid2 = newWrapper.getUUID(name); - if (!uuid.equals(uuid2)) { - uCMap.put(uuid, uuid2); - uCReverse.put(uuid2, uuid); - } - } - if (uCMap.isEmpty()) { - MainUtil.sendMessage(player, "&c - Error! Attempting to repopulate"); - for (OfflinePlotPlayer op : currentUUIDWrapper.getOfflinePlayers()) { - if (op.getLastPlayed() != 0) { - // String name = op.getPluginName(); - // StringWrapper wrap = new StringWrapper(name); - UUID uuid = currentUUIDWrapper.getUUID(op); - uuid2 = newWrapper.getUUID(op); - if (!uuid.equals(uuid2)) { - uCMap.put(uuid, uuid2); - uCReverse.put(uuid2, uuid); - } - } - } - if (uCMap.isEmpty()) { - MainUtil.sendMessage(player, "&cError. Failed to collect UUIDs!"); - return false; - } else { - MainUtil.sendMessage(player, "&a - Successfully repopulated"); - } - } - - MainUtil.sendMessage(player, "&7 - Replacing cache"); - TaskManager.runTaskAsync(() -> { - for (Entry entry : uCMap.entrySet()) { - String name = UUIDHandler.getName(entry.getKey()); - if (name != null) { - UUIDHandler.add(new StringWrapper(name), entry.getValue()); - } - } - - MainUtil.sendMessage(player, "&7 - Scanning for applicable files (uuids.txt)"); - - File file = new File(PlotSquared.get().IMP.getDirectory(), "uuids.txt"); - if (file.exists()) { - try { - List lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8); - for (String line : lines) { - try { - line = line.trim(); - if (line.isEmpty()) { - continue; - } - line = line.replaceAll("[\\|][0-9]+[\\|][0-9]+[\\|]", ""); - String[] split = line.split("\\|"); - String name = split[0]; - if (name.isEmpty() || name.length() > 16 || !StringMan - .isAlphanumericUnd(name)) { - continue; - } - UUID old = currentUUIDWrapper.getUUID(name); - if (old == null) { - continue; - } - UUID now = newWrapper.getUUID(name); - UUIDHandler.add(new StringWrapper(name), now); - uCMap.put(old, now); - uCReverse.put(now, old); - } catch (Exception e2) { - e2.printStackTrace(); - } - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - MainUtil.sendMessage(player, "&7 - Replacing wrapper"); - UUIDHandler.setUUIDWrapper(newWrapper); - - MainUtil.sendMessage(player, "&7 - Updating plot objects"); - - for (Plot plot : PlotSquared.get().getPlots()) { - UUID value = uCMap.get(plot.getOwnerAbs()); - if (value != null) { - plot.setOwnerAbs(value); - } - plot.getTrusted().clear(); - plot.getMembers().clear(); - plot.getDenied().clear(); - } - - MainUtil.sendMessage(player, "&7 - Deleting database"); - boolean result = DBFunc.deleteTables(); - - MainUtil.sendMessage(player, "&7 - Creating tables"); - - try { - DBFunc.createTables(); - if (!result) { - MainUtil.sendMessage(player, "&cConversion failed! Attempting recovery"); - for (Plot plot : PlotSquared.get().getPlots()) { - UUID value = uCReverse.get(plot.getOwnerAbs()); - if (value != null) { - plot.setOwnerAbs(value); - } - } - DBFunc.createPlotsAndData(new ArrayList<>(PlotSquared.get().getPlots()), - () -> MainUtil.sendMessage(player, "&6Recovery was successful!")); - return; - } - } catch (Exception e) { - e.printStackTrace(); - return; - } - - if (newWrapper instanceof OfflineUUIDWrapper) { - PlotSquared.get().worlds.set("UUID.force-lowercase", false); - PlotSquared.get().worlds.set("UUID.offline", true); - } else if (newWrapper instanceof DefaultUUIDWrapper) { - PlotSquared.get().worlds.set("UUID.force-lowercase", false); - PlotSquared.get().worlds.set("UUID.offline", false); - } - try { - PlotSquared.get().worlds.save(PlotSquared.get().worldsFile); - } catch (IOException ignored) { - MainUtil.sendMessage(player, - "Could not save configuration. It will need to be manual set!"); - } - - MainUtil.sendMessage(player, "&7 - Populating tables"); - - TaskManager.runTaskAsync(() -> { - ArrayList plots = new ArrayList<>(PlotSquared.get().getPlots()); - DBFunc.createPlotsAndData(plots, - () -> MainUtil.sendMessage(player, "&aConversion complete!")); - }); - - MainUtil.sendMessage(player, "&aIt is now safe for players to join"); - MainUtil.sendMessage(player, - "&cConversion is still in progress, you will be notified when it is complete"); - }); - return true; - } -} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java index 6c7e4c9eb..2ff395c52 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java @@ -31,8 +31,11 @@ import com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent; import com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent; import com.destroystokyo.paper.event.entity.SlimePathfindEvent; import com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent; +import com.destroystokyo.paper.event.server.AsyncTabCompleteEvent; import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.command.Command; +import com.plotsquared.core.command.MainCommand; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.location.Location; @@ -56,6 +59,13 @@ import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.projectiles.ProjectileSource; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import java.util.regex.Pattern; + /** * Events specific to Paper. Some toit nups here */ @@ -306,4 +316,42 @@ public class PaperListener implements Listener { event.setCancelled(true); } } + + @EventHandler public void onAsyncTabCompletion(final AsyncTabCompleteEvent event) { + PlotSquared.debug("ASYNC COMPLETION"); + String buffer = event.getBuffer(); + if (!(event.getSender() instanceof Player)) { + return; + } + if ((!event.isCommand() && !buffer.startsWith("/")) || buffer.indexOf(' ') == -1) { + return; + } + if (buffer.startsWith("/")) { + buffer = buffer.substring(1); + } + final String[] unprocessedArgs = buffer.split(Pattern.quote(" ")); + if (unprocessedArgs.length == 1) { + return; // We don't do anything in this case + } else if (!Arrays.asList("plots", "p", "plotsquared", "plot2", "p2", "ps", "2", "plotme", "plotz", "ap") + .contains(unprocessedArgs[0].toLowerCase(Locale.ENGLISH))) { + return; + } + final String[] args = new String[unprocessedArgs.length - 1]; + System.arraycopy(unprocessedArgs, 1, args, 0, args.length); + try { + final PlotPlayer player = BukkitUtil.getPlayer((Player) event.getSender()); + final Collection objects = MainCommand.getInstance().tab(player, args, buffer.endsWith(" ")); + if (objects == null) { + return; + } + final List result = new ArrayList<>(); + for (final com.plotsquared.core.command.Command o : objects) { + result.add(o.toString()); + } + event.setCompletions(result); + event.setHandled(true); + PlotSquared.debug("ASYNC COMPLETION HANDLED"); + } catch (final Exception ignored) {} + } + } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java index 11215fcc8..ddcc15320 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java @@ -103,10 +103,8 @@ import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.PremiumVerification; import com.plotsquared.core.util.RegExUtil; -import com.plotsquared.core.util.StringWrapper; import com.plotsquared.core.util.entity.EntityCategories; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.world.block.BlockType; import io.papermc.lib.PaperLib; @@ -216,7 +214,6 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; -import java.util.Map.Entry; import java.util.Objects; import java.util.Set; import java.util.UUID; @@ -254,8 +251,8 @@ public class PlayerEvents extends PlotListener implements Listener { int x = bloc.getBlockX(); int z = bloc.getBlockZ(); int distance = Bukkit.getViewDistance() * 16; - for (Entry entry : UUIDHandler.getPlayers().entrySet()) { - PlotPlayer player = entry.getValue(); + + for (final PlotPlayer player : PlotSquared.imp().getPlayerManager().getPlayers()) { Location location = player.getLocation(); if (location.getWorld().equals(world)) { if (16 * Math.abs(location.getX() - x) / 16 > distance @@ -356,18 +353,18 @@ public class PlayerEvents extends PlotListener implements Listener { if (plot.isMerged()) { disable = true; for (UUID owner : plot.getOwners()) { - if (UUIDHandler.getPlayer(owner) != null) { + if (PlotSquared.imp().getPlayerManager().getPlayerIfExists(owner) != null) { disable = false; break; } } } else { - disable = UUIDHandler.getPlayer(plot.guessOwner()) == null; + disable = PlotSquared.imp().getPlayerManager().getPlayerIfExists(plot.getOwnerAbs()) == null; } } if (disable) { for (UUID trusted : plot.getTrusted()) { - if (UUIDHandler.getPlayer(trusted) != null) { + if (PlotSquared.imp().getPlayerManager().getPlayerIfExists(trusted) != null) { disable = false; break; } @@ -379,8 +376,8 @@ public class PlayerEvents extends PlotListener implements Listener { } } if (Settings.Redstone.DISABLE_UNOCCUPIED) { - for (Entry entry : UUIDHandler.getPlayers().entrySet()) { - if (plot.equals(entry.getValue().getCurrentPlot())) { + for (final PlotPlayer player : PlotSquared.imp().getPlayerManager().getPlayers()) { + if (plot.equals(player.getCurrentPlot())) { return; } } @@ -638,14 +635,8 @@ public class PlayerEvents extends PlotListener implements Listener { @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) public void onConnect(PlayerJoinEvent event) { final Player player = event.getPlayer(); - UUIDHandler.getPlayers().remove(player.getName()); BukkitUtil.removePlayer(player.getName()); final PlotPlayer pp = BukkitUtil.getPlayer(player); - // Now - String name = pp.getName(); - StringWrapper sw = new StringWrapper(name); - UUID uuid = pp.getUUID(); - UUIDHandler.add(sw, uuid); Location location = pp.getLocation(); PlotArea area = location.getPlotArea(); @@ -951,8 +942,7 @@ public class PlayerEvents extends PlotListener implements Listener { Set recipients = event.getRecipients(); recipients.clear(); Set spies = new HashSet<>(); - for (Entry entry : UUIDHandler.getPlayers().entrySet()) { - PlotPlayer pp = entry.getValue(); + for (final PlotPlayer pp : PlotSquared.imp().getPlayerManager().getPlayers()) { if (pp.getAttribute("chatspy")) { spies.add(((BukkitPlayer) pp).player); } else { @@ -2876,7 +2866,7 @@ public class PlayerEvents extends PlotListener implements Listener { } return true; } else if (dplot != null && (!dplot.equals(vplot) || Objects - .equals(dplot.guessOwner(), vplot.guessOwner()))) { + .equals(dplot.getOwnerAbs(), vplot.getOwnerAbs()))) { return vplot != null && vplot.getFlag(PveFlag.class); } //disable the firework damage. too much of a headache to support at the moment. diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java b/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java index bf2a7a8b9..f8a155d21 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java @@ -25,9 +25,9 @@ */ package com.plotsquared.bukkit.placeholder; +import com.plotsquared.core.PlotSquared; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; -import com.plotsquared.core.util.uuid.UUIDHandler; import me.clip.placeholderapi.PlaceholderAPIPlugin; import me.clip.placeholderapi.expansion.PlaceholderExpansion; import org.bukkit.Bukkit; @@ -62,7 +62,7 @@ public class Placeholders extends PlaceholderExpansion { } @Override public String onPlaceholderRequest(Player p, String identifier) { - final PlotPlayer pl = PlotPlayer.get(p.getName()); + final PlotPlayer pl = PlotSquared.imp().getPlayerManager().getPlayerIfExists(p.getUniqueId()); if (pl == null) { return ""; @@ -122,7 +122,8 @@ public class Placeholders extends PlaceholderExpansion { if (uid == null) { return ""; } - String name = UUIDHandler.getName(uid); + + String name = PlotSquared.get().getImpromptuUUIDPipeline() .getSingle(uid, 5L); if (name != null) { return name; diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java index 854cc6ec0..d2e7930fa 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java @@ -35,7 +35,6 @@ import com.plotsquared.core.plot.PlotWeather; import com.plotsquared.core.util.EconHandler; import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.StringMan; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.world.item.ItemType; @@ -97,10 +96,7 @@ public class BukkitPlayer extends PlotPlayer { } @NotNull @Override public UUID getUUID() { - if (this.uuid == null) { - this.uuid = UUIDHandler.getUUID(this); - } - return this.uuid; + return this.player.getUniqueId(); } @Override public long getLastPlayed() { diff --git a/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDWrapper.java b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayerManager.java similarity index 71% rename from Core/src/main/java/com/plotsquared/core/util/uuid/UUIDWrapper.java rename to Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayerManager.java index b2e8e0227..6e628a8a7 100644 --- a/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDWrapper.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayerManager.java @@ -23,25 +23,27 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.plotsquared.core.util.uuid; +package com.plotsquared.bukkit.player; -import com.plotsquared.core.player.OfflinePlotPlayer; import com.plotsquared.core.player.PlotPlayer; +import com.plotsquared.core.util.PlayerManager; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import java.util.UUID; -public interface UUIDWrapper { +/** + * Player manager providing {@link BukkitPlayer Bukkit players} + */ +public class BukkitPlayerManager extends PlayerManager { - @NotNull UUID getUUID(PlotPlayer player); + @Override @NotNull public PlotPlayer createPlayer(@NotNull final UUID uuid) { + final Player player = Bukkit.getPlayer(uuid); + if (player == null || !player.isOnline()) { + throw new NoSuchPlayerException(uuid); + } + return new BukkitPlayer(player); + } - UUID getUUID(OfflinePlotPlayer player); - - UUID getUUID(String name); - - OfflinePlotPlayer getOfflinePlayer(UUID uuid); - - OfflinePlotPlayer getOfflinePlayer(String name); - - OfflinePlotPlayer[] getOfflinePlayers(); } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java index 23fd8937b..8ba3caa9b 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java @@ -39,7 +39,6 @@ import com.plotsquared.core.util.StringComparison; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.math.BlockVector2; @@ -268,15 +267,7 @@ public class BukkitUtil extends WorldUtil { if (player == lastPlayer) { return lastPlotPlayer; } - final String name = player.getName(); - final PlotPlayer plotPlayer = UUIDHandler.getPlayer(name); - if (plotPlayer != null) { - return plotPlayer; - } - lastPlotPlayer = new BukkitPlayer(player); - UUIDHandler.getPlayers().put(name, lastPlotPlayer); - lastPlayer = player; - return lastPlotPlayer; + return PlotSquared.imp().getPlayerManager().getPlayer(player.getUniqueId()); } public static Location getLocation(@NonNull final org.bukkit.Location location) { diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/SendChunk.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/SendChunk.java deleted file mode 100644 index 7a920fc8b..000000000 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/SendChunk.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * PlotSquared plot management system for Minecraft - * Copyright (C) 2020 IntellectualSites - * - * 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, see . - */ -package com.plotsquared.bukkit.util; - -import com.plotsquared.bukkit.player.BukkitPlayer; -import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.location.Location; -import com.plotsquared.core.player.PlotPlayer; -import com.plotsquared.core.plot.Plot; -import com.plotsquared.core.util.ReflectionUtils.RefClass; -import com.plotsquared.core.util.ReflectionUtils.RefConstructor; -import com.plotsquared.core.util.ReflectionUtils.RefField; -import com.plotsquared.core.util.ReflectionUtils.RefMethod; -import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; -import com.sk89q.worldedit.math.BlockVector2; -import io.papermc.lib.PaperLib; -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -import org.bukkit.World; -import org.bukkit.entity.Player; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map.Entry; - -import static com.plotsquared.core.util.ReflectionUtils.getRefClass; - -/** - * An utility that can be used to send chunks, rather than using bukkit code - * to do so (uses heavy NMS). - */ -public class SendChunk { - - private final RefMethod methodGetHandlePlayer; - private final RefMethod methodGetHandleChunk; - private final RefConstructor mapChunk; - private final RefField connection; - private final RefMethod send; - private final RefMethod methodInitLighting; - - /** - * Constructor. - */ - public SendChunk() throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException { - RefClass classCraftPlayer = getRefClass("{cb}.entity.CraftPlayer"); - this.methodGetHandlePlayer = classCraftPlayer.getMethod("getHandle"); - RefClass classCraftChunk = getRefClass("{cb}.CraftChunk"); - this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle"); - RefClass classChunk = getRefClass("{nms}.Chunk"); - this.methodInitLighting = classChunk.getMethod("initLighting"); - RefClass classMapChunk = getRefClass("{nms}.PacketPlayOutMapChunk"); - this.mapChunk = classMapChunk.getConstructor(classChunk.getRealClass(), int.class); - RefClass classEntityPlayer = getRefClass("{nms}.EntityPlayer"); - this.connection = classEntityPlayer.getField("playerConnection"); - RefClass classPacket = getRefClass("{nms}.Packet"); - RefClass classConnection = getRefClass("{nms}.PlayerConnection"); - this.send = classConnection.getMethod("sendPacket", classPacket.getRealClass()); - } - - public void sendChunk(Collection input) { - HashSet chunks = new HashSet<>(input); - HashMap> map = new HashMap<>(); - int view = Bukkit.getServer().getViewDistance(); - for (Chunk chunk : chunks) { - String world = chunk.getWorld().getName(); - ArrayList list = map.computeIfAbsent(world, k -> new ArrayList<>()); - list.add(chunk); - Object c = this.methodGetHandleChunk.of(chunk).call(); - this.methodInitLighting.of(c).call(); - } - for (Entry entry : UUIDHandler.getPlayers().entrySet()) { - PlotPlayer pp = entry.getValue(); - Plot plot = pp.getCurrentPlot(); - Location location = null; - String world; - if (plot != null) { - world = plot.getWorldName(); - } else { - location = pp.getLocation(); - world = location.getWorld(); - } - ArrayList list = map.get(world); - if (list == null) { - continue; - } - if (location == null) { - location = pp.getLocation(); - } - int chunkX = location.getX() >> 4; - int chunkZ = location.getZ() >> 4; - Player player = ((BukkitPlayer) pp).player; - Object entity = this.methodGetHandlePlayer.of(player).call(); - - for (Chunk chunk : list) { - int dx = Math.abs(chunkX - chunk.getX()); - int dz = Math.abs(chunkZ - chunk.getZ()); - if ((dx > view) || (dz > view)) { - continue; - } - Object c = this.methodGetHandleChunk.of(chunk).call(); - chunks.remove(chunk); - Object con = this.connection.of(entity).get(); - Object packet = null; - try { - packet = this.mapChunk.create(c, 65535); - } catch (Exception ignored) { - } - if (packet == null) { - PlotSquared.debug("Error with PacketPlayOutMapChunk reflection."); - } - this.send.of(con).call(packet); - } - } - for (final Chunk chunk : chunks) { - TaskManager.runTask(() -> { - try { - chunk.unload(true); - } catch (Throwable ignored) { - String worldName = chunk.getWorld().getName(); - PlotSquared.debug( - "$4Could not save chunk: " + worldName + ';' + chunk.getX() + ";" + chunk - .getZ()); - PlotSquared.debug("$3 - $4File may be open in another process (e.g. MCEdit)"); - PlotSquared.debug("$3 - $4" + worldName + "/level.dat or " + worldName - + "/level_old.dat may be corrupt (try repairing or removing these)"); - } - }); - } - } - - public void sendChunk(String worldName, Collection chunkLocations) { - World myWorld = Bukkit.getWorld(worldName); - ArrayList chunks = new ArrayList<>(); - for (BlockVector2 loc : chunkLocations) { - if (myWorld.isChunkLoaded(loc.getX(), loc.getZ())) { - PaperLib.getChunkAtAsync(myWorld, loc.getX(), loc.getZ()).thenAccept(chunks::add); - } - } - sendChunk(chunks); - } -} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/DatFileFilter.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/DatFileFilter.java deleted file mode 100644 index 65657fbff..000000000 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/DatFileFilter.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * PlotSquared plot management system for Minecraft - * Copyright (C) 2020 IntellectualSites - * - * 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, see . - */ -package com.plotsquared.bukkit.util.uuid; - -import java.io.File; -import java.io.FilenameFilter; - -public class DatFileFilter implements FilenameFilter { - - @Override public boolean accept(File dir, String name) { - return name.endsWith(".dat"); - } -} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/FileUUIDHandler.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/FileUUIDHandler.java deleted file mode 100644 index c5620ffa1..000000000 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/FileUUIDHandler.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * PlotSquared plot management system for Minecraft - * Copyright (C) 2020 IntellectualSites - * - * 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, see . - */ -package com.plotsquared.bukkit.util.uuid; - -import com.google.common.collect.HashBiMap; -import com.google.common.collect.Sets; -import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.configuration.Captions; -import com.plotsquared.core.configuration.Settings; -import com.plotsquared.core.player.OfflinePlotPlayer; -import com.plotsquared.core.plot.expiration.ExpireManager; -import com.plotsquared.core.util.StringMan; -import com.plotsquared.core.util.StringWrapper; -import com.plotsquared.core.util.task.RunnableVal; -import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; -import com.plotsquared.core.util.uuid.UUIDHandlerImplementation; -import com.plotsquared.core.util.uuid.UUIDWrapper; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.NBTInputStream; -import com.sk89q.jnbt.Tag; -import org.bukkit.Bukkit; -import org.bukkit.World; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.zip.GZIPInputStream; - -public class FileUUIDHandler extends UUIDHandlerImplementation { - - public FileUUIDHandler(UUIDWrapper wrapper) { - super(wrapper); - } - - @Override public boolean startCaching(Runnable whenDone) { - return super.startCaching(whenDone) && cache(whenDone); - } - - private Tag readTag(File file) throws IOException { - // Don't chain the creation of the GZIP stream and the NBT stream, because their - // constructors may throw an IOException. - try (BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file)); - GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream); - NBTInputStream nbtInputStream = new NBTInputStream(gzipInputStream)) { - return nbtInputStream.readNamedTag().getTag(); - } - } - - public boolean cache(final Runnable whenDone) { - final File container = Bukkit.getWorldContainer(); - List worlds = Bukkit.getWorlds(); - final String world; - if (worlds.isEmpty()) { - world = "world"; - } else { - world = worlds.get(0).getName(); - } - TaskManager.runTaskAsync(() -> { - PlotSquared.debug(Captions.PREFIX + "Starting player data caching for: " + world); - File uuidFile = new File(PlotSquared.get().IMP.getDirectory(), "uuids.txt"); - if (uuidFile.exists()) { - try { - List lines = - Files.readAllLines(uuidFile.toPath(), StandardCharsets.UTF_8); - for (String line : lines) { - try { - line = line.trim(); - if (line.isEmpty()) { - continue; - } - line = line.replaceAll("[\\|][0-9]+[\\|][0-9]+[\\|]", ""); - String[] split = line.split("\\|"); - String name = split[0]; - if (name.isEmpty() || (name.length() > 16) || !StringMan - .isAlphanumericUnd(name)) { - continue; - } - UUID uuid = FileUUIDHandler.this.uuidWrapper.getUUID(name); - if (uuid == null) { - continue; - } - UUIDHandler.add(new StringWrapper(name), uuid); - } catch (Exception e2) { - e2.printStackTrace(); - } - } - } catch (IOException e) { - e.printStackTrace(); - } - } - HashBiMap toAdd = HashBiMap.create(new HashMap<>()); - if (Settings.UUID.NATIVE_UUID_PROVIDER) { - HashSet all = UUIDHandler.getAllUUIDS(); - PlotSquared.debug("Fast mode UUID caching enabled!"); - File playerDataFolder = new File(container, world + File.separator + "playerdata"); - String[] dat = playerDataFolder.list(new DatFileFilter()); - boolean check = all.isEmpty(); - if (dat != null) { - for (String current : dat) { - String s = current.replaceAll(".dat$", ""); - try { - UUID uuid = UUID.fromString(s); - if (check || all.remove(uuid)) { - File file = new File(playerDataFolder, current); - CompoundTag compound = (CompoundTag) readTag(file); - if (!compound.containsKey("bukkit")) { - PlotSquared.debug("ERROR: Player data (" + uuid.toString() - + ".dat) does not contain the the key \"bukkit\""); - } else { - Map compoundMap = compound.getValue(); - CompoundTag bukkit = (CompoundTag) compoundMap.get("bukkit"); - Map bukkitMap = bukkit.getValue(); - String name = - (String) bukkitMap.get("lastKnownName").getValue(); - long last = (long) bukkitMap.get("lastPlayed").getValue(); - long first = (long) bukkitMap.get("firstPlayed").getValue(); - if (ExpireManager.IMP != null) { - ExpireManager.IMP.storeDate(uuid, last); - ExpireManager.IMP.storeAccountAge(uuid, last - first); - } - toAdd.put(new StringWrapper(name), uuid); - } - } - } catch (Exception e) { - e.printStackTrace(); - PlotSquared.debug(Captions.PREFIX + "Invalid playerdata: " + current); - } - } - } - add(toAdd); - if (all.isEmpty()) { - if (whenDone != null) { - whenDone.run(); - } - return; - } else { - PlotSquared.debug( - "Failed to cache: " + all.size() + " uuids - slowly processing all files"); - } - } - HashSet worlds1 = Sets.newHashSet(world, "world"); - HashSet uuids = new HashSet<>(); - HashSet names = new HashSet<>(); - File playerDataFolder = null; - for (String worldName : worlds1) { - // Getting UUIDs - playerDataFolder = new File(container, worldName + File.separator + "playerdata"); - String[] dat = playerDataFolder.list(new DatFileFilter()); - if ((dat != null) && (dat.length != 0)) { - for (String current : dat) { - String s = current.replaceAll(".dat$", ""); - try { - UUID uuid = UUID.fromString(s); - uuids.add(uuid); - } catch (Exception ignored) { - PlotSquared.debug(Captions.PREFIX + "Invalid PlayerData: " + current); - } - } - break; - } - // Getting names - File playersFolder = new File(worldName + File.separator + "players"); - dat = playersFolder.list(new DatFileFilter()); - if ((dat != null) && (dat.length != 0)) { - for (String current : dat) { - names.add(current.replaceAll(".dat$", "")); - } - break; - } - } - for (UUID uuid : uuids) { - try { - File file = - new File(playerDataFolder + File.separator + uuid.toString() + ".dat"); - if (!file.exists()) { - continue; - } - CompoundTag compound = (CompoundTag) readTag(file); - if (!compound.containsKey("bukkit")) { - PlotSquared.debug("ERROR: Player data (" + uuid.toString() - + ".dat) does not contain the the key \"bukkit\""); - } else { - Map compoundMap = compound.getValue(); - CompoundTag bukkit = (CompoundTag) compoundMap.get("bukkit"); - Map bukkitMap = bukkit.getValue(); - String name = (String) bukkitMap.get("lastKnownName").getValue(); - StringWrapper wrap = new StringWrapper(name); - if (!toAdd.containsKey(wrap)) { - long last = (long) bukkitMap.get("lastPlayed").getValue(); - long first = (long) bukkitMap.get("firstPlayed").getValue(); - if (Settings.UUID.OFFLINE) { - if (Settings.UUID.FORCE_LOWERCASE && !name.toLowerCase() - .equals(name)) { - uuid = FileUUIDHandler.this.uuidWrapper.getUUID(name); - } else { - long most = (long) compoundMap.get("UUIDMost").getValue(); - long least = (long) compoundMap.get("UUIDLeast").getValue(); - uuid = new UUID(most, least); - } - } - if (ExpireManager.IMP != null) { - ExpireManager.IMP.storeDate(uuid, last); - ExpireManager.IMP.storeAccountAge(uuid, last - first); - } - toAdd.put(wrap, uuid); - } - } - } catch (Exception ignored) { - PlotSquared.debug( - Captions.PREFIX + "&6Invalid PlayerData: " + uuid.toString() + ".dat"); - } - } - for (String name : names) { - UUID uuid = FileUUIDHandler.this.uuidWrapper.getUUID(name); - StringWrapper nameWrap = new StringWrapper(name); - toAdd.put(nameWrap, uuid); - } - - if (getUUIDMap().isEmpty()) { - for (OfflinePlotPlayer offlinePlotPlayer : FileUUIDHandler.this.uuidWrapper - .getOfflinePlayers()) { - long last = offlinePlotPlayer.getLastPlayed(); - if (last != 0) { - String name = offlinePlotPlayer.getName(); - StringWrapper wrap = new StringWrapper(name); - if (!toAdd.containsKey(wrap)) { - UUID uuid = FileUUIDHandler.this.uuidWrapper.getUUID(offlinePlotPlayer); - if (toAdd.containsValue(uuid)) { - StringWrapper duplicate = toAdd.inverse().get(uuid); - PlotSquared.debug( - "The UUID: " + uuid.toString() + " is already mapped to " - + duplicate - + "\n It cannot be added to the Map with a key of " + wrap); - } - toAdd.putIfAbsent(wrap, uuid); - if (ExpireManager.IMP != null) { - ExpireManager.IMP.storeDate(uuid, last); - } - } - } - } - } - add(toAdd); - if (whenDone != null) { - whenDone.run(); - } - }); - return true; - } - - @Override public void fetchUUID(final String name, final RunnableVal ifFetch) { - TaskManager.runTaskAsync(() -> { - ifFetch.value = FileUUIDHandler.this.uuidWrapper.getUUID(name); - TaskManager.runTask(ifFetch); - }); - } -} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/LowerOfflineUUIDWrapper.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/LowerOfflineUUIDWrapper.java deleted file mode 100644 index ad2be7ce3..000000000 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/LowerOfflineUUIDWrapper.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * PlotSquared plot management system for Minecraft - * Copyright (C) 2020 IntellectualSites - * - * 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, see . - */ -package com.plotsquared.bukkit.util.uuid; - -import com.google.common.base.Charsets; -import com.plotsquared.core.player.OfflinePlotPlayer; -import com.plotsquared.core.player.PlotPlayer; -import org.bukkit.OfflinePlayer; -import org.jetbrains.annotations.NotNull; - -import java.util.Objects; -import java.util.UUID; - -public class LowerOfflineUUIDWrapper extends OfflineUUIDWrapper { - - @NotNull @Override public UUID getUUID(PlotPlayer player) { - return UUID.nameUUIDFromBytes( - ("OfflinePlayer:" + player.getName().toLowerCase()).getBytes(Charsets.UTF_8)); - } - - @Override public UUID getUUID(OfflinePlotPlayer player) { - return UUID.nameUUIDFromBytes( - ("OfflinePlayer:" + player.getName().toLowerCase()).getBytes(Charsets.UTF_8)); - } - - @Override public UUID getUUID(OfflinePlayer player) { - return UUID.nameUUIDFromBytes( - ("OfflinePlayer:" + Objects.requireNonNull(player.getName()).toLowerCase()) - .getBytes(Charsets.UTF_8)); - } - - @Override public UUID getUUID(String name) { - return UUID - .nameUUIDFromBytes(("OfflinePlayer:" + name.toLowerCase()).getBytes(Charsets.UTF_8)); - } - -} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/OfflineUUIDWrapper.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/OfflineUUIDWrapper.java deleted file mode 100644 index 405fb940d..000000000 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/OfflineUUIDWrapper.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * PlotSquared plot management system for Minecraft - * Copyright (C) 2020 IntellectualSites - * - * 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, see . - */ -package com.plotsquared.bukkit.util.uuid; - -import com.google.common.base.Charsets; -import com.google.common.collect.BiMap; -import com.plotsquared.bukkit.player.BukkitOfflinePlayer; -import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.player.OfflinePlotPlayer; -import com.plotsquared.core.player.PlotPlayer; -import com.plotsquared.core.util.StringWrapper; -import com.plotsquared.core.util.uuid.UUIDHandler; -import com.plotsquared.core.util.uuid.UUIDWrapper; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.Server; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Collection; -import java.util.UUID; - -public class OfflineUUIDWrapper implements UUIDWrapper { - - private final Object[] arg = new Object[0]; - private Method getOnline = null; - - public OfflineUUIDWrapper() { - try { - this.getOnline = Server.class.getMethod("getOnlinePlayers"); - } catch (NoSuchMethodException | SecurityException e) { - e.printStackTrace(); - } - } - - @NotNull @Override public UUID getUUID(PlotPlayer player) { - return UUID - .nameUUIDFromBytes(("OfflinePlayer:" + player.getName()).getBytes(Charsets.UTF_8)); - } - - @Override public UUID getUUID(OfflinePlotPlayer player) { - return UUID - .nameUUIDFromBytes(("OfflinePlayer:" + player.getName()).getBytes(Charsets.UTF_8)); - } - - public UUID getUUID(OfflinePlayer player) { - return UUID - .nameUUIDFromBytes(("OfflinePlayer:" + player.getName()).getBytes(Charsets.UTF_8)); - } - - @Override public OfflinePlotPlayer getOfflinePlayer(UUID uuid) { - BiMap map = UUIDHandler.getUuidMap().inverse(); - String name = null; - if (map.containsKey(uuid)) { - name = map.get(uuid).value; - } - if (name != null) { - OfflinePlayer op = Bukkit.getOfflinePlayer(name); - if (op.hasPlayedBefore()) { - return new BukkitOfflinePlayer(op); - } - } - for (OfflinePlayer player : Bukkit.getOfflinePlayers()) { - if (getUUID(player).equals(uuid)) { - return new BukkitOfflinePlayer(player); - } - } - return null; - } - - public Player[] getOnlinePlayers() { - if (this.getOnline == null) { - Collection onlinePlayers = Bukkit.getOnlinePlayers(); - return onlinePlayers.toArray(new Player[0]); - } - try { - Object players = this.getOnline.invoke(Bukkit.getServer(), this.arg); - if (players instanceof Player[]) { - return (Player[]) players; - } else { - @SuppressWarnings("unchecked") Collection p = - (Collection) players; - return p.toArray(new Player[0]); - } - } catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException ignored) { - PlotSquared.debug("Failed to resolve online players"); - this.getOnline = null; - Collection onlinePlayers = Bukkit.getOnlinePlayers(); - return onlinePlayers.toArray(new Player[0]); - } - } - - @Override public UUID getUUID(String name) { - return UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)); - } - - @Override public OfflinePlotPlayer[] getOfflinePlayers() { - OfflinePlayer[] ops = Bukkit.getOfflinePlayers(); - return Arrays.stream(ops).map(BukkitOfflinePlayer::new).toArray(BukkitOfflinePlayer[]::new); - } - - @Override public OfflinePlotPlayer getOfflinePlayer(String name) { - return new BukkitOfflinePlayer(Bukkit.getOfflinePlayer(name)); - } -} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/SQLUUIDHandler.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/SQLUUIDHandler.java deleted file mode 100644 index a08956369..000000000 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/SQLUUIDHandler.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * PlotSquared plot management system for Minecraft - * Copyright (C) 2020 IntellectualSites - * - * 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, see . - */ -package com.plotsquared.bukkit.util.uuid; - -import com.google.common.collect.HashBiMap; -import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.configuration.Captions; -import com.plotsquared.core.configuration.Settings; -import com.plotsquared.core.database.SQLite; -import com.plotsquared.core.util.MainUtil; -import com.plotsquared.core.util.StringWrapper; -import com.plotsquared.core.util.task.RunnableVal; -import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; -import com.plotsquared.core.util.uuid.UUIDHandlerImplementation; -import com.plotsquared.core.util.uuid.UUIDWrapper; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayDeque; -import java.util.Collections; -import java.util.HashMap; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -public class SQLUUIDHandler extends UUIDHandlerImplementation { - - final int MAX_REQUESTS = 500; - private final String PROFILE_URL = - "https://sessionserver.mojang.com/session/minecraft/profile/"; - private final JSONParser jsonParser = new JSONParser(); - private final SQLite sqlite; - - public SQLUUIDHandler(UUIDWrapper wrapper) { - super(wrapper); - this.sqlite = - new SQLite(MainUtil.getFile(PlotSquared.get().IMP.getDirectory(), "usercache.db")); - try { - this.sqlite.openConnection(); - } catch (ClassNotFoundException | SQLException e) { - e.printStackTrace(); - } - - try (PreparedStatement stmt = getConnection().prepareStatement( - "CREATE TABLE IF NOT EXISTS `usercache` (uuid VARCHAR(32) NOT NULL, username VARCHAR(32) NOT NULL, PRIMARY KEY (uuid, username))")) { - stmt.execute(); - } catch (SQLException e) { - e.printStackTrace(); - } - startCaching(null); - } - - private Connection getConnection() { - synchronized (this.sqlite) { - return this.sqlite.getConnection(); - } - } - - @Override public boolean startCaching(final Runnable whenDone) { - if (!super.startCaching(whenDone)) { - return false; - } - TaskManager.runTaskAsync(() -> { - try { - HashBiMap toAdd = HashBiMap.create(new HashMap<>()); - try (PreparedStatement statement = getConnection() - .prepareStatement("SELECT `uuid`, `username` FROM `usercache`"); - ResultSet resultSet = statement.executeQuery()) { - while (resultSet.next()) { - StringWrapper username = new StringWrapper(resultSet.getString("username")); - UUID uuid = UUID.fromString(resultSet.getString("uuid")); - toAdd.put(new StringWrapper(username.value), uuid); - } - } - add(toAdd); - // This should be called as long as there are some unknown plots - final ArrayDeque toFetch = new ArrayDeque<>(); - for (UUID u : UUIDHandler.getAllUUIDS()) { - if (!uuidExists(u)) { - toFetch.add(u); - } - } - if (toFetch.isEmpty()) { - if (whenDone != null) { - whenDone.run(); - } - return; - } - FileUUIDHandler fileHandler = new FileUUIDHandler(SQLUUIDHandler.this.uuidWrapper); - fileHandler.startCaching(() -> { - // If the file based UUID handler didn't cache it, then we can't cache offline mode - // Also, trying to cache based on files again, is useless as that's what the file based uuid cacher does - if (Settings.UUID.OFFLINE) { - if (whenDone != null) { - whenDone.run(); - } - return; - } - - TaskManager.runTaskAsync(() -> { - while (!toFetch.isEmpty()) { - try { - for (int i = 0; i < Math.min(MAX_REQUESTS, toFetch.size()); i++) { - UUID uuid = toFetch.pop(); - HttpURLConnection connection = (HttpURLConnection) new URL( - SQLUUIDHandler.this.PROFILE_URL + uuid.toString() - .replace("-", "")).openConnection(); - try (InputStream con = connection.getInputStream()) { - InputStreamReader reader = new InputStreamReader(con); - JSONObject response = - (JSONObject) SQLUUIDHandler.this.jsonParser - .parse(reader); - String name = (String) response.get("name"); - if (name != null) { - add(new StringWrapper(name), uuid); - } - } - connection.disconnect(); - } - } catch (IOException | ParseException e) { - PlotSquared.debug( - "Invalid response from Mojang: Some UUIDs will be cached later. (`unknown` until then or player joins)"); - } - try { - //Mojang allows requests every 10 minutes according to https://wiki.vg/Mojang_API - //15 Minutes is chosen here since system timers are not always precise - //and it should provide enough time where Mojang won't block requests. - TimeUnit.MINUTES.sleep(15); - } catch (InterruptedException e) { - e.printStackTrace(); - break; - } - } - if (whenDone != null) { - whenDone.run(); - } - }); - }); - } catch (SQLException e) { - throw new SQLUUIDHandlerException("Couldn't select :s", e); - } - }); - return true; - } - - @Override public void fetchUUID(final String name, final RunnableVal ifFetch) { - PlotSquared.debug(Captions.PREFIX + "UUID for '" + name - + "' was null. We'll cache this from the Mojang servers!"); - if (ifFetch == null) { - return; - } - TaskManager.runTaskAsync(() -> { - try { - URL url = new URL(SQLUUIDHandler.this.PROFILE_URL); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("POST"); - connection.setRequestProperty("Content-Type", "application/json"); - connection.setUseCaches(false); - connection.setDoInput(true); - connection.setDoOutput(true); - String body = JSONArray.toJSONString(Collections.singletonList(name)); - OutputStream stream = connection.getOutputStream(); - stream.write(body.getBytes()); - stream.flush(); - stream.close(); - JSONArray array = (JSONArray) SQLUUIDHandler.this.jsonParser - .parse(new InputStreamReader(connection.getInputStream())); - JSONObject jsonProfile = (JSONObject) array.get(0); - String id = (String) jsonProfile.get("id"); - String name1 = (String) jsonProfile.get("name"); - ifFetch.value = UUID.fromString( - id.substring(0, 8) + '-' + id.substring(8, 12) + '-' + id.substring(12, 16) - + '-' + id.substring(16, 20) + '-' + id.substring(20, 32)); - } catch (IOException | ParseException e) { - e.printStackTrace(); - } - TaskManager.runTask(ifFetch); - }); - } - - @Override public void handleShutdown() { - super.handleShutdown(); - try { - getConnection().close(); - } catch (SQLException e) { - throw new SQLUUIDHandlerException("Couldn't close database connection", e); - } - } - - /** - * This is useful for name changes - */ - @Override public void rename(final UUID uuid, final StringWrapper name) { - super.rename(uuid, name); - TaskManager.runTaskAsync(() -> { - try (PreparedStatement statement = getConnection() - .prepareStatement("UPDATE usercache SET `username`=? WHERE `uuid`=?")) { - statement.setString(1, name.value); - statement.setString(2, uuid.toString()); - statement.execute(); - PlotSquared.debug( - Captions.PREFIX + "Name change for '" + uuid + "' to '" + name.value + '\''); - } catch (SQLException e) { - e.printStackTrace(); - } - }); - } - - @Override public boolean add(final StringWrapper name, final UUID uuid) { - // Ignoring duplicates - if (super.add(name, uuid)) { - TaskManager.runTaskAsync(() -> { - try (PreparedStatement statement = getConnection() - .prepareStatement("REPLACE INTO usercache (`uuid`, `username`) VALUES(?, ?)")) { - statement.setString(1, uuid.toString()); - statement.setString(2, name.toString()); - statement.execute(); - PlotSquared - .debug(Captions.PREFIX + "&cAdded '&6" + uuid + "&c' - '&6" + name + "&c'"); - } catch (SQLException e) { - e.printStackTrace(); - } - }); - return true; - } - return false; - } - - private static class SQLUUIDHandlerException extends RuntimeException { - - SQLUUIDHandlerException(String s, Throwable c) { - super("SQLUUIDHandler caused an exception: " + s, c); - } - } -} diff --git a/Core/src/main/java/com/plotsquared/core/IPlotMain.java b/Core/src/main/java/com/plotsquared/core/IPlotMain.java index ed6694e01..2705d54c2 100644 --- a/Core/src/main/java/com/plotsquared/core/IPlotMain.java +++ b/Core/src/main/java/com/plotsquared/core/IPlotMain.java @@ -36,13 +36,13 @@ import com.plotsquared.core.util.ChunkManager; import com.plotsquared.core.util.EconHandler; import com.plotsquared.core.util.InventoryUtil; import com.plotsquared.core.util.PlatformWorldManager; +import com.plotsquared.core.util.PlayerManager; import com.plotsquared.core.util.RegionManager; import com.plotsquared.core.util.SchematicHandler; import com.plotsquared.core.util.SetupUtils; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.logger.ILogger; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandlerImplementation; import com.sk89q.worldedit.extension.platform.Actor; import org.jetbrains.annotations.NotNull; @@ -220,12 +220,6 @@ public interface IPlotMain extends ILogger { */ void setGenerator(String world); - /** - * Gets the {@link UUIDHandlerImplementation} which will cache and - * provide UUIDs. - */ - UUIDHandlerImplementation initUUIDHandler(); - /** * Gets the {@link InventoryUtil} class (used for implementation specific * inventory guis). @@ -285,6 +279,13 @@ public interface IPlotMain extends ILogger { * * @return World manager */ - @NotNull PlatformWorldManager getWorldManager(); + @NotNull PlatformWorldManager getWorldManager(); + + /** + * Get the player manager implementation for the platform + * + * @return Player manager + */ + @NotNull PlayerManager getPlayerManager(); } diff --git a/Core/src/main/java/com/plotsquared/core/PlotSquared.java b/Core/src/main/java/com/plotsquared/core/PlotSquared.java index bbb8b66bc..a19f167d7 100644 --- a/Core/src/main/java/com/plotsquared/core/PlotSquared.java +++ b/Core/src/main/java/com/plotsquared/core/PlotSquared.java @@ -79,11 +79,9 @@ import com.plotsquared.core.util.RegionManager; import com.plotsquared.core.util.SchematicHandler; import com.plotsquared.core.util.SetupUtils; import com.plotsquared.core.util.StringMan; -import com.plotsquared.core.util.StringWrapper; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.logger.ILogger; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.plotsquared.core.uuid.UUIDPipeline; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.math.BlockVector2; @@ -91,6 +89,7 @@ import com.sk89q.worldedit.regions.CuboidRegion; import lombok.Getter; import lombok.NonNull; import lombok.Setter; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.BufferedReader; @@ -259,15 +258,6 @@ public class PlotSquared { if (Settings.Enabled_Components.CHUNK_PROCESSOR) { this.IMP.registerChunkProcessor(); } - // create UUIDWrapper - UUIDHandler.implementation = this.IMP.initUUIDHandler(); - if (Settings.Enabled_Components.UUID_CACHE) { - startUuidCatching(); - } else { - // Start these separately - UUIDHandler.add(new StringWrapper("*"), DBFunc.EVERYONE); - startExpiryTasks(); - } // Create Event utility class eventDispatcher = new EventDispatcher(); // create Hybrid utility class @@ -392,11 +382,11 @@ public class PlotSquared { return PlotSquared.instance; } - public static IPlotMain imp() { - if (instance != null) { + @NotNull public static IPlotMain imp() { + if (instance != null && instance.IMP != null) { return instance.IMP; } - return null; + throw new IllegalStateException("Plot main implementation is missing"); } /** @@ -437,8 +427,7 @@ public class PlotSquared { private void startUuidCatching() { TaskManager.runTaskLater(() -> { debug("Starting UUID caching"); - UUIDHandler.startCaching(() -> { - UUIDHandler.add(new StringWrapper("*"), DBFunc.EVERYONE); + /*UUIDHandler.startCaching(() -> { forEachPlotRaw(plot -> { if (plot.hasOwner() && plot.temp != -1) { if (UUIDHandler.getName(plot.getOwnerAbs()) == null) { @@ -447,7 +436,8 @@ public class PlotSquared { } }); startExpiryTasks(); - }); + });*/ + // TODO: Re-implement }, 20); } @@ -973,7 +963,7 @@ public class PlotSquared { * @return Set of Plot */ public Set getPlots(String world, String player) { - final UUID uuid = UUIDHandler.getUUID(player, null); + final UUID uuid = this.impromptuUUIDPipeline.getSingle(player, 10L); return getPlots(world, uuid); } @@ -985,7 +975,7 @@ public class PlotSquared { * @return Set of Plot */ public Set getPlots(PlotArea area, String player) { - UUID uuid = UUIDHandler.getUUID(player, null); + final UUID uuid = this.impromptuUUIDPipeline.getSingle(player, 10L); return getPlots(area, uuid); } @@ -1018,7 +1008,10 @@ public class PlotSquared { * @param uuid the plot owner * @return Set of plot */ - public Set getPlots(String world, UUID uuid) { + public Set getPlots(String world, @Nullable UUID uuid) { + if (uuid == null) { + return Collections.emptySet(); + } final Set plots = getPlots(world).stream().filter(plot -> plot.hasOwner() && plot.isOwnerAbs(uuid)) .collect(Collectors.toSet()); @@ -1627,7 +1620,6 @@ public class PlotSquared { // Close the connection DBFunc.close(); - UUIDHandler.handleShutdown(); } catch (NullPointerException throwable) { throwable.printStackTrace(); PlotSquared.log("&cCould not close database connection!"); diff --git a/Core/src/main/java/com/plotsquared/core/api/PlotAPI.java b/Core/src/main/java/com/plotsquared/core/api/PlotAPI.java index 56e507873..3991643a3 100644 --- a/Core/src/main/java/com/plotsquared/core/api/PlotAPI.java +++ b/Core/src/main/java/com/plotsquared/core/api/PlotAPI.java @@ -38,8 +38,6 @@ import com.plotsquared.core.util.ChunkManager; import com.plotsquared.core.util.EventDispatcher; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.SchematicHandler; -import com.plotsquared.core.util.uuid.UUIDHandler; -import com.plotsquared.core.util.uuid.UUIDWrapper; import lombok.NoArgsConstructor; import java.util.Collections; @@ -138,17 +136,6 @@ import java.util.UUID; return GlobalBlockQueue.IMP; } - /** - * UUIDWrapper class has basic methods for getting UUIDS. It's recommended - * to use the UUIDHandler class instead. - * - * @return UUIDWrapper - * @see UUIDWrapper - */ - public UUIDWrapper getUUIDWrapper() { - return UUIDHandler.getUUIDWrapper(); - } - /** * SchematicHandler class contains methods related to pasting, reading * and writing schematics. diff --git a/Core/src/main/java/com/plotsquared/core/command/Add.java b/Core/src/main/java/com/plotsquared/core/command/Add.java index bc4905c68..32750f8d9 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Add.java +++ b/Core/src/main/java/com/plotsquared/core/command/Add.java @@ -36,7 +36,6 @@ import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; import java.util.Iterator; -import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -62,51 +61,64 @@ public class Add extends Command { .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_TRUST), Captions.NO_PLOT_PERMS); checkTrue(args.length == 1, Captions.COMMAND_SYNTAX, getUsage()); - final Set uuids = MainUtil.getUUIDsFromString(args[0]); - checkTrue(!uuids.isEmpty(), Captions.INVALID_PLAYER, args[0]); - Iterator iterator = uuids.iterator(); - int size = plot.getTrusted().size() + plot.getMembers().size(); - while (iterator.hasNext()) { - UUID uuid = iterator.next(); - if (uuid == DBFunc.EVERYONE && !( - Permissions.hasPermission(player, Captions.PERMISSION_TRUST_EVERYONE) || Permissions - .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_TRUST))) { - MainUtil.sendMessage(player, Captions.INVALID_PLAYER, MainUtil.getName(uuid)); - iterator.remove(); - continue; - } - if (plot.isOwner(uuid)) { - MainUtil.sendMessage(player, Captions.ALREADY_ADDED, MainUtil.getName(uuid)); - iterator.remove(); - continue; - } - if (plot.getMembers().contains(uuid)) { - MainUtil.sendMessage(player, Captions.ALREADY_ADDED, MainUtil.getName(uuid)); - iterator.remove(); - continue; - } - size += plot.getTrusted().contains(uuid) ? 0 : 1; - } - checkTrue(!uuids.isEmpty(), null); - checkTrue(size <= plot.getArea().getMaxPlotMembers() || Permissions - .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_TRUST), - Captions.PLOT_MAX_MEMBERS); - // Success - confirm.run(this, () -> { - for (UUID uuid : uuids) { - if (uuid != DBFunc.EVERYONE) { - if (!plot.removeTrusted(uuid)) { - if (plot.getDenied().contains(uuid)) { - plot.removeDenied(uuid); - } - } - } - plot.addMember(uuid); - PlotSquared.get().getEventDispatcher().callMember(player, plot, uuid, true); - MainUtil.sendMessage(player, Captions.MEMBER_ADDED); - } - }, null); - return CompletableFuture.completedFuture(true); + final CompletableFuture future = new CompletableFuture<>(); + MainUtil.getUUIDsFromString(args[0], (uuids, throwable) -> { + if (throwable != null) { + Captions.INVALID_PLAYER.send(player, args[0]); + future.completeExceptionally(throwable); + return; + } else { + try { + checkTrue(!uuids.isEmpty(), Captions.INVALID_PLAYER, args[0]); + Iterator iterator = uuids.iterator(); + int size = plot.getTrusted().size() + plot.getMembers().size(); + while (iterator.hasNext()) { + UUID uuid = iterator.next(); + if (uuid == DBFunc.EVERYONE && !( + Permissions.hasPermission(player, Captions.PERMISSION_TRUST_EVERYONE) || Permissions + .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_TRUST))) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, MainUtil.getName(uuid)); + iterator.remove(); + continue; + } + if (plot.isOwner(uuid)) { + MainUtil.sendMessage(player, Captions.ALREADY_ADDED, MainUtil.getName(uuid)); + iterator.remove(); + continue; + } + if (plot.getMembers().contains(uuid)) { + MainUtil.sendMessage(player, Captions.ALREADY_ADDED, MainUtil.getName(uuid)); + iterator.remove(); + continue; + } + size += plot.getTrusted().contains(uuid) ? 0 : 1; + } + checkTrue(!uuids.isEmpty(), null); + checkTrue(size <= plot.getArea().getMaxPlotMembers() || Permissions.hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_TRUST), + Captions.PLOT_MAX_MEMBERS); + // Success + confirm.run(this, () -> { + for (UUID uuid : uuids) { + if (uuid != DBFunc.EVERYONE) { + if (!plot.removeTrusted(uuid)) { + if (plot.getDenied().contains(uuid)) { + plot.removeDenied(uuid); + } + } + } + plot.addMember(uuid); + PlotSquared.get().getEventDispatcher().callMember(player, plot, uuid, true); + MainUtil.sendMessage(player, Captions.MEMBER_ADDED); + } + }, null); + } catch (final Throwable exception) { + future.completeExceptionally(exception); + return; + } + } + future.complete(true); + }); + return future; } } diff --git a/Core/src/main/java/com/plotsquared/core/command/Alias.java b/Core/src/main/java/com/plotsquared/core/command/Alias.java index b1d8d8161..1df9848d0 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Alias.java +++ b/Core/src/main/java/com/plotsquared/core/command/Alias.java @@ -33,8 +33,6 @@ import com.plotsquared.core.plot.Plot; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.Permissions; -import com.plotsquared.core.util.StringWrapper; -import com.plotsquared.core.util.uuid.UUIDHandler; @CommandDeclaration(command = "setalias", permission = "plots.alias", @@ -79,7 +77,8 @@ public class Alias extends SubCommand { if (canExecuteCommand(player, Captions.PERMISSION_ALIAS_SET, false) || canExecuteCommand(player, Captions.PERMISSION_ALIAS_SET_OBSOLETE, false)) { - result = setAlias(player, plot, args[1]); + setAlias(player, plot, args[1]); + return true; } else { MainUtil.sendMessage(player, Captions.NO_PERMISSION); } @@ -99,38 +98,32 @@ public class Alias extends SubCommand { } - private boolean setAlias(PlotPlayer player, Plot plot, String alias) { + private void setAlias(PlotPlayer player, Plot plot, String alias) { if (alias.isEmpty()) { Captions.COMMAND_SYNTAX.send(player, getUsage()); - return false; - } - if (alias.length() >= 50) { + } else if (alias.length() >= 50) { MainUtil.sendMessage(player, Captions.ALIAS_TOO_LONG); - return false; - } - if (alias.contains(" ")) { + } else if (alias.contains(" ")) { Captions.NOT_VALID_VALUE.send(player); - return false; - } - if (MathMan.isInteger(alias)) { + } else if (MathMan.isInteger(alias)) { Captions.NOT_VALID_VALUE.send(player); - return false; - } - for (Plot p : PlotSquared.get().getPlots(plot.getArea())) { - if (p.getAlias().equalsIgnoreCase(alias)) { - MainUtil.sendMessage(player, Captions.ALIAS_IS_TAKEN); - return false; + } else { + for (Plot p : PlotSquared.get().getPlots(plot.getArea())) { + if (p.getAlias().equalsIgnoreCase(alias)) { + MainUtil.sendMessage(player, Captions.ALIAS_IS_TAKEN); + return; + } } + PlotSquared.get().getImpromptuUUIDPipeline().getSingle(alias, ((uuid, throwable) -> { + if (uuid != null) { + MainUtil.sendMessage(player, Captions.ALIAS_IS_TAKEN); + } else { + plot.setAlias(alias); + MainUtil.sendMessage(player, + Captions.ALIAS_SET_TO.getTranslated().replaceAll("%alias%", alias)); + } + })); } - if (UUIDHandler.nameExists(new StringWrapper(alias)) || PlotSquared.get() - .hasPlotArea(alias)) { - MainUtil.sendMessage(player, Captions.ALIAS_IS_TAKEN); - return false; - } - plot.setAlias(alias); - MainUtil.sendMessage(player, - Captions.ALIAS_SET_TO.getTranslated().replaceAll("%alias%", alias)); - return true; } private boolean removeAlias(PlotPlayer player, Plot plot) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Cluster.java b/Core/src/main/java/com/plotsquared/core/command/Cluster.java index ae220831e..82f602493 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Cluster.java +++ b/Core/src/main/java/com/plotsquared/core/command/Cluster.java @@ -39,7 +39,6 @@ import com.plotsquared.core.plot.PlotCluster; import com.plotsquared.core.plot.PlotId; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.Permissions; -import com.plotsquared.core.util.uuid.UUIDHandler; import java.util.ArrayList; import java.util.HashSet; @@ -371,22 +370,27 @@ public class Cluster extends SubCommand { return false; } } - // check uuid - UUID uuid = UUIDHandler.getUUID(args[1], null); - if (uuid == null) { - MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[2]); - return false; - } - if (!cluster.isAdded(uuid)) { - // add the user if not added - cluster.invited.add(uuid); - DBFunc.setInvited(cluster, uuid); - PlotPlayer player2 = UUIDHandler.getPlayer(uuid); - if (player2 != null) { - MainUtil.sendMessage(player2, Captions.CLUSTER_INVITED, cluster.getName()); - } - } - MainUtil.sendMessage(player, Captions.CLUSTER_ADDED_USER); + + PlotSquared.get().getImpromptuUUIDPipeline() + .getSingle(args[1], (uuid, throwable) -> { + if (throwable != null) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[1]); + } else { + if (!cluster.isAdded(uuid)) { + // add the user if not added + cluster.invited.add(uuid); + DBFunc.setInvited(cluster, uuid); + + final PlotPlayer otherPlayer = + PlotSquared.imp().getPlayerManager().getPlayerIfExists(uuid); + if (otherPlayer != null) { + MainUtil.sendMessage(otherPlayer, Captions.CLUSTER_INVITED, + cluster.getName()); + } + } + MainUtil.sendMessage(player, Captions.CLUSTER_ADDED_USER); + } + }); return true; } case "k": @@ -420,35 +424,41 @@ public class Cluster extends SubCommand { } } // check uuid - UUID uuid = UUIDHandler.getUUID(args[1], null); - if (uuid == null) { - MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[1]); - return false; - } - // Can't kick if the player is yourself, the owner, or not added to the cluster - if (uuid.equals(player.getUUID()) || uuid.equals(cluster.owner) || !cluster - .isAdded(uuid)) { - MainUtil.sendMessage(player, Captions.CANNOT_KICK_PLAYER, cluster.getName()); - return false; - } - if (cluster.helpers.contains(uuid)) { - cluster.helpers.remove(uuid); - DBFunc.removeHelper(cluster, uuid); - } - cluster.invited.remove(uuid); - DBFunc.removeInvited(cluster, uuid); - PlotPlayer player2 = UUIDHandler.getPlayer(uuid); - if (player2 != null) { - MainUtil.sendMessage(player2, Captions.CLUSTER_REMOVED, cluster.getName()); - } - for (Plot plot : new ArrayList<>( - PlotSquared.get().getPlots(player2.getLocation().getWorld(), uuid))) { - PlotCluster current = plot.getCluster(); - if (current != null && current.equals(cluster)) { - plot.unclaim(); - } - } - MainUtil.sendMessage(player2, Captions.CLUSTER_KICKED_USER); + PlotSquared.get().getImpromptuUUIDPipeline() + .getSingle(args[1], (uuid, throwable) -> { + if (throwable != null) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[1]); + } else { + // Can't kick if the player is yourself, the owner, or not added to the cluster + if (uuid.equals(player.getUUID()) || uuid.equals(cluster.owner) + || !cluster.isAdded(uuid)) { + MainUtil.sendMessage(player, Captions.CANNOT_KICK_PLAYER, + cluster.getName()); + } else { + if (cluster.helpers.contains(uuid)) { + cluster.helpers.remove(uuid); + DBFunc.removeHelper(cluster, uuid); + } + cluster.invited.remove(uuid); + DBFunc.removeInvited(cluster, uuid); + + final PlotPlayer player2 = + PlotSquared.imp().getPlayerManager().getPlayerIfExists(uuid); + if (player2 != null) { + MainUtil.sendMessage(player2, Captions.CLUSTER_REMOVED, + cluster.getName()); + } + for (Plot plot : new ArrayList<>(PlotSquared.get() + .getPlots(player2.getLocation().getWorld(), uuid))) { + PlotCluster current = plot.getCluster(); + if (current != null && current.equals(cluster)) { + plot.unclaim(); + } + } + MainUtil.sendMessage(player2, Captions.CLUSTER_KICKED_USER); + } + } + }); return true; } case "quit": @@ -529,24 +539,27 @@ public class Cluster extends SubCommand { MainUtil.sendMessage(player, Captions.NOT_IN_CLUSTER); return false; } - UUID uuid = UUIDHandler.getUUID(args[2], null); - if (uuid == null) { - MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[2]); - return false; - } - if (args[1].equalsIgnoreCase("add")) { - cluster.helpers.add(uuid); - DBFunc.setHelper(cluster, uuid); - return MainUtil.sendMessage(player, Captions.CLUSTER_ADDED_HELPER); - } - if (args[1].equalsIgnoreCase("remove")) { - cluster.helpers.remove(uuid); - DBFunc.removeHelper(cluster, uuid); - return MainUtil.sendMessage(player, Captions.CLUSTER_REMOVED_HELPER); - } - MainUtil.sendMessage(player, Captions.COMMAND_SYNTAX, - "/plot cluster helpers "); - return false; + + PlotSquared.get().getImpromptuUUIDPipeline() + .getSingle(args[2], (uuid, throwable) -> { + if (throwable != null) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[2]); + } else { + if (args[1].equalsIgnoreCase("add")) { + cluster.helpers.add(uuid); + DBFunc.setHelper(cluster, uuid); + MainUtil.sendMessage(player, Captions.CLUSTER_ADDED_HELPER); + } else if (args[1].equalsIgnoreCase("remove")) { + cluster.helpers.remove(uuid); + DBFunc.removeHelper(cluster, uuid); + MainUtil.sendMessage(player, Captions.CLUSTER_REMOVED_HELPER); + } else { + MainUtil.sendMessage(player, Captions.COMMAND_SYNTAX, + "/plot cluster helpers "); + } + } + }); + return true; } case "spawn": case "home": @@ -615,21 +628,27 @@ public class Cluster extends SubCommand { } } String id = cluster.toString(); - String owner = UUIDHandler.getName(cluster.owner); - if (owner == null) { - owner = "unknown"; - } - String name = cluster.getName(); - String size = (cluster.getP2().x - cluster.getP1().x + 1) + "x" + ( - cluster.getP2().y - cluster.getP1().y + 1); - String rights = cluster.isAdded(player.getUUID()) + ""; - String message = Captions.CLUSTER_INFO.getTranslated(); - message = message.replaceAll("%id%", id); - message = message.replaceAll("%owner%", owner); - message = message.replaceAll("%name%", name); - message = message.replaceAll("%size%", size); - message = message.replaceAll("%rights%", rights); - MainUtil.sendMessage(player, message); + + PlotSquared.get().getImpromptuUUIDPipeline() + .getSingle(cluster.owner, (username, throwable) -> { + final String owner; + if (username == null) { + owner = "unknown"; + } else { + owner = username; + } + String name = cluster.getName(); + String size = (cluster.getP2().x - cluster.getP1().x + 1) + "x" + ( + cluster.getP2().y - cluster.getP1().y + 1); + String rights = cluster.isAdded(player.getUUID()) + ""; + String message = Captions.CLUSTER_INFO.getTranslated(); + message = message.replaceAll("%id%", id); + message = message.replaceAll("%owner%", owner); + message = message.replaceAll("%name%", name); + message = message.replaceAll("%size%", size); + message = message.replaceAll("%rights%", rights); + MainUtil.sendMessage(player, message); + }); return true; } case "sh": diff --git a/Core/src/main/java/com/plotsquared/core/command/Command.java b/Core/src/main/java/com/plotsquared/core/command/Command.java index 6535e3b2c..6e97eb30a 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Command.java +++ b/Core/src/main/java/com/plotsquared/core/command/Command.java @@ -37,6 +37,8 @@ import com.plotsquared.core.util.StringComparison; import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; +import lombok.SneakyThrows; +import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.lang.reflect.InvocationTargetException; @@ -603,6 +605,10 @@ public abstract class Command { return object; } + @SneakyThrows protected static void sneakyThrow(@NotNull final Throwable throwable) { + throw throwable; + } + public enum CommandResult { FAILURE, SUCCESS } diff --git a/Core/src/main/java/com/plotsquared/core/command/Comment.java b/Core/src/main/java/com/plotsquared/core/command/Comment.java index 284587106..501ba4247 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Comment.java +++ b/Core/src/main/java/com/plotsquared/core/command/Comment.java @@ -25,6 +25,7 @@ */ package com.plotsquared.core.command; +import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; @@ -33,11 +34,9 @@ import com.plotsquared.core.plot.comment.CommentManager; import com.plotsquared.core.plot.comment.PlotComment; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.StringMan; -import com.plotsquared.core.util.uuid.UUIDHandler; import java.util.Arrays; import java.util.Locale; -import java.util.Map.Entry; @CommandDeclaration(command = "comment", aliases = {"msg"}, @@ -96,12 +95,13 @@ public class Comment extends SubCommand { StringMan.join(CommentManager.inboxes.keySet(), "|")); return false; } - for (Entry entry : UUIDHandler.getPlayers().entrySet()) { - PlotPlayer pp = entry.getValue(); + + for (final PlotPlayer pp : PlotSquared.imp().getPlayerManager().getPlayers()) { if (pp.getAttribute("chatspy")) { MainUtil.sendMessage(pp, "/plot comment " + StringMan.join(args, " ")); } } + sendMessage(player, Captions.COMMENT_ADDED); return true; } diff --git a/Core/src/main/java/com/plotsquared/core/command/DebugClaimTest.java b/Core/src/main/java/com/plotsquared/core/command/DebugClaimTest.java deleted file mode 100644 index 5412ed6a2..000000000 --- a/Core/src/main/java/com/plotsquared/core/command/DebugClaimTest.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * PlotSquared plot management system for Minecraft - * Copyright (C) 2020 IntellectualSites - * - * 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, see . - */ -package com.plotsquared.core.command; - -import com.google.common.collect.BiMap; -import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.configuration.Captions; -import com.plotsquared.core.location.Location; -import com.plotsquared.core.player.PlotPlayer; -import com.plotsquared.core.plot.Plot; -import com.plotsquared.core.plot.PlotArea; -import com.plotsquared.core.plot.PlotId; -import com.plotsquared.core.plot.PlotManager; -import com.plotsquared.core.util.ChunkManager; -import com.plotsquared.core.util.MainUtil; -import com.plotsquared.core.util.StringWrapper; -import com.plotsquared.core.util.WorldUtil; -import com.plotsquared.core.util.uuid.UUIDHandler; -import com.sk89q.worldedit.math.BlockVector2; - -import java.util.ArrayList; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; - -@CommandDeclaration(command = "debugclaimtest", - description = - "If you accidentally delete your database, this command will attempt to restore all plots based on the data from plot signs. " - + "Execution time may vary", - category = CommandCategory.DEBUG, - requiredType = RequiredType.CONSOLE, - permission = "plots.debugclaimtest") -public class DebugClaimTest extends SubCommand { - - @Override public boolean onCommand(final PlotPlayer player, String[] args) { - if (args.length < 3) { - return !MainUtil.sendMessage(null, - "If you accidentally delete your database, this command will attempt to restore all plots based on the data from the " - + "plot signs. \n\n&cMissing world arg /plot debugclaimtest {world} {PlotId min} {PlotId max}"); - } - PlotArea area = PlotSquared.get().getPlotAreaByString(args[0]); - if (area == null || !WorldUtil.IMP.isWorld(area.getWorldName())) { - Captions.NOT_VALID_PLOT_WORLD.send(player, args[0]); - return false; - } - PlotId min, max; - try { - args[1].split(";"); - args[2].split(";"); - min = PlotId.fromString(args[1]); - max = PlotId.fromString(args[2]); - } catch (Exception ignored) { - return !MainUtil.sendMessage(player, - "&cInvalid min/max values. &7The values are to Plot IDs in the format &cX;Y &7where X;Y are the plot coords\nThe conversion " - + "will only check the plots in the selected area."); - } - MainUtil.sendMessage(player, - "&3Sign Block&8->&3Plot&8: &7Beginning sign to plot conversion. This may take a while..."); - MainUtil.sendMessage(player, - "&3Sign Block&8->&3Plot&8: Found an excess of 250,000 chunks. Limiting search radius... (~3.8 min)"); - PlotManager manager = area.getPlotManager(); - CompletableFuture.runAsync(() -> { - ArrayList ids = MainUtil.getPlotSelectionIds(min, max); - MainUtil.sendMessage(player, - "&3Sign Block&8->&3Plot&8: " + ids.size() + " plot ids to check!"); - for (PlotId id : ids) { - Plot plot = area.getPlotAbs(id); - if (plot.hasOwner()) { - MainUtil.sendMessage(player, " - &cDB Already contains: " + plot.getId()); - continue; - } - Location location = manager.getSignLoc(plot); - BlockVector2 chunk = BlockVector2.at(location.getX() >> 4, location.getZ() >> 4); - ChunkManager.manager.loadChunk(area.getWorldName(), chunk, false).thenRun(() -> { - String[] lines = WorldUtil.IMP.getSignSynchronous(location); - if (lines != null) { - String line = lines[2]; - if (line != null && line.length() > 2) { - line = line.substring(2); - BiMap map = UUIDHandler.getUuidMap(); - UUID uuid = map.get(new StringWrapper(line)); - if (uuid == null) { - for (Map.Entry stringWrapperUUIDEntry : map - .entrySet()) { - if (stringWrapperUUIDEntry.getKey().value.toLowerCase() - .startsWith(line.toLowerCase())) { - uuid = stringWrapperUUIDEntry.getValue(); - break; - } - } - } - if (uuid == null) { - uuid = UUIDHandler.getUUID(line, null); - } - if (uuid != null) { - MainUtil.sendMessage(player, - " - &aFound plot: " + plot.getId() + " : " + line); - plot.setOwner(uuid); - MainUtil.sendMessage(player, " - &8Updated plot: " + plot.getId()); - } else { - MainUtil.sendMessage(player, - " - &cInvalid PlayerName: " + plot.getId() + " : " + line); - } - } - } - }).join(); - } - }).thenRun(() -> MainUtil.sendMessage(player, "&3Sign Block&8->&3Plot&8: Finished scan.")); - return true; - } -} diff --git a/Core/src/main/java/com/plotsquared/core/command/DebugImportWorlds.java b/Core/src/main/java/com/plotsquared/core/command/DebugImportWorlds.java index 9cca145a5..1eedabb71 100644 --- a/Core/src/main/java/com/plotsquared/core/command/DebugImportWorlds.java +++ b/Core/src/main/java/com/plotsquared/core/command/DebugImportWorlds.java @@ -27,6 +27,7 @@ package com.plotsquared.core.command; import com.google.common.base.Charsets; import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.PlotId; import com.plotsquared.core.plot.world.PlotAreaManager; @@ -35,7 +36,6 @@ import com.plotsquared.core.plot.world.SinglePlotAreaManager; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; -import com.plotsquared.core.util.uuid.UUIDHandler; import java.io.File; import java.util.UUID; @@ -76,7 +76,8 @@ public class DebugImportWorlds extends Command { if (name.length() > 16) { uuid = UUID.fromString(name); } else { - uuid = UUIDHandler.getUUID(name, null); + Captions.FETCHING_PLAYER.send(player); + uuid = PlotSquared.get().getImpromptuUUIDPipeline().getSingle(name, 60000L); } if (uuid == null) { uuid = diff --git a/Core/src/main/java/com/plotsquared/core/command/Deny.java b/Core/src/main/java/com/plotsquared/core/command/Deny.java index d591bfa1a..072975226 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Deny.java +++ b/Core/src/main/java/com/plotsquared/core/command/Deny.java @@ -34,10 +34,8 @@ import com.plotsquared.core.plot.Plot; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.WorldUtil; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.worldedit.world.gamemode.GameModes; -import java.util.Set; import java.util.UUID; @CommandDeclaration(command = "deny", @@ -68,48 +66,46 @@ public class Deny extends SubCommand { MainUtil.sendMessage(player, Captions.NO_PLOT_PERMS); return true; } - Set uuids = MainUtil.getUUIDsFromString(args[0]); - if (uuids.isEmpty()) { - MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[0]); - return false; - } - for (UUID uuid : uuids) { - if (uuid == DBFunc.EVERYONE && !( - Permissions.hasPermission(player, Captions.PERMISSION_DENY_EVERYONE) || Permissions - .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_DENY))) { - MainUtil.sendMessage(player, Captions.INVALID_PLAYER, MainUtil.getName(uuid)); - continue; - } - if (plot.isOwner(uuid)) { - MainUtil.sendMessage(player, Captions.CANT_REMOVE_OWNER, MainUtil.getName(uuid)); - return false; - } - if (plot.getDenied().contains(uuid)) { - MainUtil.sendMessage(player, Captions.ALREADY_ADDED, MainUtil.getName(uuid)); - return false; - } - if (uuid != DBFunc.EVERYONE) { - plot.removeMember(uuid); - plot.removeTrusted(uuid); - } - plot.addDenied(uuid); - PlotSquared.get().getEventDispatcher().callDenied(player, plot, uuid, true); - if (!uuid.equals(DBFunc.EVERYONE)) { - handleKick(UUIDHandler.getPlayer(uuid), plot); + MainUtil.getUUIDsFromString(args[0], (uuids, throwable) -> { + if (throwable != null || uuids.isEmpty()) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[0]); } else { - for (PlotPlayer plotPlayer : plot.getPlayersInPlot()) { - // Ignore plot-owners - if (plot.isAdded(plotPlayer.getUUID())) { - continue; + for (UUID uuid : uuids) { + if (uuid == DBFunc.EVERYONE && !( + Permissions.hasPermission(player, Captions.PERMISSION_DENY_EVERYONE) || Permissions + .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_DENY))) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, MainUtil.getName(uuid)); + } else if (plot.isOwner(uuid)) { + MainUtil.sendMessage(player, Captions.CANT_REMOVE_OWNER, MainUtil.getName(uuid)); + return; + } else if (plot.getDenied().contains(uuid)) { + MainUtil.sendMessage(player, Captions.ALREADY_ADDED, MainUtil.getName(uuid)); + return; + } else { + if (uuid != DBFunc.EVERYONE) { + plot.removeMember(uuid); + plot.removeTrusted(uuid); + } + plot.addDenied(uuid); + PlotSquared.get().getEventDispatcher().callDenied(player, plot, uuid, true); + if (!uuid.equals(DBFunc.EVERYONE)) { + handleKick(PlotSquared.imp().getPlayerManager().getPlayerIfExists(uuid), plot); + } else { + for (PlotPlayer plotPlayer : plot.getPlayersInPlot()) { + // Ignore plot-owners + if (plot.isAdded(plotPlayer.getUUID())) { + continue; + } + handleKick(plotPlayer, plot); + } + } } - handleKick(plotPlayer, plot); } + MainUtil.sendMessage(player, Captions.DENIED_ADDED); } - } - if (!uuids.isEmpty()) { - MainUtil.sendMessage(player, Captions.DENIED_ADDED); - } + }); + return true; } diff --git a/Core/src/main/java/com/plotsquared/core/command/Merge.java b/Core/src/main/java/com/plotsquared/core/command/Merge.java index 480112c14..7998e3a84 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Merge.java +++ b/Core/src/main/java/com/plotsquared/core/command/Merge.java @@ -172,7 +172,7 @@ public class Merge extends SubCommand { MainUtil.sendMessage(player, Captions.NO_PLOT_PERMS); return false; } else { - uuid = plot.guessOwner(); + uuid = plot.getOwnerAbs(); } } if (!force && EconHandler.manager != null && plotArea.useEconomy() && price > 0d diff --git a/Core/src/main/java/com/plotsquared/core/command/Visit.java b/Core/src/main/java/com/plotsquared/core/command/Visit.java index 372130a2d..0c31076f2 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Visit.java +++ b/Core/src/main/java/com/plotsquared/core/command/Visit.java @@ -38,14 +38,16 @@ import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; -import com.plotsquared.core.util.uuid.UUIDHandler; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; @CommandDeclaration(command = "visit", permission = "plots.visit", @@ -71,10 +73,71 @@ public class Visit extends Command { if (args.length == 1 && args[0].contains(":")) { args = args[0].split(":"); } - int page = Integer.MIN_VALUE; - Collection unsorted = null; - PlotArea sortByArea = player.getApplicablePlotArea(); - boolean shouldSortByArea = Settings.Teleport.PER_WORLD_VISIT; + + final Collection unsortedPre = new HashSet<>(); + final PlotArea[] sortByArea = new PlotArea[] {player.getApplicablePlotArea()}; + final AtomicBoolean shouldSortByArea = new AtomicBoolean(Settings.Teleport.PER_WORLD_VISIT); + + final Consumer pageConsumer = page -> { + if (page == Integer.MIN_VALUE) { + page = 1; + } + if (unsortedPre.isEmpty()) { + Captions.FOUND_NO_PLOTS.send(player); + } else { + final Collection unsorted = new ArrayList<>(unsortedPre); + if (unsorted.size() > 1) { + unsorted.removeIf(plot -> !plot.isBasePlot()); + } + if (page < 1 || page > unsorted.size()) { + Captions.NOT_VALID_NUMBER.send(player, "(1, " + unsorted.size() + ")"); + } else { + List plots; + if (shouldSortByArea.get()) { + plots = PlotSquared.get().sortPlots(unsorted, PlotSquared.SortType.CREATION_DATE, sortByArea[0]); + } else { + plots = PlotSquared.get().sortPlotsByTemp(unsorted); + } + final Plot plot = plots.get(page - 1); + if (!plot.hasOwner()) { + if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_UNOWNED)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_UNOWNED); + return; + } + } else if (plot.isOwner(player.getUUID())) { + if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_OWNED) && !Permissions.hasPermission(player, Captions.PERMISSION_HOME)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_OWNED); + return; + } + } else if (plot.isAdded(player.getUUID())) { + if (!Permissions.hasPermission(player, Captions.PERMISSION_SHARED)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_SHARED); + return; + } + } else { + if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_OTHER)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_OTHER); + return; + } + if (!plot.getFlag(UntrustedVisitFlag.class) && !Permissions.hasPermission(player, Captions.PERMISSION_ADMIN_VISIT_UNTRUSTED)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_ADMIN_VISIT_UNTRUSTED); + return; + } + } + confirm.run(this, + () -> plot.teleportPlayer(player, TeleportCause.COMMAND, result -> { + if (result) { + whenDone.run(Visit.this, CommandResult.SUCCESS); + } else { + whenDone.run(Visit.this, CommandResult.FAILURE); + } + }), () -> whenDone.run(Visit.this, CommandResult.FAILURE)); + } + } + }; + + final int[] page = new int[]{Integer.MIN_VALUE}; + switch (args.length) { case 3: if (!MathMan.isInteger(args[1])) { @@ -82,109 +145,66 @@ public class Visit extends Command { Captions.COMMAND_SYNTAX.send(player, getUsage()); return CompletableFuture.completedFuture(false); } - page = Integer.parseInt(args[2]); + page[0] = Integer.parseInt(args[2]); case 2: - if (page != Integer.MIN_VALUE || !MathMan.isInteger(args[1])) { - sortByArea = PlotSquared.get().getPlotAreaByString(args[1]); - if (sortByArea == null) { + if (page[0] != Integer.MIN_VALUE || !MathMan.isInteger(args[1])) { + sortByArea[0] = PlotSquared.get().getPlotAreaByString(args[1]); + if (sortByArea[0] == null) { Captions.NOT_VALID_NUMBER.send(player, "(1, ∞)"); Captions.COMMAND_SYNTAX.send(player, getUsage()); return CompletableFuture.completedFuture(false); } - UUID user = UUIDHandler.getUUIDFromString(args[0]); - if (user == null) { - Captions.COMMAND_SYNTAX.send(player, getUsage()); - return CompletableFuture.completedFuture(false); - } - unsorted = PlotSquared.get().getBasePlots(user); - shouldSortByArea = true; + + MainUtil.getUUIDsFromString(args[0], (uuids, throwable) -> { + if (throwable != null || uuids.size() != 1) { + Captions.COMMAND_SYNTAX.send(player, getUsage()); + } else { + unsortedPre.addAll(PlotSquared.get().getBasePlots((UUID) uuids.toArray()[0])); + shouldSortByArea.set(true); + pageConsumer.accept(page[0]); + } + }); break; } - page = Integer.parseInt(args[1]); + page[0] = Integer.parseInt(args[1]); case 1: - UUID user = args[0].length() >= 2 ? UUIDHandler.getUUIDFromString(args[0]) : null; - if (user != null && !PlotSquared.get().hasPlot(user)) { - user = null; - } - if (page == Integer.MIN_VALUE && user == null && MathMan.isInteger(args[0])) { - page = Integer.parseInt(args[0]); - unsorted = PlotSquared.get().getBasePlots(player); - break; - } - if (user != null) { - unsorted = PlotSquared.get().getBasePlots(user); - } else { - Plot plot = MainUtil.getPlotFromString(player, args[0], true); - if (plot != null) { - unsorted = Collections.singletonList(plot.getBasePlot(false)); + final String[] finalArgs = args; + final Consumer uuidConsumer = uuid -> { + if (page[0] == Integer.MIN_VALUE && uuid == null && MathMan.isInteger(finalArgs[0])) { + page[0] = Integer.parseInt(finalArgs[0]); + unsortedPre.addAll(PlotSquared.get().getBasePlots(player)); + } else { + if (uuid != null) { + unsortedPre.addAll(PlotSquared.get().getBasePlots(uuid)); + } else { + Plot plot = MainUtil.getPlotFromString(player, finalArgs[0], true); + if (plot != null) { + unsortedPre.addAll(Collections.singletonList(plot.getBasePlot(false))); + } + } } + pageConsumer.accept(page[0]); + }; + + if (args[0].length() >= 2) { + PlotSquared.get().getImpromptuUUIDPipeline().getSingle(args[0], (uuid, throwable) -> { + if (uuid != null && !PlotSquared.get().hasPlot(uuid)) { + uuidConsumer.accept(null); + } else { + uuidConsumer.accept(uuid); + } + }); + } else { + uuidConsumer.accept(null); } break; case 0: - page = 1; - unsorted = PlotSquared.get().getPlots(player); + unsortedPre.addAll(PlotSquared.get().getPlots(player)); + pageConsumer.accept(1); break; default: } - if (page == Integer.MIN_VALUE) { - page = 1; - } - if (unsorted == null || unsorted.isEmpty()) { - Captions.FOUND_NO_PLOTS.send(player); - return CompletableFuture.completedFuture(false); - } - unsorted = new ArrayList<>(unsorted); - if (unsorted.size() > 1) { - unsorted.removeIf(plot -> !plot.isBasePlot()); - } - if (page < 1 || page > unsorted.size()) { - Captions.NOT_VALID_NUMBER.send(player, "(1, " + unsorted.size() + ")"); - return CompletableFuture.completedFuture(false); - } - List plots; - if (shouldSortByArea) { - plots = PlotSquared.get() - .sortPlots(unsorted, PlotSquared.SortType.CREATION_DATE, sortByArea); - } else { - plots = PlotSquared.get().sortPlotsByTemp(unsorted); - } - final Plot plot = plots.get(page - 1); - if (!plot.hasOwner()) { - if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_UNOWNED)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_UNOWNED); - return CompletableFuture.completedFuture(false); - } - } else if (plot.isOwner(player.getUUID())) { - if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_OWNED) && !Permissions - .hasPermission(player, Captions.PERMISSION_HOME)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_OWNED); - return CompletableFuture.completedFuture(false); - } - } else if (plot.isAdded(player.getUUID())) { - if (!Permissions.hasPermission(player, Captions.PERMISSION_SHARED)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_SHARED); - return CompletableFuture.completedFuture(false); - } - } else { - if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_OTHER)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_OTHER); - return CompletableFuture.completedFuture(false); - } - if (!plot.getFlag(UntrustedVisitFlag.class) && !Permissions - .hasPermission(player, Captions.PERMISSION_ADMIN_VISIT_UNTRUSTED)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_ADMIN_VISIT_UNTRUSTED); - return CompletableFuture.completedFuture(false); - } - } - confirm.run(this, () -> plot.teleportPlayer(player, TeleportCause.COMMAND, result -> { - if (result) { - whenDone.run(Visit.this, CommandResult.SUCCESS); - } else { - whenDone.run(Visit.this, CommandResult.FAILURE); - } - }), () -> whenDone.run(Visit.this, CommandResult.FAILURE)); - return CompletableFuture.completedFuture(true); } diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java index 6238ec066..9d9251c61 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java @@ -450,6 +450,7 @@ public enum Captions implements Caption { // DEBUG_REPORT_CREATED("$1Uploaded a full debug to: $1%url%", "Paste"), PURGE_SUCCESS("$4Successfully purged %s plots", "Purge"), + FETCHING_PLAYER("$1PlotSquared is attempting to find the specified player from your argument(s). This may take a while.", "Players"), // TRIM_IN_PROGRESS("A world trim task is already in progress!", "Trim"), // diff --git a/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java b/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java index 08133387e..5a4e43142 100644 --- a/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java +++ b/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java @@ -61,7 +61,6 @@ import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.worldedit.world.gamemode.GameMode; import com.sk89q.worldedit.world.gamemode.GameModes; import com.sk89q.worldedit.world.item.ItemType; @@ -161,7 +160,7 @@ public class PlotListener { if (plot.getFlag(NotifyEnterFlag.class)) { if (!Permissions.hasPermission(player, "plots.flag.notify-enter.bypass")) { for (UUID uuid : plot.getOwners()) { - PlotPlayer owner = UUIDHandler.getPlayer(uuid); + final PlotPlayer owner = PlotSquared.imp().getPlayerManager().getPlayerIfExists(uuid); if (owner != null && !owner.getUUID().equals(player.getUUID())) { MainUtil.sendMessage(owner, Captions.NOTIFY_ENTER.getTranslated() .replace("%player", player.getName()) @@ -337,7 +336,7 @@ public class PlotListener { if (plot.getFlag(NotifyLeaveFlag.class)) { if (!Permissions.hasPermission(player, "plots.flag.notify-enter.bypass")) { for (UUID uuid : plot.getOwners()) { - PlotPlayer owner = UUIDHandler.getPlayer(uuid); + final PlotPlayer owner = PlotSquared.imp().getPlayerManager().getPlayerIfExists(uuid); if ((owner != null) && !owner.getUUID().equals(player.getUUID())) { MainUtil.sendMessage(owner, Captions.NOTIFY_LEAVE.getTranslated() .replace("%player", player.getName()) diff --git a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java index 911c56adb..586809880 100644 --- a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java +++ b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java @@ -49,7 +49,6 @@ import com.plotsquared.core.util.EconHandler; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.world.gamemode.GameMode; import com.sk89q.worldedit.world.item.ItemType; @@ -108,17 +107,6 @@ public abstract class PlotPlayer implements CommandCaller, OfflinePlotPlayer { return PlotSquared.get().IMP.wrapPlayer(player); } - /** - * Get the cached PlotPlayer from a username
- * - This will return null if the player has not finished logging in or is not online - * - * @param name - * @return - */ - public static PlotPlayer get(String name) { - return UUIDHandler.getPlayer(name); - } - public abstract Actor toActor(); /** @@ -363,8 +351,6 @@ public abstract class PlotPlayer implements CommandCaller, OfflinePlotPlayer { /** * Get this player's full location (including yaw/pitch) - * - * @return */ public abstract Location getLocationFull(); @@ -563,11 +549,10 @@ public abstract class PlotPlayer implements CommandCaller, OfflinePlotPlayer { plot.getId(), getName())); } } - String name = getName(); if (ExpireManager.IMP != null) { ExpireManager.IMP.storeDate(getUUID(), System.currentTimeMillis()); } - UUIDHandler.getPlayers().remove(name); + PlotSquared.imp().getPlayerManager().removePlayer(this); PlotSquared.get().IMP.unregister(this); } diff --git a/Core/src/main/java/com/plotsquared/core/plot/Plot.java b/Core/src/main/java/com/plotsquared/core/plot/Plot.java index 9461219ef..e7cfbcafd 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/Plot.java +++ b/Core/src/main/java/com/plotsquared/core/plot/Plot.java @@ -25,7 +25,6 @@ */ package com.plotsquared.core.plot; -import com.google.common.collect.BiMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import com.plotsquared.core.PlotSquared; @@ -56,17 +55,14 @@ import com.plotsquared.core.plot.flag.implementations.KeepFlag; import com.plotsquared.core.plot.schematic.Schematic; import com.plotsquared.core.queue.GlobalBlockQueue; import com.plotsquared.core.queue.LocalBlockQueue; -import com.plotsquared.core.util.ChunkManager; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.RegionManager; import com.plotsquared.core.util.SchematicHandler; -import com.plotsquared.core.util.StringWrapper; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector2; @@ -83,7 +79,6 @@ import java.awt.geom.PathIterator; import java.awt.geom.Rectangle2D; import java.io.File; import java.net.URL; -import java.nio.charset.StandardCharsets; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; @@ -405,11 +400,10 @@ public class Plot { * @return list of PlotPlayer(s) or an empty list */ public List getPlayersInPlot() { - ArrayList players = new ArrayList<>(); - for (Entry entry : UUIDHandler.getPlayers().entrySet()) { - PlotPlayer plotPlayer = entry.getValue(); - if (this.equals(plotPlayer.getCurrentPlot())) { - players.add(plotPlayer); + final List players = new ArrayList<>(); + for (final PlotPlayer player : PlotSquared.imp().getPlayerManager().getPlayers()) { + if (this.equals(player.getCurrentPlot())) { + players.add(player); } } return players; @@ -1717,12 +1711,7 @@ public class Plot { this.setSign("unknown"); return; } - String name = UUIDHandler.getName(this.getOwnerAbs()); - if (name == null) { - this.setSign("unknown"); - } else { - this.setSign(name); - } + PlotSquared.get().getImpromptuUUIDPipeline().getSingle(this.getOwnerAbs(), this::setSign); } /** @@ -2372,7 +2361,6 @@ public class Plot { * Check if a plot can be claimed by the provided player. * * @param player the claiming player - * @return */ public boolean canClaim(@NotNull PlotPlayer player) { PlotCluster cluster = this.getCluster(); @@ -2382,81 +2370,13 @@ public class Plot { return false; } } - final UUID owner = this.guessOwner(); + final UUID owner = this.getOwnerAbs(); if (owner != null) { return false; } return !isMerged(); } - /** - * Guess the owner of a plot either by the value in memory, or the sign data
- * Note: Recovering from sign information is useful if e.g. PlotMe conversion wasn't successful - * - * @return UUID - */ - public UUID guessOwner() { - if (this.hasOwner()) { - return this.getOwnerAbs(); - } - if (!this.area.allowSigns() || !Settings.Enabled_Components.GUESS_PLOT_OWNER) { - return null; - } - try { - final Location location = this.getManager().getSignLoc(this); - String[] lines = TaskManager.IMP.sync(new RunnableVal() { - @Override public void run(String[] value) { - ChunkManager.manager - .loadChunk(location.getWorld(), location.getBlockVector2(), false); - this.value = WorldUtil.IMP.getSignSynchronous(location); - } - }); - if (lines == null) { - return null; - } - loop: - for (int i = 4; i > 0; i--) { - String caption = Captions.valueOf("OWNER_SIGN_LINE_" + i).getTranslated(); - int index = caption.indexOf("%plr%"); - if (index < 0) { - continue; - } - String line = lines[i - 1]; - if (line.length() <= index) { - return null; - } - String name = line.substring(index); - if (name.isEmpty()) { - return null; - } - UUID owner = UUIDHandler.getUUID(name, null); - if (owner != null) { - this.setOwnerAbs(owner); - break; - } - if (lines[i - 1].length() == 15) { - BiMap map = UUIDHandler.getUuidMap(); - for (Entry entry : map.entrySet()) { - String key = entry.getKey().value; - if (key.length() > name.length() && key.startsWith(name)) { - this.setOwnerAbs(entry.getValue()); - break loop; - } - } - } - this.setOwnerAbs(UUID.nameUUIDFromBytes( - ("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8))); - break; - } - if (this.hasOwner()) { - this.create(); - } - return this.getOwnerAbs(); - } catch (IllegalArgumentException ignored) { - return null; - } - } - /** * Remove the south road section of a plot
* - Used when a plot is merged
@@ -3099,10 +3019,12 @@ public class Plot { return false; } if (!isMerged()) { - return UUIDHandler.getPlayer(this.getOwnerAbs()) != null; + return PlotSquared.imp().getPlayerManager() + .getPlayerIfExists(Objects.requireNonNull(this.getOwnerAbs())) != null; } for (final Plot current : getConnectedPlots()) { - if (current.hasOwner() && UUIDHandler.getPlayer(current.getOwnerAbs()) != null) { + if (current.hasOwner() && PlotSquared.imp().getPlayerManager() + .getPlayerIfExists(Objects.requireNonNull(current.getOwnerAbs())) != null) { return true; } } @@ -3114,9 +3036,9 @@ public class Plot { * - E.g. floor, wall, border etc.
* - The available components depend on the generator being used
* - * @param component - * @param blocks - * @return + * @param component Component to set + * @param blocks Pattern to use the generation + * @return True if the component was set successfully */ public boolean setComponent(String component, Pattern blocks) { PlotComponentSetEvent event = diff --git a/Core/src/main/java/com/plotsquared/core/util/MainUtil.java b/Core/src/main/java/com/plotsquared/core/util/MainUtil.java index 93cb7b3e4..4e887fead 100644 --- a/Core/src/main/java/com/plotsquared/core/util/MainUtil.java +++ b/Core/src/main/java/com/plotsquared/core/util/MainUtil.java @@ -49,7 +49,7 @@ import com.plotsquared.core.plot.flag.types.DoubleFlag; import com.plotsquared.core.util.net.AbstractDelegateOutputStream; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; +import com.plotsquared.core.uuid.UUIDMapping; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; @@ -73,6 +73,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -81,6 +82,7 @@ import java.util.Optional; import java.util.Scanner; import java.util.Set; import java.util.UUID; +import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.IntConsumer; import java.util.function.IntFunction; @@ -99,12 +101,6 @@ public class MainUtil { FLAG_DECIMAL_FORMAT.setMaximumFractionDigits(340); } - /** - * If the NMS code for sending chunk updates is functional
- * - E.g. If using an older version of Bukkit, or before the plugin is updated to 1.5
- * - Slower fallback code will be used if not.
- */ - public static boolean canSendChunk = false; /** * Cache of mapping x,y,z coordinates to the chunk array
* - Used for efficient world generation
@@ -152,15 +148,6 @@ public class MainUtil { } } - public static void sendAdmin(final String s) { - for (final PlotPlayer player : UUIDHandler.getPlayers().values()) { - if (player.hasPermission(Captions.PERMISSION_ADMIN.getTranslated())) { - player.sendMessage(Captions.color(s)); - } - } - PlotSquared.debug(s); - } - public static void upload(UUID uuid, String file, String extension, final RunnableVal writeTask, final RunnableVal whenDone) { if (writeTask == null) { @@ -396,7 +383,7 @@ public class MainUtil { if (owner.equals(DBFunc.SERVER)) { return Captions.SERVER.getTranslated(); } - String name = UUIDHandler.getName(owner); + String name = PlotSquared.get().getImpromptuUUIDPipeline().getSingle(owner, 10L); if (name == null) { return Captions.UNKNOWN.getTranslated(); } @@ -467,7 +454,7 @@ public class MainUtil { for (String term : split) { try { - UUID uuid = UUIDHandler.getUUID(term, null); + UUID uuid = PlotSquared.get().getImpromptuUUIDPipeline().getSingle(term, 10L); if (uuid == null) { uuid = UUID.fromString(term); } @@ -738,33 +725,44 @@ public class MainUtil { return ratings; } - public static Set getUUIDsFromString(String list) { + public static void getUUIDsFromString(final String list, final BiConsumer, Throwable> consumer) { String[] split = list.split(","); - HashSet result = new HashSet<>(); - for (String name : split) { + + final Set result = new HashSet<>(); + final List request = new LinkedList<>(); + + for (final String name : split) { if (name.isEmpty()) { - // Invalid - return Collections.emptySet(); - } - if ("*".equals(name)) { + consumer.accept(Collections.emptySet(), null); + return; + } else if ("*".equals(name)) { result.add(DBFunc.EVERYONE); - continue; - } - if (name.length() > 16) { + } else if (name.length() > 16) { try { result.add(UUID.fromString(name)); - continue; } catch (IllegalArgumentException ignored) { - return Collections.emptySet(); + consumer.accept(Collections.emptySet(), null); + return; } + } else { + request.add(name); } - UUID uuid = UUIDHandler.getUUID(name, null); - if (uuid == null) { - return Collections.emptySet(); - } - result.add(uuid); } - return result; + + if (request.isEmpty()) { + consumer.accept(result, null); + } else { + PlotSquared.get().getImpromptuUUIDPipeline().getUUIDs(request).whenComplete((uuids, throwable) -> { + if (throwable != null) { + consumer.accept(null, throwable); + } else { + for (final UUIDMapping uuid : uuids) { + result.add(uuid.getUuid()); + } + consumer.accept(result, null); + } + }); + } } /** @@ -931,7 +929,7 @@ public class MainUtil { public static void getPersistentMeta(UUID uuid, final String key, final RunnableVal result) { - PlotPlayer player = UUIDHandler.getPlayer(uuid); + PlotPlayer player = PlotSquared.imp().getPlayerManager().getPlayerIfExists(uuid); if (player != null) { result.run(player.getPersistentMeta(key)); } else { diff --git a/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java b/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java new file mode 100644 index 000000000..fd1eebe4e --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java @@ -0,0 +1,120 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * 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, see . + */ +package com.plotsquared.core.util; + +import com.plotsquared.core.player.PlotPlayer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * Manages player instances + */ +public abstract class PlayerManager { + + private final Map playerMap = new HashMap<>(); + private final Object playerLock = new Object(); + + /** + * Remove a player from the player map + * + * @param plotPlayer Player to remove + */ + public void removePlayer(@NotNull final PlotPlayer plotPlayer) { + synchronized (playerLock) { + this.playerMap.remove(plotPlayer.getUUID()); + } + } + + /** + * Get the player from its UUID if it is stored in the player map. + * + * @param uuid Player UUID + * @return Player, or null + */ + @Nullable public PlotPlayer getPlayerIfExists(@Nullable final UUID uuid) { + if (uuid == null) { + return null; + } + return this.playerMap.get(uuid); + } + + @Nullable public PlotPlayer getPlayerIfExists(@Nullable final String name) { + for (final PlotPlayer plotPlayer : this.playerMap.values()) { + if (plotPlayer.getName().equalsIgnoreCase(name)) { + return plotPlayer; + } + } + return null; + } + + /** + * Get a plot player from a UUID. This method requires + * that the caller actually knows that the player exists. + *

+ * The method will throw an exception if there is no such + * player online. + * + * @param uuid Player UUID + * @return Player object + */ + @NotNull public PlotPlayer getPlayer(@NotNull final UUID uuid) { + synchronized (playerLock) { + PlotPlayer player = this.playerMap.get(uuid); + if (player == null) { + player = createPlayer(uuid); + this.playerMap.put(uuid, player); + } + return player; + } + } + + @NotNull protected abstract PlotPlayer createPlayer(@NotNull final UUID uuid); + + /** + * Get all online players + * + * @return Unmodifiable collection of players + */ + public Collection getPlayers() { + return Collections.unmodifiableCollection(this.playerMap.values()); + } + + + public static final class NoSuchPlayerException extends IllegalArgumentException { + + public NoSuchPlayerException(@NotNull final UUID uuid) { + super(String.format("There is no online player with UUID '%s'", uuid.toString())); + } + + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java b/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java index 3adb8d19e..aa9e7a04c 100644 --- a/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java +++ b/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java @@ -104,7 +104,7 @@ public abstract class SchematicHandler { Iterator i = plots.iterator(); final Plot plot = i.next(); i.remove(); - String owner = UUIDHandler.getName(plot.guessOwner()); + String owner = UUIDHandler.getName(plot.getOwnerAbs()); if (owner == null) { owner = "unknown"; } diff --git a/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java b/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java new file mode 100644 index 000000000..a7c7c2a8f --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java @@ -0,0 +1,82 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * 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, see . + */ +package com.plotsquared.core.util; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.command.Command; +import com.plotsquared.core.command.CommandCategory; +import com.plotsquared.core.command.RequiredType; +import com.plotsquared.core.uuid.UUIDMapping; +import lombok.experimental.UtilityClass; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * Tab completion utilities + */ +@UtilityClass public class TabCompletions { + + private final Cache> cachedCompletionValues = + CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build(); + + /** + * Get a list of tab completions corresponding to player names. This uses the UUID pipeline + * cache, so it will complete will all names known to PlotSquared + * + * @param input Command input + * @param existing Players that should not be included in completions + * @return List of completions + */ + @NotNull public List completePlayers(@NotNull final String input, + @NotNull final List existing) { + List players = cachedCompletionValues.getIfPresent("players"); + if (players == null) { + final Collection mappings = + PlotSquared.get().getImpromptuUUIDPipeline().getAllImmediately(); + players = new ArrayList<>(mappings.size()); + for (final UUIDMapping mapping : mappings) { + players.add(mapping.getUsername()); + } + cachedCompletionValues.put("players", players); + } + final String processedInput = input.toLowerCase(Locale.ENGLISH); + return players.stream() + .filter(player -> player.toLowerCase(Locale.ENGLISH).startsWith(processedInput)) + .filter(player -> !existing.contains(player)).map( + player -> new Command(null, false, player, "", RequiredType.NONE, + CommandCategory.INFO) { + }).collect(Collectors.toList()); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDHandler.java b/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDHandler.java deleted file mode 100644 index 6dd8b1c47..000000000 --- a/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDHandler.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * PlotSquared plot management system for Minecraft - * Copyright (C) 2020 IntellectualSites - * - * 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, see . - */ -package com.plotsquared.core.util.uuid; - -import com.google.common.collect.BiMap; -import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.configuration.Captions; -import com.plotsquared.core.database.DBFunc; -import com.plotsquared.core.player.OfflinePlotPlayer; -import com.plotsquared.core.player.PlotPlayer; -import com.plotsquared.core.util.StringWrapper; -import com.plotsquared.core.util.task.RunnableVal; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.UUID; - -public class UUIDHandler { - - public static UUIDHandlerImplementation implementation; - - public static void add(StringWrapper name, UUID uuid) { - implementation.add(name, uuid); - } - - /** - * Get the map containing all names/uuids. - * - * @return map with names + uuids - * @see BiMap - */ - public static BiMap getUuidMap() { - return implementation.getUUIDMap(); - } - - /** - * Check if a uuid is cached - * - * @param uuid to check - * @return true of the uuid is cached - * @see BiMap#containsValue(Object) - */ - public static boolean uuidExists(UUID uuid) { - return implementation.uuidExists(uuid); - } - - /** - * Check if a name is cached - * - * @param name to check - * @return true of the name is cached - * @see BiMap#containsKey(Object) - */ - public static boolean nameExists(StringWrapper name) { - return implementation.nameExists(name); - } - - public static HashSet getAllUUIDS() { - final HashSet uuids = new HashSet<>(); - PlotSquared.get().forEachPlotRaw(plot -> { - if (plot.hasOwner()) { - uuids.add(plot.getOwnerAbs()); - uuids.addAll(plot.getTrusted()); - uuids.addAll(plot.getMembers()); - uuids.addAll(plot.getDenied()); - } - }); - return uuids; - } - - public static UUIDWrapper getUUIDWrapper() { - return implementation.getUUIDWrapper(); - } - - public static void setUUIDWrapper(UUIDWrapper wrapper) { - implementation.setUUIDWrapper(wrapper); - } - - public static void startCaching(Runnable whenDone) { - implementation.startCaching(whenDone); - } - - public static void cache(BiMap toAdd) { - implementation.add(toAdd); - } - - @NotNull public static UUID getUUID(PlotPlayer player) { - return implementation.getUUID(player); - } - - public static UUID getUUID(OfflinePlotPlayer player) { - if (implementation == null) { - return null; - } - return implementation.getUUID(player); - } - - @Nullable public static String getName(UUID uuid) { - if (implementation == null) { - return null; - } - if (uuid != null && uuid.equals(DBFunc.SERVER)) { - return Captions.SERVER.getTranslated(); - } - return implementation.getName(uuid); - } - - @Nullable public static PlotPlayer getPlayer(@Nullable final UUID uuid) { - if (implementation == null || uuid == null) { - return null; - } - return check(implementation.getPlayer(uuid)); - } - - public static PlotPlayer getPlayer(String name) { - if (implementation == null) { - return null; - } - return check(implementation.getPlayer(name)); - } - - private static PlotPlayer check(@Nullable PlotPlayer player) { - if (player != null && !player.isOnline()) { - UUIDHandler.getPlayers().remove(player.getName()); - PlotSquared.get().IMP.unregister(player); - player = null; - } - return player; - } - - public static UUID getUUIDFromString(String nameOrUUIDString) { - if (implementation == null) { - return null; - } - if (nameOrUUIDString.length() > 16) { - try { - return UUID.fromString(nameOrUUIDString); - } catch (IllegalArgumentException e) { - return null; - } - } - return UUIDHandler.getUUID(nameOrUUIDString, null); - } - - public static UUID getUUID(String name, RunnableVal ifFetch) { - if (implementation == null) { - return null; - } - return implementation.getUUID(name, ifFetch); - } - - public static UUID getCachedUUID(String name, RunnableVal ifFetch) { - if (implementation == null) { - return null; - } - return implementation.getUUIDMap().get(new StringWrapper(name)); - } - - public static Map getPlayers() { - if (implementation == null) { - return new HashMap<>(); - } - return implementation.getPlayers(); - } - - public static void handleShutdown() { - if (implementation == null) { - return; - } - implementation.handleShutdown(); - } -} diff --git a/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDHandlerImplementation.java b/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDHandlerImplementation.java deleted file mode 100644 index 687af58e0..000000000 --- a/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDHandlerImplementation.java +++ /dev/null @@ -1,324 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * PlotSquared plot management system for Minecraft - * Copyright (C) 2020 IntellectualSites - * - * 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, see . - */ -package com.plotsquared.core.util.uuid; - -import com.google.common.base.Charsets; -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.configuration.Captions; -import com.plotsquared.core.configuration.Settings; -import com.plotsquared.core.database.DBFunc; -import com.plotsquared.core.player.OfflinePlotPlayer; -import com.plotsquared.core.player.PlotPlayer; -import com.plotsquared.core.plot.Plot; -import com.plotsquared.core.util.StringMan; -import com.plotsquared.core.util.StringWrapper; -import com.plotsquared.core.util.task.RunnableVal; -import com.plotsquared.core.util.task.TaskManager; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -public abstract class UUIDHandlerImplementation { - - public final HashSet unknown = new HashSet<>(); - private final ConcurrentHashMap players; - protected UUIDWrapper uuidWrapper; - private boolean cached = false; - private BiMap uuidMap = HashBiMap.create(new HashMap<>()); - - public UUIDHandlerImplementation(UUIDWrapper wrapper) { - this.uuidWrapper = wrapper; - this.players = new ConcurrentHashMap<>(); - } - - /** - * If the UUID is not found, some commands can request to fetch the UUID when possible. - * - * @param name - * @param ifFetch - */ - public abstract void fetchUUID(String name, RunnableVal ifFetch); - - /** - * Start UUID caching (this should be an async task) - * Recommended to override this is you want to cache offline players - */ - public boolean startCaching(Runnable whenDone) { - if (this.cached) { - return false; - } - return this.cached = true; - } - - public UUIDWrapper getUUIDWrapper() { - return this.uuidWrapper; - } - - public void setUUIDWrapper(UUIDWrapper wrapper) { - this.uuidWrapper = wrapper; - } - - public void rename(UUID uuid, StringWrapper name) { - this.uuidMap.inverse().remove(uuid); - this.uuidMap.put(name, uuid); - } - - public void add(BiMap toAdd) { - if (this.uuidMap.isEmpty()) { - this.uuidMap = toAdd; - } - for (Map.Entry entry : toAdd.entrySet()) { - UUID uuid = entry.getValue(); - StringWrapper name = entry.getKey(); - if (uuid == null || name == null) { - continue; - } - StringWrapper oldName = this.uuidMap.inverse().get(uuid); - if (oldName != null) { - if (this.uuidMap.containsKey(name)) { - continue; - } - if (getPlayer(uuid) == null) { - rename(uuid, name); - } - continue; - } - this.uuidMap.put(name, uuid); - } - PlotSquared - .debug(Captions.PREFIX + "&6Cached a total of: " + this.uuidMap.size() + " UUIDs"); - } - - public boolean add(final StringWrapper name, final UUID uuid) { - if (uuid == null) { - PlotSquared.debug("UUID cannot be null!"); - return false; - } - if (name == null) { - try { - this.unknown.add(uuid); - } catch (Exception e) { - PlotSquared.log("&c(minor) Invalid UUID mapping: " + uuid); - e.printStackTrace(); - } - return false; - } - - /* - * lazy UUID conversion: - * - Useful if the person misconfigured the database, or settings before - * PlotMe conversion - */ - if (!Settings.UUID.OFFLINE && !this.unknown.isEmpty()) { - TaskManager.runTaskAsync(() -> { - UUID offline = UUID.nameUUIDFromBytes( - ("OfflinePlayer:" + name.value).getBytes(Charsets.UTF_8)); - if (!UUIDHandlerImplementation.this.unknown.contains(offline) && !name.value - .equals(name.value.toLowerCase())) { - offline = UUID.nameUUIDFromBytes( - ("OfflinePlayer:" + name.value.toLowerCase()).getBytes(Charsets.UTF_8)); - if (!UUIDHandlerImplementation.this.unknown.contains(offline)) { - offline = null; - } - } - if (offline != null && !offline.equals(uuid)) { - UUIDHandlerImplementation.this.unknown.remove(offline); - Set plots = PlotSquared.get().getPlotsAbs(offline); - if (!plots.isEmpty()) { - for (final Plot plot : plots) { - plot.setOwnerAbs(uuid); - } - DBFunc.replaceUUID(offline, uuid); - PlotSquared.debug("&cDetected invalid UUID stored for: " + name.value); - PlotSquared.debug( - "&7 - Did you recently switch to online-mode storage without running `uuidconvert`?"); - PlotSquared.debug("&6" + PlotSquared.imp().getPluginName() - + " will update incorrect entries when the user logs in, or you can reconstruct your database."); - } - } - }); - } else if (Settings.UUID.FORCE_LOWERCASE && !this.unknown.isEmpty() && !name.value - .equals(name.value.toLowerCase())) { - TaskManager.runTaskAsync(() -> { - UUID offlineUpper = UUID.nameUUIDFromBytes( - ("OfflinePlayer:" + name.value).getBytes(Charsets.UTF_8)); - if (UUIDHandlerImplementation.this.unknown.contains(offlineUpper) && !offlineUpper - .equals(uuid)) { - UUIDHandlerImplementation.this.unknown.remove(offlineUpper); - Set plots = PlotSquared.get().getPlotsAbs(offlineUpper); - if (!plots.isEmpty()) { - for (final Plot plot : plots) { - plot.setOwnerAbs(uuid); - } - replace(offlineUpper, uuid, name.value); - } - } - }); - } - try { - UUID existing = this.uuidMap.put(name, uuid); - if (existing != null) { - if (!existing.equals(uuid)) { - Set plots = PlotSquared.get().getPlots(existing); - if (!plots.isEmpty()) { - for (final Plot plot : plots) { - plot.setOwnerAbs(uuid); - } - replace(existing, uuid, name.value); - } - return true; - } else { - StringWrapper oName = this.uuidMap.inverse().get(existing); - if (!oName.equals(name)) { - this.uuidMap.remove(name); - this.uuidMap.put(name, uuid); - } - } - return false; - } - } catch (Exception ignored) { - BiMap inverse = this.uuidMap.inverse(); - StringWrapper oldName = inverse.get(uuid); - if (oldName != null) { - if (this.uuidMap.containsKey(name)) { - return false; - } - PlotPlayer player = getPlayer(uuid); - if (player == null || player.getName().equalsIgnoreCase(name.value)) { - rename(uuid, name); - return false; - } - StringWrapper newName = new StringWrapper(player.getName()); - UUID newUUID = player.getUUID(); - if (newUUID.equals(uuid) && !newName.equals(oldName)) { - inverse.remove(uuid); - this.uuidMap.put(newName, newUUID); - } - return false; - } - this.uuidMap.put(name, uuid); - } - return true; - } - - private void replace(UUID from, UUID to, String name) { - DBFunc.replaceUUID(from, to); - PlotSquared.debug("&cDetected invalid UUID stored for: " + name); - PlotSquared.debug( - "&7 - Did you recently switch to online-mode storage without running `uuidconvert`?"); - PlotSquared.debug("&6" + PlotSquared.imp().getPluginName() - + " will update incorrect entries when the user logs in, or you can reconstruct your database."); - } - - public boolean uuidExists(UUID uuid) { - return this.uuidMap.containsValue(uuid); - } - - public BiMap getUUIDMap() { - return this.uuidMap; - } - - public boolean nameExists(StringWrapper wrapper) { - return this.uuidMap.containsKey(wrapper); - } - - public void handleShutdown() { - this.players.clear(); - this.uuidMap.clear(); - } - - @Nullable public String getName(UUID uuid) { - if (uuid == null) { - return null; - } - StringWrapper name = this.uuidMap.inverse().get(uuid); - if (name != null) { - return name.value; - } - return null; - } - - @Nullable public UUID getUUID(String name, RunnableVal ifFetch) { - if (name.isEmpty()) { - return null; - } - // check online - PlotPlayer player = getPlayer(name); - if (player != null) { - return player.getUUID(); - } - // check cache - StringWrapper wrap = new StringWrapper(name); - UUID uuid = this.uuidMap.get(wrap); - if (uuid != null) { - return uuid; - } - // Read from disk OR convert directly to offline UUID - if (Settings.UUID.OFFLINE && !StringMan.contains(name, ';')) { - uuid = this.uuidWrapper.getUUID(name); - add(new StringWrapper(name), uuid); - return uuid; - } - if ((ifFetch != null)) { - fetchUUID(name, ifFetch); - return null; - } - return null; - } - - @NotNull public UUID getUUID(PlotPlayer player) { - return this.uuidWrapper.getUUID(player); - } - - public UUID getUUID(OfflinePlotPlayer player) { - return this.uuidWrapper.getUUID(player); - } - - @Nullable public PlotPlayer getPlayer(UUID uuid) { - String name = getName(uuid); - if (name != null) { - return getPlayer(name); - } - return null; - } - - public PlotPlayer getPlayer(String name) { - return this.players.get(name); - } - - public Map getPlayers() { - return this.players; - } - -} diff --git a/Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java b/Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java index 81a42bacd..32bbbb6bc 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java @@ -30,6 +30,7 @@ import com.google.common.cache.CacheBuilder; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.UUID; import java.util.function.Consumer; @@ -73,4 +74,8 @@ public class CacheUUIDService implements UUIDService, Consumer } } + @Override @NotNull public Collection getImmediately() { + return this.usernameCache.asMap().values(); + } + } diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDMapping.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDMapping.java index 798d586ff..35a4c6c2c 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDMapping.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDMapping.java @@ -25,6 +25,7 @@ */ package com.plotsquared.core.uuid; +import lombok.EqualsAndHashCode; import org.jetbrains.annotations.NotNull; import java.util.UUID; @@ -32,7 +33,7 @@ import java.util.UUID; /** * A pair consisting of a UUID and a username */ -public class UUIDMapping { +@EqualsAndHashCode public class UUIDMapping { private final UUID uuid; private final String username; diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java index 7add9ef8a..6d85db51f 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java @@ -35,13 +35,16 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.function.BiConsumer; import java.util.function.Consumer; /** @@ -181,10 +184,16 @@ public class UUIDPipeline { * @param username Username * @param uuid UUID consumer */ - public void getSingle(@NotNull final String username, @NotNull final Consumer uuid) { - this.getUUIDs(Collections.singletonList(username)).thenAccept(uuids -> { - if (!uuids.isEmpty()) { - uuid.accept(uuids.get(0).getUuid()); + public void getSingle(@NotNull final String username, @NotNull final BiConsumer uuid) { + this.getUUIDs(Collections.singletonList(username)).whenComplete((uuids, throwable) -> { + if (throwable != null) { + uuid.accept(null, throwable); + } else { + if (!uuids.isEmpty()) { + uuid.accept(uuids.get(0).getUuid(), null); + } else { + uuid.accept(null, null); + } } }); } @@ -195,10 +204,16 @@ public class UUIDPipeline { * @param uuid UUID * @param username Username consumer */ - public void getSingle(@NotNull final UUID uuid, @NotNull final Consumer username) { - this.getNames(Collections.singletonList(uuid)).thenAccept(uuids -> { - if (!uuids.isEmpty()) { - username.accept(uuids.get(0).getUsername()); + public void getSingle(@NotNull final UUID uuid, @NotNull final BiConsumer username) { + this.getNames(Collections.singletonList(uuid)).whenComplete((uuids, throwable) -> { + if (throwable != null) { + username.accept(null, throwable); + } else { + if (!uuids.isEmpty()) { + username.accept(uuids.get(0).getUsername(), null); + } else { + username.accept(null, null); + } } }); } @@ -274,4 +289,18 @@ public class UUIDPipeline { }, this.executor); } + /** + * Get as many UUID mappings as possible under the condition + * that the operation cannot be blocking (for an extended amount of time) + * + * @return All mappings that could be provided immediately + */ + @NotNull public final Collection getAllImmediately() { + final Set mappings = new LinkedHashSet<>(); + for (final UUIDService service : this.getServiceListInstance()) { + mappings.addAll(service.getImmediately()); + } + return mappings; + } + } diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java index 468de09b2..25588305e 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java @@ -27,6 +27,8 @@ package com.plotsquared.core.uuid; import org.jetbrains.annotations.NotNull; +import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.UUID; @@ -53,4 +55,14 @@ public interface UUIDService { */ @NotNull List getUUIDs(@NotNull final List usernames); + /** + * Get as many UUID mappings as possible under the condition + * that the operation cannot be blocking (for an extended amount of time) + * + * @return All mappings that could be provided immediately + */ + default @NotNull Collection getImmediately() { + return Collections.emptyList(); + } + } diff --git a/Core/src/test/java/com/plotsquared/core/plot/util/UUIDHandlerImplementationTest.java b/Core/src/test/java/com/plotsquared/core/plot/util/UUIDHandlerImplementationTest.java index 291461478..9bcad05bd 100644 --- a/Core/src/test/java/com/plotsquared/core/plot/util/UUIDHandlerImplementationTest.java +++ b/Core/src/test/java/com/plotsquared/core/plot/util/UUIDHandlerImplementationTest.java @@ -28,15 +28,14 @@ package com.plotsquared.core.plot.util; import com.plotsquared.core.database.AbstractDBTest; import com.plotsquared.core.database.DBFunc; import com.plotsquared.core.util.task.RunnableVal; -import com.plotsquared.core.util.uuid.UUIDHandlerImplementation; -import com.plotsquared.core.util.uuid.UUIDWrapper; +import com.plotsquared.core.util.uuid.OfflinePlayerService; import org.junit.Before; import java.util.UUID; public class UUIDHandlerImplementationTest extends UUIDHandlerImplementation { - public UUIDHandlerImplementationTest(UUIDWrapper wrapper) { + public UUIDHandlerImplementationTest(OfflinePlayerService wrapper) { super(wrapper); }