Discord

  • 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!

Spigot Inventar/Enderchest eines Spielers in MySQL abspeichern

heras

Redstoneengineer
Mitglied seit
25 Juli 2019
Beiträge
38
Minecraft
xTailsPvP
Hallo,
Ich will einen Plugin machen bei dem das Inventar eines Spielers mit mehreren Servern verknüpft sein soll.
Also wenn ein Spieler in einem Server 5 Brote und 1 Steak hat und dann den Server wechselt, soll er bei dem anderen Server auch 5 Brote und 1 Steak haben. Ich hatte mir überlegt das beim Verlassen des 1. Servers die Items von dem Spieler in MySQL zu speichern und wenn er auf den anderen Server joint das die Items von Mysql genommen werden und auf das Inventar des Spielers eingefügt werden. Doch dann müsste ich 30 Items einzelnd pro Spieler in Mysql eintragen. Hätte jemand eine andere Idee wie ich das machen könnte oder muss ich das so machen das bei jedem Spieler 30 Items in Mysql gespeichert werden?
Es wäre sehr nett wenn ihr mir das helfen könntet!

Ich danke an allen die mir helfen werden schon im Voraus!
 

petomka

Redstoneengineer
Osterei Experte
Mitglied seit
8 Oktober 2012
Beiträge
36
Alter
20
Hallo,

grundsätzlich ist es natürlich möglich, auch solche komplexeren Daten in einer MySQL Datenbank zu speichern, da gibt es natürlich unterschiedliche Herangehensweisen. Ich hoffe aber, du denkst nicht daran, eine Tabelle zu erstellen, die (mehr als) 30 Spalten hat - wenn ja, dann solltest du dir mal dringend ein paar Dinge zu Normalisierung in Datenbanksystem ansehen (da gibt es natürlich sinnvolle und weniger sinnvolle Normalisierungen...).

Speichern in einem lesbaren (human readable) Format
Solltest du die Daten in deiner Datenbank für einen Menschen lesbar abspeichern wollen (wozu auch immer man das machen wollen würde in so einem Fall), kannst du deine Items z.B. als JSON-Object serialisieren und so abspeichern. Das JSON-Format können Mensch und Maschine gut lesen - lässt sich aber auch nicht viel optimieren.

Den JSON-String könntest du dann einfach als TEXT oder ähnliches speichern. Gson von Google könnte für so etwas sehr hilfreich sein, Dokumentationen davon findest du auf der verlinkten GitHub-Seite, sonst gibt es auch so reichlich Tutorials zu Gson im Internet.

Speichern als binäre Rohdaten
Andernfalls kannst du die Daten direkt als einzelne Bytes in die Datenbank schreiben, dafür gibt es in MySQL den eingebauten Datentyp BLOB (was für "Binary Large Object" steht). Da gibt es auch verschiedene größen für diesen (Quelle):
  • BLOB speichert 64KiB
  • MEDIUMBLOB speichert 16 MiB
  • LONGBLOB speichert 4 GiB
Ich würde dir empfehlen, die entsprechende Spalte in deiner Tabelle als MEDIUMBLOB anzulegen, da es bei umfangreichen Inventaren mit 64KiB doch sehr eng werden könnte (z.B. beschrieben Bücher o.Ä.).

Die Daten werden dann über Output- und InputStreams serialisiert bzw. deserialisiert (respektive). Zum Serialisieren eines ItemStacks könntest du z.B. mit einem OutputStream und einem BukkitObjectOutputStream so vorgehen:
Java:
private Blob serializeItemStack(Connection connection, ItemStack itemStack) throws Exception {
    Blob blob = connection.createBlob();
    try (OutputStream out = blob.setBinaryStream(1)) { //Mit 1 anfangen, nicht 0 - siehe Dokumentation.
        try (BukkitObjectOutputStream bukkitOut = new BukkitObjectOutputStream(out)) {
            bukkitOut.writeObject(itemStack);
            return blob;
        }
    }
}
Der Code ist bestimmt nicht optimal und soll auch nur als Beispiel dienen. Das musst du dann natürlich deinen Anforderungen entsprechend anpassen, du könntest z.B. direkt ein ganzes Array von ItemStacks serialisieren, davor würde ich dir aber empfehlen, in den Stream zuvor die größe des Arrays zu schreiben, dann ist es beim Deserialisieren direkt sehr einfach, da gleich bekannt ist, wie viele Objekte gelesen werden können.
Deserialisieren funktioniert übrigens sehr ähnlich, schaue dir dazu einfach mal das Interface Blob an und den BukkitObjectInputStream.

Die BukkitStreams arbeiten übrigens mit der ConfigurationSerializable-API zusammen (und funktioniert auch so ähnlich). Dazu gibt es auch ein paar gute Tutorials, z.B. [dieses hier].

Einen weiteren anderen Ansatz über Base64 kodierte Daten findest du [hier], vielleicht hilft dir das ja auch weiter und lernst davon noch etwas.
 

JOO200

Vorarbeiter
Osterei Experte
Mitglied seit
18 Dezember 2016
Beiträge
263
Um dir noch einige lästige Suchereien zu ersparen:

Wenn du in einem BungeeCord-Netzwerk arbeitest, dann wird das PlayerDisconnectEvent von dem verlassenden Server NACH dem AsyncPlayerPreLoginEvent von dem betretenden Server ausgeführt. Dadurch ist es nicht sonderlich performant möglich, dem Spieler direkt zum Joinen das Inventar zu laden, du brauchst dort eine gewisse Pause.

Ich habe einige Experimente mit NBT-Daten speichern gemacht. Das funktioniert soweit ganz gut, du kannst simpel das Inventar, die Enderchest, Leben, Effekte, XP, Errungenschaften und/oder Rezeptbücher "exportieren" und auch wieder "importieren". Versionsübergreifend müsste ein Großteil dieser NBT-Daten gleich sein. In der Theorie könntest du auch diese Daten in die DB schreiben. Dabei hast du das oben genannte Problem, beim Einloggen eines Spielers werden die Spieldaten asynchron geladen, ein Nachladen ist dabei sicherlich "irgendwie" möglich.

In meinen Tests habe ich dafür im NMS-Code eine Klasse überschrieben und per Setter oder über Reflections dort die zuständige Klasse zum Speichern/Laden von NBT-Daten der Spieler überschrieben.

Wenn du das für deinen eigenen Server optimieren möchtest, empfehl ich dir da tatsächlich einmal Paper zu "forken", unter https://github.com/electronicboy/byof gibt es dafür ein Beispiel, wie man das machen könnte. Das ist aber dann schon fortgeschrittener Stoff.

PS: https://minecraft-server.eu/forum/threads/serialisieren-von-itemstacks-in-datenbanken-so-einfach-kann-es-gehen.43520/
 
Oben