diff --git a/src/main/java/com/lishid/openinv/OpenInv.java b/src/main/java/com/lishid/openinv/OpenInv.java index 3e6c20ea..2b66f6c2 100644 --- a/src/main/java/com/lishid/openinv/OpenInv.java +++ b/src/main/java/com/lishid/openinv/OpenInv.java @@ -201,6 +201,72 @@ public void setPlayerAnyChestStatus(OfflinePlayer player, boolean status) { saveConfig(); } + /** + * Get an OfflinePlayer by name. + * + * @param name the name of the Player + * @return the OfflinePlayer, or null if no players have ever logged in + */ + public OfflinePlayer matchPlayer(String name) { + + // Warn if called on the main thread - if we resort to searching offline players, this may take several seconds. + if (getServer().isPrimaryThread()) { + getLogger().warning("Call to OpenInv#matchPlayer made on the main thread!"); + getLogger().warning("This can cause the server to hang, potentially severely."); + getLogger().warning("Trace:"); + for (StackTraceElement element : new Throwable().fillInStackTrace().getStackTrace()) { + getLogger().warning(element.toString()); + } + } + + OfflinePlayer player = getServer().getPlayerExact(name); + + if (player != null) { + return player; + } + + player = getServer().getOfflinePlayer(name); + + /* + * Compatibility: Pre-UUID, getOfflinePlayer always returns an OfflinePlayer. Post-UUID, + * getOfflinePlayer will return null if no matching player is found. To preserve + * compatibility, only return the player if they have played before. Ignoring current online + * status is fine, they'd have been found by getPlayerExact otherwise. + */ + if (player != null && player.hasPlayedBefore()) { + return player; + } + + player = getServer().getPlayer(name); + + if (player != null) { + return player; + } + + int bestMatch = Integer.MAX_VALUE; + for (OfflinePlayer offline : getServer().getOfflinePlayers()) { + if (offline.getName() == null) { + // Loaded by UUID only, name has never been looked up. + continue; + } + + // Compatibility: Lang3 is only bundled with 1.8+ + int currentMatch = org.apache.commons.lang.StringUtils.getLevenshteinDistance(name, offline.getName()); + + if (currentMatch == 0) { + return offline; + } + + if (currentMatch < bestMatch) { + bestMatch = currentMatch; + player = offline; + } + } + + // Only null if no players have played ever, otherwise even the worst match will do. + return player; + } + public static void ShowHelp(Player player) { player.sendMessage(ChatColor.GREEN + "/openinv - Open a player's inventory"); player.sendMessage(ChatColor.GREEN + " (aliases: oi, inv, open)"); diff --git a/src/main/java/com/lishid/openinv/commands/OpenEnderPluginCommand.java b/src/main/java/com/lishid/openinv/commands/OpenEnderPluginCommand.java index eb516d79..5299a9ae 100644 --- a/src/main/java/com/lishid/openinv/commands/OpenEnderPluginCommand.java +++ b/src/main/java/com/lishid/openinv/commands/OpenEnderPluginCommand.java @@ -17,9 +17,7 @@ package com.lishid.openinv.commands; import java.util.HashMap; -import java.util.List; -import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.OfflinePlayer; import org.bukkit.command.Command; @@ -75,20 +73,13 @@ public boolean onCommand(CommandSender sender, Command command, String label, St new BukkitRunnable() { @Override public void run() { - List matches = Bukkit.matchPlayer(name); - final OfflinePlayer offlinePlayer; - if (!matches.isEmpty()) { - offlinePlayer = matches.get(0); - } else { - offlinePlayer = Bukkit.getOfflinePlayer(name); - } - if (!player.isOnline()) { - return; - } + final OfflinePlayer offlinePlayer = plugin.matchPlayer(name); + if (offlinePlayer == null || !offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline()) { player.sendMessage(ChatColor.RED + "Player not found!"); return; } + new BukkitRunnable() { @Override public void run() { @@ -98,6 +89,7 @@ public void run() { openInventory(player, offlinePlayer); } }.runTask(plugin); + } }.runTaskAsynchronously(plugin); diff --git a/src/main/java/com/lishid/openinv/commands/OpenInvPluginCommand.java b/src/main/java/com/lishid/openinv/commands/OpenInvPluginCommand.java index 548aa190..441f2b48 100644 --- a/src/main/java/com/lishid/openinv/commands/OpenInvPluginCommand.java +++ b/src/main/java/com/lishid/openinv/commands/OpenInvPluginCommand.java @@ -17,9 +17,7 @@ package com.lishid.openinv.commands; import java.util.HashMap; -import java.util.List; -import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.OfflinePlayer; import org.bukkit.command.Command; @@ -75,20 +73,13 @@ public boolean onCommand(CommandSender sender, Command command, String label, St new BukkitRunnable() { @Override public void run() { - List matches = Bukkit.matchPlayer(name); - final OfflinePlayer offlinePlayer; - if (!matches.isEmpty()) { - offlinePlayer = matches.get(0); - } else { - offlinePlayer = Bukkit.getOfflinePlayer(name); - } - if (!player.isOnline()) { - return; - } + final OfflinePlayer offlinePlayer = plugin.matchPlayer(name); + if (offlinePlayer == null || !offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline()) { player.sendMessage(ChatColor.RED + "Player not found!"); return; } + new BukkitRunnable() { @Override public void run() { @@ -98,6 +89,7 @@ public void run() { openInventory(player, offlinePlayer); } }.runTask(plugin); + } }.runTaskAsynchronously(plugin); diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index ae0b2f76..35c0f65e 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: OpenInv main: com.lishid.openinv.OpenInv -version: 2.4.8 +version: 2.4.9 author: lishid authors: [Jikoo] description: >