• 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 [Erledigt] HashMap in Config abspeichern und wieder auslesen

Xenoshi

Kuhfänger
Registriert
22 November 2015
Beiträge
77
Diamanten
300
Minecraft
godlessFloof
Hey ich habe mal was anderes hier vielleicht könnt ihr mir helfen.

Naja wie beschrieben möchte ich gerne verschiedene Sachen abspeichern.
Zum Beispiel habe ich 4 Dörfer. In jedem Dorf sind Spieler drinnen.
Also
Dorf 1 : Simon, Lars, Anni
Dorf 2 : Leny, Ben, Sarah

Ich schick hier mal den Code rein den ich zur zeit ausprobiert habe.
Dieser ist aus dem Internet aber nur vom Abschreiben raffe ich nichts wäre nett wenn mir jemand das also erklären könnte.
public static HashMap<Object, Object> villageplayers = new HashMap<Object, Object>();

public static void saveVillagePlayers(String village, HashMap<Object, Object> hm){
file = new File("plugins//" + Main.getInstance().getName() + "//villages", village + ".yml");
cfg = YamlConfiguration.loadConfiguration(file);
if(file.exists()){
for(Object key : hm.keySet()){
cfg.set("Players", hm.get(key));
}
try {
cfg.save(file);
} catch (IOException e) { e.printStackTrace(); }
}
}

public static void loadVillagePlayers(String village){
file = new File("plugins//" + Main.getInstance().getName() + "//villages", village + ".yml");
cfg = YamlConfiguration.loadConfiguration(file);
if(file.exists()) {
for(String villages : cfg.getConfigurationSection("Players").getKeys(false)){
villageplayers.put(villages, cfg.get("Players"));
}
}
}

Es wird aber nicht abgespeichert noch geladen weshalb das was ich geplant hatte nicht funkt.
Mit freundlichen Grüßen
Xeno
 

Avankziar

Schafhirte
Registriert
12 Februar 2018
Beiträge
135
Alter
33
Diamanten
324
Minecraft
Avankziar
Wenn ich das richtig verstehe, willst du in deinem Beispiel 2 Datein, welche eine Liste von Spielernamen beinhaltet, korrekt?

Nun hier die punkte, wo ich Probleme sehe:
- Die Pfadangabe sieht nicht richtig aus. Persönlich weiß ich nicht genau, wie man in einer Zeile eine Datein in einem Unterordner angiebt, aber ich kenne einen Kniff:
Code:
        File directory = new File(plugin.getDataFolder()+"/Languages/"); //Hier erstelle ich ein Subordner mit dem namen Languages.
        if(!directory.exists())
        {
            directory.mkdir(); //Hier erstelle ich den Ordner, falls der nicht existiert.
        }
        language = new File(directory.getPath(), languageString+".yml"); //Hier hole ich mir den Pfad des Subordners und dahinter der
         //name der Datei.
        if(!language.exists())
        {
            try
            {
                //Hier erstelle ich eine leere datei aus meinem Plugin. Später baue ich mir dann intern im Code weiter was^^.
                FileUtils.copyToFile(plugin.getResource("default.yml"), language);
            } catch (IOException e)
            {
                e.printStackTrace();
            }
        }
        //hier noch eine simples laden mit yaml.load(file); in etwa
- Wenn du in einer for Schleife immer wieder den gleichen Pfad "Players" neu setzt, wird der immer Überschrieben.
Es ist simpler eine List<String> aus den Spieler zu erstellen, und diese dann einmalig pro Datei unter "Players" abzuspeichern.

Avan
 

Xenoshi

Kuhfänger
Registriert
22 November 2015
Beiträge
77
Diamanten
300
Minecraft
godlessFloof
Wenn ich das richtig verstehe, willst du in deinem Beispiel 2 Datein, welche eine Liste von Spielernamen beinhaltet, korrekt?

Nun hier die punkte, wo ich Probleme sehe:
- Die Pfadangabe sieht nicht richtig aus. Persönlich weiß ich nicht genau, wie man in einer Zeile eine Datein in einem Unterordner angiebt, aber ich kenne einen Kniff:
Code:
        File directory = new File(plugin.getDataFolder()+"/Languages/"); //Hier erstelle ich ein Subordner mit dem namen Languages.
        if(!directory.exists())
        {
            directory.mkdir(); //Hier erstelle ich den Ordner, falls der nicht existiert.
        }
        language = new File(directory.getPath(), languageString+".yml"); //Hier hole ich mir den Pfad des Subordners und dahinter der
         //name der Datei.
        if(!language.exists())
        {
            try
            {
                //Hier erstelle ich eine leere datei aus meinem Plugin. Später baue ich mir dann intern im Code weiter was^^.
                FileUtils.copyToFile(plugin.getResource("default.yml"), language);
            } catch (IOException e)
            {
                e.printStackTrace();
            }
        }
        //hier noch eine simples laden mit yaml.load(file); in etwa
- Wenn du in einer for Schleife immer wieder den gleichen Pfad "Players" neu setzt, wird der immer Überschrieben.
Es ist simpler eine List<String> aus den Spieler zu erstellen, und diese dann einmalig pro Datei unter "Players" abzuspeichern.

Avan

Okay danke für deine schnelle Antwort.
Ich habe aber ein paar Fragezeichen über dem kopf.

1. Was ist die File "language"? Wo wird diese diviniert.
2. Was bedeutet das genau? "FileUtils.copyToFile(plugin.getResource("default.yml"), language);"
3. Das verstehe ich irgendwie nicht weil es dazu keine Ansprache gibt "/hier noch eine simples laden mit yaml.load(file); in etwa"

  • Meine Pfadangabe ist an sich richtig und funkt auch.
  • Mit der Liste, bräuchte ich auch hilfe.
 

JOO200

Braumeister
Registriert
18 Dezember 2016
Beiträge
442
Diamanten
228
Die einfachste Variante wird sein, wenn du eine neue Klasse erstellst, welche ein Dorf repräsentiert.
In diese Klasse kannst du den Namen des Dorfes und die Namen (oder besser UUIDs) der Bewohner als Attribut setzen. Und wenn du so etwas wie die Größe oder die Position des Dorfes abspeichern möchtest, kannst du das dann auch in die Klasse schreiben.

Somit hättest du also an zentraler Position eine "List<Village>", in welcher du deine Dörfer speicherst. Alternativ kannst du natürlich auch eine Map nehmen und dann als Key z.B. den Namen ("Map<String, Village"). Eine HashMap mit je einem "Object" als Key und Value ist unüblich und macht relativ wenig Sinn. Mit dieser Map könntest du dann auch auf ein spezielles Dorf zugreifen, ohne durch die komplette Liste zu iterieren.

Wenn du nun also deine Dörfer speichern möchtest, iterierst du über diese Liste und rufst eine Methode der "Village"-Klasse zum speichern auf. Diese Methode erstellt dann die entsprechende Datei in deinem Plugin-Ordner und speichert als Liste die UUIDs der Spieler ab.
Entsprechende Methoden zur Erstellen von Yaml-Konfigs gibt es bereits von Spigot, alternative kannst du dir auch einmal snakeyaml als Abhängigkeit anschauen.

Wenn du nach dem Pluginstart nun diese Liste wieder laden möchtes, iterierst du über alle bestehenden Dateien und lädst die einzelnen Dörfer. Dazu sollte es dann in der Village-Klasse eine statische Methode zum laden eines neuen Dorfs geben oder ein ctor, welcher aus der Yaml-Datei die benötigten Informationen zieht.

Die Lösung von @Avankziar hat einige Schwachpunkte:
Zum einen werden die Code Conventions von Java nicht beachtet und die geschweiften Klammern in neue Zeilen gesetzt.
Zum anderen hilft dir dieser Code-Schnipsel bei deinem Problem nicht wirklich weiter, weil es unzureichend erklärt wird.

Und als abschließender Kommentar:
Ein "Dorf" hört sich sehr nach einer Region in der Welt an. Mitglieder eines Dorfes hören sich nach Membern oder Ownern an. Es gibt bereits Plugins, die sowas sehr gut verwalten, z.B. WorldGuard. Für gewöhnlich gibt es dort auch entsprechende APIs, womit du ohne viel Aufwand die Dörfer selbst erstellen kannst und die Teilnehmer des Dorfes editieren kannst. Auch wenn solche APIs etwas komplexer erscheinen, hast du damit langfristiger deine Ruhe. Gerade bei regionsbezogenen Sachen nutze ich in der Zwischenzeit so gut wie nur WorldGuard.
 

Xenoshi

Kuhfänger
Registriert
22 November 2015
Beiträge
77
Diamanten
300
Minecraft
godlessFloof
Die einfachste Variante wird sein, wenn du eine neue Klasse erstellst, welche ein Dorf repräsentiert.
In diese Klasse kannst du den Namen des Dorfes und die Namen (oder besser UUIDs) der Bewohner als Attribut setzen. Und wenn du so etwas wie die Größe oder die Position des Dorfes abspeichern möchtest, kannst du das dann auch in die Klasse schreiben.

Somit hättest du also an zentraler Position eine "List<Village>", in welcher du deine Dörfer speicherst. Alternativ kannst du natürlich auch eine Map nehmen und dann als Key z.B. den Namen ("Map<String, Village"). Eine HashMap mit je einem "Object" als Key und Value ist unüblich und macht relativ wenig Sinn. Mit dieser Map könntest du dann auch auf ein spezielles Dorf zugreifen, ohne durch die komplette Liste zu iterieren.

Wenn du nun also deine Dörfer speichern möchtest, iterierst du über diese Liste und rufst eine Methode der "Village"-Klasse zum speichern auf. Diese Methode erstellt dann die entsprechende Datei in deinem Plugin-Ordner und speichert als Liste die UUIDs der Spieler ab.
Entsprechende Methoden zur Erstellen von Yaml-Konfigs gibt es bereits von Spigot, alternative kannst du dir auch einmal snakeyaml als Abhängigkeit anschauen.

Wenn du nach dem Pluginstart nun diese Liste wieder laden möchtes, iterierst du über alle bestehenden Dateien und lädst die einzelnen Dörfer. Dazu sollte es dann in der Village-Klasse eine statische Methode zum laden eines neuen Dorfs geben oder ein ctor, welcher aus der Yaml-Datei die benötigten Informationen zieht.

Die Lösung von @Avankziar hat einige Schwachpunkte:
Zum einen werden die Code Conventions von Java nicht beachtet und die geschweiften Klammern in neue Zeilen gesetzt.
Zum anderen hilft dir dieser Code-Schnipsel bei deinem Problem nicht wirklich weiter, weil es unzureichend erklärt wird.

Und als abschließender Kommentar:
Ein "Dorf" hört sich sehr nach einer Region in der Welt an. Mitglieder eines Dorfes hören sich nach Membern oder Ownern an. Es gibt bereits Plugins, die sowas sehr gut verwalten, z.B. WorldGuard. Für gewöhnlich gibt es dort auch entsprechende APIs, womit du ohne viel Aufwand die Dörfer selbst erstellen kannst und die Teilnehmer des Dorfes editieren kannst. Auch wenn solche APIs etwas komplexer erscheinen, hast du damit langfristiger deine Ruhe. Gerade bei regionsbezogenen Sachen nutze ich in der Zwischenzeit so gut wie nur WorldGuard.
Erstmal bomben Text.

Damit ich dir hintergrundinfos geben kann zu dem was ich vorhabe, hier:

Ein Spieler kann in ein Dorf mit einem command geaddet werden.
Es gibt nur Member einen festen "Owner" jedoch nicht.
Es sollen auch regionen nicht gesaved werden oder so sondern einfach nur als gimig gibt es diese Dörfer.
Letztlich bekommt man wenn man in dem Dorf ist:
1. Einen Prefix in der Tab.
2. Ein Scoreboard für das geweilige Team.
 

JOO200

Braumeister
Registriert
18 Dezember 2016
Beiträge
442
Diamanten
228
Deine Hintegrundinformationen sind widersprüchlich:
"Es sollen auch regionen nicht gesaved werden", aber "Ein Spieler kann in ein Dorf mit einem command geaddet werden.". Das macht keinen Sinn. Wie soll denn überprüft werden, in welchem Dorf man gerade ist, zu dem man hinzugefügt werden soll?
Wenn die Dörfer nicht mit einer Region assoziert werden, führt das schnell zu Chaos. Am Ende werden die Spieler kreuz und quer hinzugefügt und du weißt nichtmal mehr selbst, wie das kommen konnte. Und wenn es keine Owner gibt, dann kann jeder bestehende Member einen anderen Spieler zu dem Dorf hinzufügen?

Und sowohl Prefix als auch Scoreboard könntest du mit WorldGuard verhältnismäßig einfach realisieren. Ich kann verstehen, wenn du das alles erstmal selbst "von 0" aufbauen möchtest, allerdings bin ich grundsätzlich dagegen, bereits funktionierende und existierende Sachen doppelt zu entwickeln.

Ich sehe tatsächlich bei deinem Konzept auch noch einige Schwachpunkte. Was passiert, wenn ein Spieler in mehreren Dörfern gleichzeitig Member ist? Wie kann ein Spieler in Dorf wieder verlassen?

Und wenn das alles so ein "simples Gimmick" ist, dann ist der andere Weg vielleicht einfacher:
Hefte den Spielern die Information an, welches ihr aktives Dorf ist. Dies kannst du über einen entsprechenden Tag selbst machen. Dieser Tag wird dann im Spielstand gespeichert und automatisch vom Server geladen.
Somit hast du die Schwachpunkte aus deinem Konzept auch behoben: Durch den Tag gibt es nur ein aktives Dorf und du kannst dann ein entsprechendes Scoreboard erzeugen und die Spieler dazufügen (ob ein Scoreboard auch gespeichert wird, wenn ein Spieler offline geht, kann ich so gar nicht sagen, dafür arbeite ich zu selten mit denen).
 

Xenoshi

Kuhfänger
Registriert
22 November 2015
Beiträge
77
Diamanten
300
Minecraft
godlessFloof
Vielleicht habe ich mich dumm ausgedrückt. Sry dafür :D

Also es ist so. Spieler können normal auf den Server joinen und neutral bauen.
Es ist also egal ob sie in einem Dorf sind oder nicht.
Sollte jedoch jemand zu einem Dorf gehören wollen, so gibt es Moderatoren im Projekt die Spieler in ein Dorf hinzufügen und rauswerfen können mithilfe von Commands. Auch darf gebaut werden wo man will. Quasi hat also ein Dorf eine Fläche aber diese wird nicht vorgeschrieben oder mit einem Plugin Definiert. Also haben die meinetwegen 100 Blöcke oder auch 100.000. Es ist also egal. Vergiss also erstmal grundsätzlich das mit dem Worldguardplatz. Es ist btw eine Art CraftAttack (nur halt mein Style).


Zu den Problemen die du auftischst.
Es kann nur ein Spieler in ein Dorf hinzugefügt oder rausgeworfen werden. (Das mit dem Owner wird noch kommen)
Regionen sind nicht Fest jeder darf also bauen wo er will. Dörfer können aber mit einer Mauer zum Beispiel ein gebiet eingerenzen müssen sie aber nicht.
Mit dem Prefix und so joar. Ich weiß nicht wie man das mit zum Beispiel WorldGuard macht aber andersrum will ich es auch selbst machen denn ich hasse es andere Plugins für so "simple" Sachen zu nehmen.
Spieler können auch erst in ein anderes Dorf wenn Sie das andere verlassen haben oder das ganze mit dem Team abgesprochen ist.
Mit dem einfachen Weg, das ganze verstehe ich null was du da meinst :D

Vielleicht hilft dir der Beitrag mehr mein Problem zu verstehen.
Das einzige Problem was ich nämlich habe, die Liste der Dörfer wird nicht mehr nach serverstart in die HashMap geladen.
Aus diesem Grund habe ich diesen Beitrag geschrieben.
Vielleicht hättest du da nen gutes Beispiel wie man das machen könnte.
 

JOO200

Braumeister
Registriert
18 Dezember 2016
Beiträge
442
Diamanten
228
Okay, was genau du benutzt, ist schlussendlich egal, wenn es funktioniert.

Um deine HashMap wieder zu befüllen, müsstest du nach dem Neustarten des Servers in der onEnable-Methode die Datei(en) öffnen und die dort gespeicherten Werte wieder in sinnvolle Objekte verwandeln. Dabei verstehe ich nicht genau, was da das Problem ist? Wie du Dateien öffnest und über alle Dateien in einem Ordner iterieren kannst, gibt es zur genüge als Beispiel im Internet.

Das Problem was ich damit habe:
Da deine Dörfer nichts weiter als ein Name ist, den du deinen Spieler anheften möchtest, wäre es sehr viel einfacher, wenn du dem Dorfnamen als Attribut an den Spieler heftest. Dadurch würdest du dann beim Speichern vom Spieler die Information mitgeben, zu welchem Dorf er gehört. Nicht dem Dorf eine Liste mitgeben, welche Spieler alles zu diesem Dorf gehören. Denn wenn du die Liste nur in dem Dorf hast, musst du zur Überprüfung, ob der Spieler bereits in einem Dorf ist, einmal über alle Dörfer iterieren und dort über alle enthaltenen Spieler. Das ist bei der Performance eher mittelmäßig.

Aber nachdem das wohl eher ein kleines Projekt sein wird, brauchst du dir über Performance wohl keine Gedanken machen.

Was hast du denn bisher gemacht, um dein Dorf wieder aus der Datei zu laden? Hast du bereits irgendwas in der onEnable dafür stehen?
 
Oben