From f901ce2793eedd0909eaa22a9c1ee6d209b377a5 Mon Sep 17 00:00:00 2001 From: ryanhamshire Date: Wed, 19 Nov 2014 18:43:44 -0800 Subject: [PATCH] Perf: Offline player lookup by name. By searching only players who've been online recently, the search is made MUCH faster without trading a great deal of RAM to get it. --- .../GriefPrevention/DataStore.java | 2 +- .../GriefPrevention/GriefPrevention.java | 74 +++++++++++++------ .../GriefPrevention/PlayerEventHandler.java | 4 + 3 files changed, 57 insertions(+), 23 deletions(-) diff --git a/src/me/ryanhamshire/GriefPrevention/DataStore.java b/src/me/ryanhamshire/GriefPrevention/DataStore.java index 7b6cce5..ff5220e 100644 --- a/src/me/ryanhamshire/GriefPrevention/DataStore.java +++ b/src/me/ryanhamshire/GriefPrevention/DataStore.java @@ -1011,7 +1011,7 @@ public abstract class DataStore this.addDefault(defaults, Messages.TransferClaimPermission, "That command requires the administrative claims permission.", null); this.addDefault(defaults, Messages.TransferClaimMissing, "There's no claim here. Stand in the administrative claim you want to transfer.", null); this.addDefault(defaults, Messages.TransferClaimAdminOnly, "Only administrative claims may be transferred to a player.", null); - this.addDefault(defaults, Messages.PlayerNotFound, "Player not found.", null); + this.addDefault(defaults, Messages.PlayerNotFound, "No player by that name has logged in recently.", null); this.addDefault(defaults, Messages.TransferTopLevel, "Only top level claims (not subdivisions) may be transferred. Stand outside of the subdivision and try again.", null); this.addDefault(defaults, Messages.TransferSuccess, "Claim transferred.", null); this.addDefault(defaults, Messages.TrustListNoClaim, "Stand inside the claim you're curious about.", null); diff --git a/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java b/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java index 60547c0..561be0e 100644 --- a/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java +++ b/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java @@ -302,6 +302,35 @@ public class GriefPrevention extends JavaPlugin } } + int playersCached = 0; + OfflinePlayer [] offlinePlayers = this.getServer().getOfflinePlayers(); + long now = System.currentTimeMillis(); + final long TENDAYS = 1000 * 60 * 60 * 24 * 10; + for(OfflinePlayer player : offlinePlayers) + { + try + { + String playerName = player.getName(); + UUID playerID = player.getUniqueId(); + if(playerName == null || playerID == null) continue; + long absentMilliseconds = now - player.getLastPlayed(); + + //if the player has been seen in the last 10 days, cache his name/UUID pair + if(absentMilliseconds < TENDAYS) + { + this.playerNameToIDMap.put(playerName, playerID); + this.playerNameToIDMap.put(playerName.toLowerCase(), playerID); + playersCached++; + } + } + catch(Exception e) + { + e.printStackTrace(); + } + } + + AddLogEntry("Cached " + playersCached + " recent players."); + AddLogEntry("Boot finished."); } @@ -986,7 +1015,7 @@ public class GriefPrevention extends JavaPlugin return true; } - OfflinePlayer targetPlayer = this.resolvePlayerByName(args[0], true); + OfflinePlayer targetPlayer = this.resolvePlayerByName(args[0]); if(targetPlayer == null) { GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound); @@ -1123,7 +1152,7 @@ public class GriefPrevention extends JavaPlugin //validate player argument or group argument if(!args[0].startsWith("[") || !args[0].endsWith("]")) { - otherPlayer = this.resolvePlayerByName(args[0], true); + otherPlayer = this.resolvePlayerByName(args[0]); if(!clearPermissions && otherPlayer == null && !args[0].equals("public")) { GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound); @@ -1554,7 +1583,7 @@ public class GriefPrevention extends JavaPlugin if(args.length != 1) return false; //try to find that player - OfflinePlayer otherPlayer = this.resolvePlayerByName(args[0], true); + OfflinePlayer otherPlayer = this.resolvePlayerByName(args[0]); if(otherPlayer == null) { GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound); @@ -1604,7 +1633,7 @@ public class GriefPrevention extends JavaPlugin //otherwise try to find the specified player else { - otherPlayer = this.resolvePlayerByName(args[0], true); + otherPlayer = this.resolvePlayerByName(args[0]); if(otherPlayer == null) { GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound); @@ -1745,7 +1774,7 @@ public class GriefPrevention extends JavaPlugin } //otherwise, find the specified player - OfflinePlayer targetPlayer = this.resolvePlayerByName(args[0], true); + OfflinePlayer targetPlayer = this.resolvePlayerByName(args[0]); if(targetPlayer == null) { GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound); @@ -1932,7 +1961,7 @@ public class GriefPrevention extends JavaPlugin if(args.length != 1) return false; //find the specified player - OfflinePlayer targetPlayer = this.resolvePlayerByName(args[0], true); + OfflinePlayer targetPlayer = this.resolvePlayerByName(args[0]); if(targetPlayer == null) { GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound); @@ -2070,7 +2099,7 @@ public class GriefPrevention extends JavaPlugin else { - otherPlayer = this.resolvePlayerByName(recipientName, false); + otherPlayer = this.resolvePlayerByName(recipientName); if(otherPlayer == null && !recipientName.equals("public") && !recipientName.equals("all")) { GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound); @@ -2215,7 +2244,8 @@ public class GriefPrevention extends JavaPlugin } //helper method to resolve a player by name - private OfflinePlayer resolvePlayerByName(String name, boolean searchOffline) + ConcurrentHashMap playerNameToIDMap = new ConcurrentHashMap(); + private OfflinePlayer resolvePlayerByName(String name) { //try online players first Player targetPlayer = this.getServer().getPlayerExact(name); @@ -2224,22 +2254,22 @@ public class GriefPrevention extends JavaPlugin targetPlayer = this.getServer().getPlayer(name); if(targetPlayer != null) return targetPlayer; - OfflinePlayer bestMatch = null; - if(searchOffline) + UUID bestMatchID = null; + + //try exact match first + bestMatchID = this.playerNameToIDMap.get(name); + + //if failed, try ignore case + if(bestMatchID == null) { - //then search offline players - OfflinePlayer [] players = this.getServer().getOfflinePlayers(); - for(int i = 0; i < players.length; i++) - { - if(players[i].getName() != null && players[i].getName().equalsIgnoreCase(name)) - { - bestMatch = players[i]; - if(bestMatch.getName().equals(name)) return bestMatch; - } - } + bestMatchID = this.playerNameToIDMap.get(name.toLowerCase()); } - - return bestMatch; + if(bestMatchID == null) + { + return null; + } + + return this.getServer().getOfflinePlayer(bestMatchID); } //helper method to resolve a player name from the player's UUID diff --git a/src/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java b/src/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java index 27bf75a..f713bb7 100644 --- a/src/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java +++ b/src/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java @@ -587,6 +587,10 @@ class PlayerEventHandler implements Listener //in case player has changed his name, on successful login, update UUID > Name mapping GriefPrevention.cacheUUIDNamePair(player.getUniqueId(), player.getName()); + + //also cache the reverse mapping + GriefPrevention.instance.playerNameToIDMap.put(player.getName(), playerID); + GriefPrevention.instance.playerNameToIDMap.put(player.getName().toLowerCase(), playerID); } //when a player spawns, conditionally apply temporary pvp protection