Ich möchte mir hier kurz zu dem "speicher niemals Player objekte" Käse melden. Es ist absoluter Schwachsinn nicht die Spieler Objekte zu referenzieren. Warum? Das ist ganz einfach:
Wenn man den Namen oder die UUID speichert muss man jedesmal einen Lookup machen wenn man das Spielerobjekt wieder haben will um damit zu arbeiten. Nun gucken wir uns doch mal an was bei einem Lookup passiert:
Code:
public Player getPlayer(final String name) {
Validate.notNull(name, "Name cannot be null");
Player found = null;
String lowerName = name.toLowerCase();
int delta = Integer.MAX_VALUE;
for (Player player : getOnlinePlayers()) {
if (player.getName().toLowerCase().startsWith(lowerName)) {
int curDelta = player.getName().length() - lowerName.length();
if (curDelta < delta) {
found = player;
delta = curDelta;
}
if (curDelta == 0) break;
}
}
return found;
}
Bukkit.getServer().getPlayer(String) iteriert also durch alle Spieler und guckt ob der Name den wir suchen in dem anderen Namen enthalten ist und gibt den Spieler zurück welcher am wenigsten Differenz hat. Schonmal kacke und inperformant.
Code:
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;
}
Bukkit.getServer().getPlayerExact(String) iteriert auch, berechnet aber keine Differenzen. D.h. es muss genau der Spieler online sein den wir suchen. Schon weitaus besser aber immernoch eine Iteration über alle Spieler.
Code:
public Player getPlayer(UUID id) {
for (Player player : getOnlinePlayers()) {
if (player.getUniqueId().equals(id)) {
return player;
}
}
return null;
}
Bukkit.getServer().getPlayer(UUID) sieht nicht viel anders aus als getPlayerExact(String) und iteriert auch wie diese.
D.h. wenn man einen Namen oder eine UUID hat iteriert man um an das Spieler Objekt zu kommen im schlimmsten Fall immer durch alle Spieler die gerade online sind. Das verbraucht CPU und ist wie oben schon gesagt unnötig.
Es gibt zwei Sachen die es zu beachten gibt warum viele meinen das Player Objekte speichern schlecht ist:
1. Es verbraucht mehr RAM
2. Es ist schlecht für den Server
Zu 1. bleibt zu sagen das die Referenz auf ein Objekt (welches z.b. in einer Liste oder Map abgelegt wird) immer gleich groß ist egal was für ein Objekt sich dahinter verbirgt. Also verbraucht eine Referenz auf einen String/UUID genausoviel RAM wie eine auf ein Player Objekt.
Zu 2. es ist nur dann schlecht für den Server wenn man das Player Objekt nie wieder freigibt. Normalerweilse handelt es sich bei Listen/Maps um harte Referenzen (die JVM wird das Objekt nicht freigeben solange noch harte Referenzen bestehen). Es gibt nun zwei Lösungsansätze davon. Der (finde ich) beste Ansatz ist das lösen der harten Referenzen beim verlassen des Spielers. List.remove(Player) oder Map.remove(Player) löst die harte Referenz komplett auf. Wem das aber zu blöd ist kann immernoch zur WeakReference (schwachen Referenz) greifen. Diese zählt nicht zu den harten Referenzen und die JVM ignoriert diese wenn es darum geht ein Objekt zu löschen.
http://docs.oracle.com/javase/7/docs/api/java/lang/ref/WeakReference.html
Soviel zum Thema speichert NIEMALS ein Player Objekt