• 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 Spielerstats u.ä. Ingame zwischenspeichern [MySQL]

Addycted

Kuhfänger
Registriert
3 Oktober 2017
Beiträge
72
Diamanten
300
Minecraft
BySkeezy
Huhu,
nach langer Inaktivität hier im Forum melde ich mich mal mit einem Problem bzw. einer Frage zurück:

Ich habe wieder angefangen Minecraft Plugins zu programmieren und überlege aktuell ob es sinnvoller wäre, in der MySQL Datenbank gespeicherte Dinge(in dem Falle Stats) Ingame zwischenzuspeichern , solange diese Ingame durchgehend verändert oder genutzt werden.

Ich beziehe mich damit jetzt gerade hauptsächlich auf Stats. Wenn man jetzt beispielsweise die Stats beim Einloggen eines Spielers nur einmal aus der MySQL ausliest und beim Ausloggen wieder in der MySQL Datenbank speichert, wäre es doch besser als wenn man diese wegen jeder kleinsten Änderung ( z.B. einem Kill oder Geldveränderungen ) neu ausliest und dann wieder updatet, oder liege ich da falsch ?

Meine zweites Problem ist, dass ich noch nicht ganz sicher bin, auf welche Weise ich diese Daten dann zwischenspeichern soll, damit es am effektivsten ist.

//EDIT: Ich habe jetzt wirklich ziemlich viel gegooglet und bin zumindest schon so weit, dass ich mir ein PlayerStats Object angelegt habe. Ich weiß nur immernoch nicht, wie ich die Variablen bzw. Werte jetzt darin/damit speichere. Ich müsste ja die PlayerStats Klasse mit den UUIDs bzw. mit dem Player verbinden und so saven.


Hier noch die Klassen, falls irgendwie hilfreich:
Java:
public class sPlayer {
    
    private int admin;
    private int level;
    private int bank;
    private int cash;
    private int deaths;
    
    public sPlayer(int admin, int level, int bank, int cash, int deaths) {
        this.admin = admin;
        this.level = level;
        this.bank = bank;
        this.cash = cash;
        this.deaths = deaths;
    }
    
    public void setAdmin(int admin) {
        this.admin = admin;
    }
    
    public int getAdmin() {
        return admin;
    }
    
    public void setLevel(int level) {
        this.level = level;
    }
    
    public int getLevel() {
        return level;
    }
    
    public void setBank(int bank) {
        this.bank = bank;
    }
    
    public int getBank() {
        return bank;
    }
    
    public void setCash(int cash) {
        this.cash = cash;
    }
    
    public int getCash() {
        return cash;
    }
    
    public void setDeaths(int deaths) {
        this.deaths = deaths;
    }
    
    public int getDeaths() {
        return deaths;
    }

}

Java:
public class Stats {

    public static boolean playerExists(String uuid) {
        
        try {
            ResultSet rs = MySQL.query("SELECT * FROM users WHERE UUID = '" +uuid+ "'");
            if(rs.next()) {
                return rs.getString("UUID") != null;
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
    
    public static void createPlayer(String uuid) {
        if(!(playerExists(uuid))) {
            MySQL.update("INSERT INTO users (UUID, ADMIN, LEVEL, BANK, CASH, DEATHS) VALUES ('" +uuid+ "', '0', '1', '0', '0', '0');");
        }
    }
    
    /*public static void loadPlayer(String uuid) {
        if(playerExists(uuid)) {
            try {
                ResultSet rs = MySQL.query("SELECT * FROM Stats WHERE UUID = '" +uuid+ "'");
                
            } catch (Exception e) {

            }
        }
    }*/
    
    //savePlayer(String uuid)
    
}


Ich freue mich auf Ideen & Lösungen

MfG. Skeezy
 
Zuletzt bearbeitet:

Ativendus

Kuhfänger
Registriert
7 Dezember 2016
Beiträge
78
Diamanten
352
Du könntest jetzt entweder eine HashMap erstellen, in der du sPlayer dem Spieler zuweißt oder eine ArrayList in der du sPlayer abspeicherst, dann müsstest du aber noch zum Beispiel die UUID des Spielers in sPlayer speichern und dann könntest du sPlayer mit der UUID des Spielers aus der Array filtern
 

Addycted

Kuhfänger
Registriert
3 Oktober 2017
Beiträge
72
Diamanten
300
Minecraft
BySkeezy
Du könntest jetzt entweder eine HashMap erstellen, in der du sPlayer dem Spieler zuweißt oder eine ArrayList in der du sPlayer abspeicherst, dann müsstest du aber noch zum Beispiel die UUID des Spielers in sPlayer speichern und dann könntest du sPlayer mit der UUID des Spielers aus der Array filtern
Ja. Ich bin aktuell am Versuch mit der HashMap. Mein Problem ist aktuell nur, dass ich nicht weiß, wie ich dann auf die einzelne sPlayer Klasse des richtigen Spielers über die HashMap zugreife bzw. wie ich z.B. über die HashMap die Deaths des Spielers gette. Bin da irgendwie etwas raus aus der ganzen Materie.

Ich füge nochmal meine sPlayer Klasse an, auch wenn ich denke dass diese bereits falsch ist.
Pastebin (sPlayer)
 

Addycted

Kuhfänger
Registriert
3 Oktober 2017
Beiträge
72
Diamanten
300
Minecraft
BySkeezy
Hier, das ist die überarbeite Version von deiner Klasse. Mit sPlayer.getSPlayer(uuid) kannst du den Spieler aus der Storage rausholen.

Okay cool. Danke für die hilfreiche Funktion. Müsste ich diese dann für die getAdmin() usw. noch ergänzen oder kann ich diese Funktionen dann einfach über getSPlayer aufrufen ? :)

Ich verstehe irgendwie nicht so ganz, wie ich aus der sPlayer Klasse für den bestimmten Spieler anhand der UUID die anderen Werte bekomme. Müsste ich dann in jedem getter/setter die UUID mit angeben? Denn die HashMap speichert ja die sPlayer Klasse und wenn ich die Klasse für einen Spieler aufrufe, muss ich ja noch die entsprechenden Stats auslesen.
 
Zuletzt bearbeitet:

Addycted

Kuhfänger
Registriert
3 Oktober 2017
Beiträge
72
Diamanten
300
Minecraft
BySkeezy
sPlayer Object von dem kannst du mit zum Beispiel getCash() das Geld abrufen

Okay. Ich nehme an, dass es funktionieren sollte allerdings habe ich glaubig in dieser Methode ne Menge falsch gemacht, da sie 1. garnicht aufgerufen wird und 2. somit auch keine Stats aus der MySQL in den sPlayer saved. Der Konstruktor sollte eigtl. die Infos aus der MySQL in den "Cache" speichern.

Java:
public sPlayer(UUID uuid) {
        if(Stats.playerExists(uuid.toString())) {
            System.out.println("Player exists");
            try {
                ResultSet rs = MySQL.query("SELECT * FROM Stats WHERE UUID = '" +uuid+ "'");
                System.out.println("1");
                if(rs.next()) {
                    System.out.println("2");
                    sPlayer.setAdmin(rs.getInt("ADMIN"));
                    sPlayer.setLevel(rs.getInt("LEVEL"));
                    sPlayer.setBank(rs.getInt("BANK"));
                    sPlayer.setCash(rs.getInt("CASH"));
                    sPlayer.setDeaths(rs.getInt("DEATHS"));
                    System.out.println("Bank:" + sPlayer.getBank());
                    
                    storage.put(uuid, this);
                }
            } catch (SQLException e) {
                System.out.println("5");
                e.printStackTrace();
            }
        }
    }

Java:
public class Stats {
    
    public static boolean playerExists(String uuid) {
        
        try {
            ResultSet rs = MySQL.query("SELECT * FROM users WHERE UUID = '" +uuid+ "'");
            if(rs.next()) {
                System.out.println("gefunden");
                return rs.getString("UUID") != null;
            }
            return false;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }
    
    public static void createPlayer(String uuid) {
        if(!(playerExists(uuid))) {
            MySQL.update("INSERT INTO users (UUID, ADMIN, LEVEL, BANK, CASH, DEATHS) VALUES ('" +uuid+ "', '0', '1', '0', '0', '0');");
        }
    }
    
}

Ich habe mich in Minecraft bzw. java vorher noch nie mit MySQL beschäftigt und diese ganze Sache mit dem Cache bereitet mir wirklich ziemliche Probleme muss ich sagen :/
 

Addycted

Kuhfänger
Registriert
3 Oktober 2017
Beiträge
72
Diamanten
300
Minecraft
BySkeezy
[20:24:45] [Server thread/INFO]: gefunden

Und das auch nur, weil die createPlayer funktion im onPlayerConnect aufgerufen wird.
Mehr nicht, auch keine Fehlermeldungen.

Java:
@EventHandler
    public void OnPlayerJoin(PlayerJoinEvent e)
    {
        Player p = e.getPlayer();
        UUID uuid = e.getPlayer().getUniqueId();
        sPlayer pstats = sPlayer.getSPlayer(uuid);
        e.setJoinMessage("§e" + p.getName() + " ist dem Server beigetreten.");
        Stats.createPlayer(p.getUniqueId().toString());
        p.sendMessage("Deine Stats: Admin(" +pstats.getAdmin()+ "), Level(" +pstats.getLevel()+ "), Bank(" +pstats.getBank()+ "), Cash(" +pstats.getCash()+ "), Deaths(" +pstats.getDeaths()+ ").");
    }
 

Ativendus

Kuhfänger
Registriert
7 Dezember 2016
Beiträge
78
Diamanten
352
1. Du rufst deine Methode zum erstellen des Spielers in der Datenbank nach dem du versucht die Daten aus der Bank herauszulesen. Packt die Methode createPlayer() vor getSPlayer()

2. Du musst ja noch den sPlayer überhaupt erstellen

Wenn du dies als getSPlayer Methode benutzt wird sPlayer automatisch erzeugt, dann würde es auch funktionieren, wenn du nur getSPlayer benutzt

Java:
public static sPlayer getSPlayer(UUID uuid) {
    sPlayer sPlayer = storage.get(uuid);
    if (sPlayer == null) {
        sPlayer = new sPlayer(uuid);
    }
    return sPlayer;
}

Also so dein Event

Java:
@EventHandler
    public void OnPlayerJoin(PlayerJoinEvent e)
    {
        Player p = e.getPlayer();
        UUID uuid = e.getPlayer().getUniqueId();
        Stats.createPlayer(p.getUniqueId().toString());
        sPlayer pstats = sPlayer.getSPlayer(uuid);
        e.setJoinMessage("§e" + p.getName() + " ist dem Server beigetreten.");
        p.sendMessage("Deine Stats: Admin(" +pstats.getAdmin()+ "), Level(" +pstats.getLevel()+ "), Bank(" +pstats.getBank()+ "), Cash(" +pstats.getCash()+ "), Deaths(" +pstats.getDeaths()+ ").");
    }

Code:
public sPlayer(UUID uuid) {
        if(Stats.playerExists(uuid.toString())) {
            try {
                ResultSet rs = MySQL.query("SELECT * FROM Stats WHERE UUID = '" +uuid+ "'");
                if(rs.next()) {
                    setAdmin(rs.getInt("ADMIN"));
                    setLevel(rs.getInt("LEVEL"));
                    setBank(rs.getInt("BANK"));
                    setCash(rs.getInt("CASH"));
                    setDeaths(rs.getInt("DEATHS"));
                    storage.put(uuid, this);
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
 
Zuletzt bearbeitet:

Addycted

Kuhfänger
Registriert
3 Oktober 2017
Beiträge
72
Diamanten
300
Minecraft
BySkeezy
//EDIT: Es funktioniert alles. Danke für deine investierte Zeit mir damit zu helfen. Google konnte mir gestern wirklich nur mager weiterhelfen. Die NPE kam durch einen Fehler im Query da "Stats" durch "users" getauscht werden musste.

Code:
[21:00:11] [Server thread/ERROR]: Could not pass event PlayerJoinEvent to Survival v1.0
org.bukkit.event.EventException: null
        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:320) ~[spigot-1.15.2.jar:git-Spigot-800b93f-8160e29]
        at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:70) ~[spigot-1.15.2.jar:git-Spigot-800b93f-8160e29]
        at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:529) [spigot-1.15.2.jar:git-Spigot-800b93f-8160e29]
        at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:514) [spigot-1.15.2.jar:git-Spigot-800b93f-8160e29]
        at net.minecraft.server.v1_15_R1.PlayerList.a(PlayerList.java:176) [spigot-1.15.2.jar:git-Spigot-800b93f-8160e29]
        at net.minecraft.server.v1_15_R1.LoginListener.c(LoginListener.java:154) [spigot-1.15.2.jar:git-Spigot-800b93f-8160e29]
        at net.minecraft.server.v1_15_R1.LoginListener.tick(LoginListener.java:53) [spigot-1.15.2.jar:git-Spigot-800b93f-8160e29]
        at net.minecraft.server.v1_15_R1.NetworkManager.a(NetworkManager.java:220) [spigot-1.15.2.jar:git-Spigot-800b93f-8160e29]
        at net.minecraft.server.v1_15_R1.ServerConnection.c(ServerConnection.java:129) [spigot-1.15.2.jar:git-Spigot-800b93f-8160e29]
        at net.minecraft.server.v1_15_R1.MinecraftServer.b(MinecraftServer.java:1105) [spigot-1.15.2.jar:git-Spigot-800b93f-8160e29]
        at net.minecraft.server.v1_15_R1.DedicatedServer.b(DedicatedServer.java:399) [spigot-1.15.2.jar:git-Spigot-800b93f-8160e29]
        at net.minecraft.server.v1_15_R1.MinecraftServer.a(MinecraftServer.java:984) [spigot-1.15.2.jar:git-Spigot-800b93f-8160e29]
        at net.minecraft.server.v1_15_R1.MinecraftServer.run(MinecraftServer.java:824) [spigot-1.15.2.jar:git-Spigot-800b93f-8160e29]
        at java.lang.Thread.run(Unknown Source) [?:1.8.0_251]
Caused by: java.lang.NullPointerException
        at de.skeezy.survival.main.sPlayer.<init>(sPlayer.java:24) ~[?:?]
        at de.skeezy.survival.main.sPlayer.getSPlayer(sPlayer.java:85) ~[?:?]
        at de.skeezy.survival.main.Main.OnPlayerJoin(Main.java:56) ~[?:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_251]
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_251]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_251]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_251]
        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:316) ~[spigot-1.15.2.jar:git-Spigot-800b93f-8160e29]
        ... 13 more
[21:00:11] [Server thread/INFO]: BySkeezy[/127.0.0.1:49612] logged in with entity id 4432 at ([world]20050.459121171025, 117.0, 20417.865348433064)
>
 
Oben