• Es freut uns dass du in unser Minecraft Forum gefunden hast. Hier kannst du mit über 130.000 Minecraft Fans über Minecraft diskutieren, Fragen stellen und anderen helfen. In diesem Minecraft Forum kannst du auch nach Teammitgliedern, Administratoren, Moderatoren , Supporter oder Sponsoren suchen. Gerne kannst du im Offtopic Bereich unseres Minecraft Forums auch über nicht Minecraft spezifische Themen reden. Wir hoffen dir gefällt es in unserem Minecraft Forum!

Asynchrone Methodenaufrufe mit Minecraft Inhalt

CubBossa

Schafhirte
Registriert
17 Juli 2015
Beiträge
125
Diamanten
369
Minecraft
CubBossa
Hallöchen, ich schreib grad nochmal nen Beitrag wegen nem anderen Anliegen, bei dem ich auf google-art nicht weiterkam :D
Und zwar kann ich ja mit Callbacks einen Rechenprozess, bzw. zum Beispiel das Warten auf die Antwort von Bungee oder der MySQL, asynchron ich sag mal in den "Hintergrund" verlegen, sodass der Server nicht einfriert.
Nun hab ich gelesen, man soll keine Minecraft Methoden verwenden wenn man nicht im Hauptthread ist. Stimmt das so?
Asynchronous tasks should never access any API in Bukkit. Great care should be taken to assure the thread-safety of asynchronous tasks
Wenn ich nun also beispielsweise die Information einer Datenbank lade, und dem Spieler im Callback dann sende. Würde ich erstmal drauf achten, dass es eine final Player variable ist. (Soweit mit diesem Tutorial)
Dann würde ich im callback einen null-check machen, falls der spieler sich ausgeloggt hat? und dann die daten senden. Ich denke eine Chatmessage wird nicht so fatal sein, aber welche Methoden darf ich denn jetzt nicht mehr in callbacks verwenden und welche schon?
Und wie mache ich den Vorgang in einem Callback wieder synchron damit ich alle Methoden sorglos verwenden kann? Einfach, indem ich einen sync Scheduler starte? Oder habe ich hier etwas total falsch aufgefasst

Dankbar für jede Hilfe und alle Geduld ^^
Grüße, CubBossa
 

EinDev

Minecrafter
Registriert
22 März 2016
Beiträge
23
Diamanten
112
Lustig dass du das fragst, diese Frage habe ich mir letztens erst selbst gestellt.
Genau, von Seitens Bukkit wird empfohlen, keine Methode außerhalb des Main-Threads aufzurufen.
Aber der Chat ist da eine Ausnahme, da das ganze Handling Asynchron stattfindet. Daher kannst du ohne Sorgen Chatnachrichten Asynchron versenden.
Aber nochmal hier der Hinweis: Das gilt nur für Chatnachrichten. Andere Aufrufe der Bukkit-API solltest du immer im Main-Thread ausführen.

Dann würde ich im callback einen null-check machen, falls der spieler sich ausgeloggt hat?
Das musst du nicht, wenn der Spieler offline ist wird die Nachricht AFAIK einfach nicht gesendet ;)

Ich denke eine Chatmessage wird nicht so fatal sein
Auch wenn es in diesem Fall zutrifft, liegt das keinesfalls an der "unfatalität" der Chatmessage. Selbst in einer simplen HashMap können Fehler auftreten wenn nicht aufgepasst wird, dass niemand gleichzeitig drauf zugreift. (Stichwort: Thread-Safe)

Und wie mache ich den Vorgang in einem Callback wieder synchron damit ich alle Methoden sorglos verwenden kann?
Dazu hilft einfach BukkitScheduler#runTask() (Link)
 

Chrisliebär❤️

nur echt mit ❤️
Moderator
Registriert
19 Mai 2014
Beiträge
1.675
Diamanten
830
@EinDev hat da eigentlich schon den wichtigsten Teil genannt: Die Chat Message API ist Threadsafe. Aber NUR DIE, das heißt du darfst darin keine anderen API Calls machen um beispielsweise andere Informationen für die Nachricht zu bekommen.

Das musst du nicht, wenn der Spieler offline ist wird die Nachricht AFAIK einfach nicht gesendet
Hier liegt ein ganz großes Missverständnis, vermutlich von euch beiden, aber auf jeden fall von @CubBossa. Wenn du die Referenz auf Bukkit Libraryobjekte speicherst, musst du genau aufpassen was du tust. Die Bukkit API erlaubt das nicht. Entsprechend musst du sicherstellen, dass du in jedem Fall nur gültige Objekte benutzt. Der Spieler wird nicht plötzlich null sein, wenn der Spieler den Server verlassen hat. Das ist nur eine Referenz, das Objekt selbst wird einfach nicht mehr von Bukkit aktualisiert. Die Benutzung von final ist auch komplett egal. Final hat im Bezug auf Threadsicherheit zwar eine wichtige Bedeutung, aber die ist eher technischer Natur und hängt mit vollkommen anderen Dingen zusammen.

Du kannst natürlich davon ausgehen, dass du einem Spielerobjekt, welches nicht länger auf dem Server ist, trotzdem Chatnachrichten schicken kannst. Aber das kann dann halt kaputt gehen. Hier muss man dann ganz genau die Feinheiten betrachten welche Garantien die API macht und welche Dinge man lediglich tun kann, weil man weiß, dass nichts schief geht. Letzteres kann sich aber mit jedem Update von Bukkit ändern.
 

CubBossa

Schafhirte
Registriert
17 Juli 2015
Beiträge
125
Diamanten
369
Minecraft
CubBossa
Okay wow das war ja schon sehr informativ :D
Jetzt taten sich mir doch noch ein paar Fragen auf. Zum Beispiel hast du EinDev geschrieben, dass ich sicherstellen muss, dass nicht mehrere Zugriffe gleichzeitig passieren. Ist das der zeitpunkt, wo synchronized verwendung findet?

Und den Rest der Fragen würde ich am Besten an nem Beispiel im JoinListener fragen:
Java:
        DataManager.getInstance().getSetting(player.getUniqueId(), Setting.LOBBY_HIDE_PLAYERS, 0, new DatabaseCallback<MysqlSetting>() {
            @Override
            public void run(MysqlSetting result) {
                if(result.getValue() == 1) {
                    for (Player all : Bukkit.getOnlinePlayers()) {
                        player.hidePlayer(Main.getInstance(), all);
                    }
                }
            }
        });
Also nach allem was ich gelernt habe ist das hier ja ne katastrophe, richtig?
Weil die hidePlayer() methode ja nicht asynchron aufgerufen werden soll. Würde ich dann einfach noch nen synced task um die forschleife schachteln? Oder bin ich jetzt auf nem komplett falschen weg^^
Würde ich den Spieler jetzt final machen?
Muss ich abfragen ob der Spieler "player" online ist?

Ich les ja oft in foren, dass man selbst erst mal dies oder das lernen soll, wenn ihr da hilfreiche Links für naja unstudierte habt ^^ würde ich mich auch freuen. Danke schonmal
 

EinDev

Minecrafter
Registriert
22 März 2016
Beiträge
23
Diamanten
112
Ist das der zeitpunkt, wo synchronized verwendung findet?
Das hilft dir in dem Fall nicht weiter. In dem Fall einfach in dem Callback von BukkitScheduler#runTask() ausführen.

Also nach allem was ich gelernt habe ist das hier ja ne katastrophe, richtig?
Naja in ca. 90% der Fälle wird es funktionieren. In allen anderen Fällen - wer weiß was da passiert.

Würde ich dann einfach noch nen synced task um die forschleife schachteln?
Ja, ich würde aber nicht das Player-Objekt zwischen beiden Kontexten übernehmen, sondern stattdessen die UUID. Dann im Main-Thread dann abfragen, ob die UUID überhaupt noch online ist. Falls ja, kannst du dir ja über Bukkit.getPlayer das aktuelle Playerobjekt neu holen.
Nehmen wir z.B. an der Spieler disconnected und verbindet sich neu. In dem Fall ist das alte Spielerobjekt vermutlich ungültig, obwohl der Spieler online ist.

Spieler final machen macht in diesem Fall keinen Unterschied.

Mit Links kann ich dir leider nicht dienen, ich müsste selbst erstmal anfangen zu googlen ;)
 
Oben