-
-
Save aikar/0f7e9e67e72a3b006a81 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 2dda94416930a1f2565127a51a5c53ac137e6f1e Mon Sep 17 00:00:00 2001 | |
From: Aikar <aikar@aikar.co> | |
Date: Sat, 23 Aug 2014 15:11:40 -0400 | |
Subject: [PATCH] Improvements to Player Lookup | |
Minecraft and CraftBukkit both use Arrays to store online players, | |
and any time a player needs to be looked up by name the system iterates | |
all online players and does a name comparison. | |
This is very ineffecient and can reduce performance on servers with high player count. | |
By using a map based approach for player lookups, player lookup should | |
be consistent in performance regardless of how many players are online. | |
diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java | |
index ab1d9a5..f49ebce 100644 | |
--- a/src/main/java/net/minecraft/server/PlayerList.java | |
+++ b/src/main/java/net/minecraft/server/PlayerList.java | |
@@ -49,6 +49,31 @@ public abstract class PlayerList { | |
private static final SimpleDateFormat g = new SimpleDateFormat("yyyy-MM-dd \'at\' HH:mm:ss z"); | |
private final MinecraftServer server; | |
public final List<EntityPlayer> players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety | |
+ // Spigot start | |
+ public final Map<String, EntityPlayer> playerMap = new java.util.HashMap<String, EntityPlayer>() { | |
+ @Override | |
+ public EntityPlayer put(String key, EntityPlayer value) { | |
+ return super.put(key.toLowerCase(), value); | |
+ } | |
+ | |
+ @Override | |
+ public EntityPlayer get(Object key) { | |
+ // put the .playerConnection check done in other places here | |
+ EntityPlayer player = super.get(key instanceof String ? ((String)key).toLowerCase() : key); | |
+ return (player != null && player.playerConnection != null) ? player : null; | |
+ } | |
+ | |
+ @Override | |
+ public boolean containsKey(Object key) { | |
+ return super.containsKey(key instanceof String ? ((String)key).toLowerCase() : key); | |
+ } | |
+ | |
+ @Override | |
+ public EntityPlayer remove(Object key) { | |
+ return super.remove(key instanceof String ? ((String)key).toLowerCase() : key); | |
+ } | |
+ }; | |
+ // Spigot end | |
private final Map<UUID, EntityPlayer> j = Maps.newHashMap(); | |
private final GameProfileBanList k; | |
private final IpBanList l; | |
@@ -289,6 +314,7 @@ public abstract class PlayerList { | |
this.players.add(entityplayer); | |
this.j.put(entityplayer.getUniqueID(), entityplayer); | |
// this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[] { entityplayer})); // CraftBukkit - replaced with loop below | |
+ this.playerMap.put(entityplayer.getName(), entityplayer); // Spigot | |
WorldServer worldserver = this.server.getWorldServer(entityplayer.dimension); | |
// CraftBukkit start | |
@@ -358,6 +384,7 @@ public abstract class PlayerList { | |
worldserver.kill(entityplayer); | |
worldserver.getPlayerChunkMap().removePlayer(entityplayer); | |
this.players.remove(entityplayer); | |
+ this.playerMap.remove(entityplayer.getName()); // Spigot | |
UUID uuid = entityplayer.getUniqueID(); | |
EntityPlayer entityplayer1 = (EntityPlayer) this.j.get(uuid); | |
@@ -393,8 +420,11 @@ public abstract class PlayerList { | |
UUID uuid = EntityHuman.a(gameprofile); | |
ArrayList arraylist = Lists.newArrayList(); | |
- EntityPlayer entityplayer; | |
- | |
+ // Spigot start | |
+ EntityPlayer entityplayer = a(uuid); // PAIL Rename getPlayer | |
+ if (entityplayer != null) { | |
+ /* | |
+ // Spigot end | |
for (int i = 0; i < this.players.size(); ++i) { | |
entityplayer = (EntityPlayer) this.players.get(i); | |
if (entityplayer.getUniqueID().equals(uuid)) { | |
@@ -405,7 +435,7 @@ public abstract class PlayerList { | |
Iterator iterator = arraylist.iterator(); | |
while (iterator.hasNext()) { | |
- entityplayer = (EntityPlayer) iterator.next(); | |
+ entityplayer = (EntityPlayer) iterator.next();*/ // Spigot | |
savePlayerFile(entityplayer); // CraftBukkit - Force the player's inventory to be saved | |
entityplayer.playerConnection.disconnect("You logged in from another location"); | |
} | |
@@ -1020,6 +1050,7 @@ public abstract class PlayerList { | |
} | |
public EntityPlayer getPlayer(String s) { | |
+ if (true) { return playerMap.get(s); } // Spigot | |
Iterator iterator = this.players.iterator(); | |
EntityPlayer entityplayer; | |
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java | |
index 8be0698..1bc684f 100644 | |
--- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java | |
+++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java | |
@@ -144,14 +144,7 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa | |
} | |
public Player getPlayer() { | |
- for (Object obj : server.getHandle().players) { | |
- EntityPlayer player = (EntityPlayer) obj; | |
- if (player.getUniqueID().equals(getUniqueId())) { | |
- return (player.playerConnection != null) ? player.playerConnection.getPlayer() : null; | |
- } | |
- } | |
- | |
- return null; | |
+ return Bukkit.getServer().getPlayer(getUniqueId()); // Spigot - replace whole method | |
} | |
@Override | |
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java | |
index fd41124..54b81e9 100644 | |
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java | |
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java | |
@@ -401,7 +401,13 @@ public final class CraftServer implements Server { | |
public Player getPlayer(final String name) { | |
Validate.notNull(name, "Name cannot be null"); | |
- Player found = null; | |
+ // Spigot start | |
+ Player found = getPlayerExact(name); | |
+ if (found != null) { | |
+ return found; | |
+ } | |
+ // Spigot end | |
+ | |
String lowerName = name.toLowerCase(); | |
int delta = Integer.MAX_VALUE; | |
for (Player player : getOnlinePlayers()) { | |
@@ -420,22 +426,15 @@ public final class CraftServer implements Server { | |
@Override | |
@Deprecated | |
public Player getPlayerExact(String name) { | |
- Validate.notNull(name, "Name cannot be null"); | |
- | |
- String lname = name.toLowerCase(); | |
- | |
- for (Player player : getOnlinePlayers()) { | |
- if (player.getName().equalsIgnoreCase(lname)) { | |
- return player; | |
- } | |
- } | |
- | |
- return null; | |
+ // Spigot start - replace whole method | |
+ EntityPlayer player = playerList.playerMap.get(name); | |
+ return player != null ? player.getBukkitEntity() : null; | |
+ // Spigot end | |
} | |
@Override | |
public Player getPlayer(UUID id) { | |
- EntityPlayer player = playerList.a(id); | |
+ EntityPlayer player = playerList.a(id); // PAIL Rename getPlayer | |
if (player != null) { | |
return player.getBukkitEntity(); | |
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java | |
index 3162541..dba91c2 100644 | |
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java | |
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java | |
@@ -105,13 +105,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { | |
} | |
public boolean isOnline() { | |
- for (Object obj : server.getHandle().players) { | |
- EntityPlayer player = (EntityPlayer) obj; | |
- if (player.getName().equalsIgnoreCase(getName())) { | |
- return true; | |
- } | |
- } | |
- return false; | |
+ return server.getPlayer(getUniqueId()) != null; // Spigot - replace whole method | |
} | |
public InetSocketAddress getAddress() { | |
-- | |
1.9.1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment