Coding mit Java | Java-basierten APIs

  • Ersteller Ersteller ij9F_i0FaF-d9lrDSDDpDbfo
  • Erstellt am Erstellt am
Status
Für weitere Antworten geschlossen.
Ich habe eine ArrayList und will das an alle Spieler die in der ArrayList sind eine narchicht gesendet wird aber in Intellj wird das schon als fehler angezeigt
Code:
if(Lobby.size() > 8){
                    for(Player l : Lobby) {
                        l.sendMessage("§aDas Spiel beginnt in 60 Sekunden!");
                    }

Die ArrayList habe ich natürlich auch schon ist halt nur weiter oben ^^
Ersteinmal wurde im Bukkit-Forum empfohlen ChatColor.FARBE zu nehmen, statt "§FARBE".
Und als zweites... Was ist der Fehler?
 
Fehler
Incompaible
types required: org.bukkit.entity.player
found: Java.lang.string
 
Hey :)
wie ich bereits sagte , bin ich neu in java :)
Dann lern Java. Das sieht grausam aus.

Man kann es zum Beispiel so machen:
Code:
public static void firework(Player p, int times, int delay, Type type, Color color)
 {
 for(int i = 1; i <= times; i++)
 {
 Bukkit.getScheduler().scheduleSyncDelayedTask(DeineMain.getInstance(), new Runnable()
 {
 public void run()
 {
 Firework fw = (Firework) p.getWorld().spawnEntity(p.getLocation(), EntityType.FIREWORK);
 FireworkMeta fwm = fw.getFireworkMeta();
 FireworkEffect effect = FireworkEffect.builder().withColor(color).with(type).build();
 fwm.addEffect(effect);
 fwm.setPower((int) 0.9);
 fw.setFireworkMeta(fwm);
 }
 }, delay);
 }
 }
 
EDIT : Da hat der Tim sich in der Fehlermeldung verlesen.

Bei ArrayLists für Spieler NIEMALS (eig wirklich nie, seeehr selten Ausnahmen) den Player speichern , immer String und dann den Namen.

Zu dem Beitrag mit dem Incompatible Error. Du vergleichst da ein Objekt vom Typen String mit einem von Typ Player.
 
Aber man sollte es sich angewöhnen, vor allem, da es keinen Vorteil bringt den Playername statt der UUID zu speichern.
Ich sehe den kompletten Vorteil, die UUID statt den Namen zu speichern. Die UUID ist zwar länger, aber je nach dem, was man für ein Serverkonzept hat, bleibt ein Server auch mal etwas länger an.
Wenn man dann den Namen speichert, sich einer umbenennt und dann drauf kommt, ist alles anders (für ihn).

Ja schon, derzeit aber noch nicht verpflichtend.
Eigentlich schon. Direkt die UUID speichern, und man hat am Ende weniger zu tuten, wenn die Namensänderung eingeführt wird. (Ich weis, das heißt 'zu tun')
 
EDIT : Da hat der Tim sich in der Fehlermeldung verlesen.

Bei ArrayLists für Spieler NIEMALS (eig wirklich nie, seeehr selten Ausnahmen) den Player speichern , immer String und dann den Namen.

Zu dem Beitrag mit dem Incompatible Error. Du vergleichst da ein Objekt vom Typen String mit einem von Typ Player.

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 :D
 
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 :D
Genauso gut ist bei Maps die Nutzung von WeakHashMap ^^
 
@geNAZt Mal so ne rein theorethische Frage... :D
Problem: ein Game-Framework mit vielen Attributen, u.a. einer Lobby. Das Spiel besteht aus mehreren Phasen (GameStates) nehmen wir mal an, das Lobby-Objekt hat (ist zwar unwahrscheinlich aber dies ist ja nur ein Beispiel) sehr viele Attribute, die eine gewisse Menge an RAM benötigen, das Game-Framework soll aber möglichst RAM sparend sein und die Lobby hat nur eine Referenz, nämlich in der Game klasse.
Meine Frage an dich ist:
Würdest du die Lobby nachdem der GameState > Lobby ist auf null setzen? (Sie wird nicht mehr gebraucht)

Deine Meinung würde mich mal interessieren :)
 
Ja. Aber Java wird die eh erst aufräumen wenn Java den RAM braucht oder du ander GC Einstellungen hast.
 
Status
Für weitere Antworten geschlossen.

Soziale Medien

  • X
  • TikTok

Über uns

  • GommeHD.net ist einer der größten Minecraft-Server der Welt. Dir gefällt unser Server? Dann unterstütze uns durch einen Kauf im Shop!
  • Shop