From 1266111f8a3be5af63bf7cc535a1765b51b6beaa Mon Sep 17 00:00:00 2001 From: Sn0wStorm Date: Wed, 29 Jan 2020 15:39:02 +0100 Subject: [PATCH] Implemented Playerdata DB Syncing --- resources/config/v13/de/config.yml | 18 +++++++ resources/config/v13/en/config.yml | 17 +++++++ resources/config/v13/fr/config.yml | 17 +++++++ resources/config/v13/it/config.yml | 17 +++++++ resources/config/v13/zh/config.yml | 17 +++++++ src/com/dre/brewery/BPlayer.java | 49 ++++++++++++++++--- src/com/dre/brewery/api/BreweryApi.java | 8 +++ src/com/dre/brewery/filedata/BConfig.java | 5 +- src/com/dre/brewery/filedata/BData.java | 14 +++--- .../dre/brewery/listeners/PlayerListener.java | 11 ++++- src/com/dre/brewery/utility/SQLSync.java | 39 +++++++++++---- 11 files changed, 184 insertions(+), 28 deletions(-) diff --git a/resources/config/v13/de/config.yml b/resources/config/v13/de/config.yml index a4afb6d..1f4620f 100644 --- a/resources/config/v13/de/config.yml +++ b/resources/config/v13/de/config.yml @@ -65,6 +65,7 @@ maxBrewsInMCBarrels: 6 # Benutzte Zutaten und andere Brau-Daten werden in allen Brewery Tränken gespeichert. Um zu verhindern, # dass gehackte clients diese Daten auslesen um Rezepte herauszufinden, können diese encodiert werden. # Einziger Nachteil: Tränke können nur auf Servern mit dem gleichen encodeKey benutzt werden. +# Wenn Brewery Tränke auf mehreren (Bungeecord) Servern benutzt werden, unten unter 'multiServerDB' eine gemeinsame Datenbank eintragen. # Dies kann also aktiviert werden um Rezept-cheating schwerer zu machen, aber keine Tränke per World Download, Schematic, o.ä. geteilt werden. [false] enableEncode: false encodeKey: 0 @@ -780,6 +781,23 @@ useGMInventories: true useLogBlock: true +# -- MultiServer/BungeeCord -- +# Wenn Brewery auf mehreren Servern läuft und diese zB mit BungeeCord verbunden sind, +# sollte hier eine gemeinsame Datenbank eingetragen werden. +# Dann wird Betrunkenheit auf den Servern synchronisiert und encodierte Tränke können auf allen Servern benutzt werden. + +multiServerDB: + # Soll die Datenbank-Synchronisation aktiviert sein + enabled: false + # Soll die Betrunkenheit von Spielern synchronisiert werden + syncDrunkeness: true + host: localhost + port: '3306' + user: minec + password: xyz + database: base + + # -- Chat Veränderungs Einstellungen -- # Ob geschriebener Chat bei großer Trunkenheit abgefälscht werden soll, diff --git a/resources/config/v13/en/config.yml b/resources/config/v13/en/config.yml index 84b82c7..d46b32c 100644 --- a/resources/config/v13/en/config.yml +++ b/resources/config/v13/en/config.yml @@ -66,6 +66,7 @@ maxBrewsInMCBarrels: 6 # hacked clients from reading what exactly was used to brew an item, the data can be encoded/scrambled. # This is a fast process to stop players from hacking out recipes, once they get hold of a brew. # Only drawback: brew items can only be used on another server with the same encodeKey. +# When using Brews on multiple (BungeeCord) Servers, define a shared Database below at 'multiServerDB' # So enable this if you want to make recipe cheating harder, but don't share any brews by world download, schematics, or other means. [false] enableEncode: false encodeKey: 0 @@ -774,6 +775,22 @@ useGMInventories: true useLogBlock: true +# -- MultiServer/BungeeCord -- +# If Brewery is running on multiple connected Servers (via BungeeCord) +# a shared Database can be used here to synchronise drunkeness and to be able to use encoded brews between them. + +multiServerDB: + # If using the Database is enabled + enabled: false + # If the drunkeness of players should be synchronised between Servers + syncDrunkeness: true + host: localhost + port: '3306' + user: minec + password: xyz + database: base + + # -- Chat Distortion Settings -- # If written Chat is distorted when the Player is Drunk, so that it looks like drunk writing diff --git a/resources/config/v13/fr/config.yml b/resources/config/v13/fr/config.yml index 1c0602f..bcab090 100644 --- a/resources/config/v13/fr/config.yml +++ b/resources/config/v13/fr/config.yml @@ -67,6 +67,7 @@ maxBrewsInMCBarrels: 6 # Pour empêcher les clients piratés de lire exactement ce qui a été utilisé pour infuser un élément, les données peuvent être encodées/brouillées. # Il s'agit d'un processus rapide pour empêcher les joueurs de pirater des recettes, une fois qu'ils mettent la main sur une bière. # Seul inconvénient: Les boissons brassicoles ne peuvent être utilisés que sur un autre serveur avec la même clé de chiffrement. +# Lorsque vous utilisez des boissons brassicoles sur plusieurs serveurs (BungeeCord), définissez une base de données partagée ci-dessous à "multiServerDB". # Activez cette option si vous voulez rendre la tricherie des recettes plus difficile, mais ne partagez pas les infusions par téléchargement mondial, schémas ou autres moyens. enableEncode: false encodeKey: 0 @@ -780,6 +781,22 @@ useGMInventories: true useLogBlock: true +# -- MultiServer/BungeeCord -- +# Si Brewery est exécuté sur plusieurs serveurs connectés (via BungeeCord), une base de données partagée peut être utilisée +# ici pour synchroniser l'ivresse et pour pouvoir utiliser des boissons codées entre elles. + +multiServerDB: + # Si l'utilisation de la base de données est activée + enabled: false + # Si l'ivresse des joueurs devait être synchronisée entre les serveurs + syncDrunkeness: true + host: localhost + port: '3306' + user: minec + password: xyz + database: base + + # -- Paramètres de la distorsion du Chat -- # Si le Chat écrit est déformé quand le joueur est ivre, de sorte qu'il ressemble à un chat bourré en train d'écrire diff --git a/resources/config/v13/it/config.yml b/resources/config/v13/it/config.yml index c2a206f..1e6dd7c 100644 --- a/resources/config/v13/it/config.yml +++ b/resources/config/v13/it/config.yml @@ -66,6 +66,7 @@ maxBrewsInMCBarrels: 6 # hacked clients from reading what exactly was used to brew an item, the data can be encoded/scrambled. # This is a fast process to stop players from hacking out recipes, once they get hold of a brew. # Only drawback: brew items can only be used on another server with the same encodeKey. +# When using Brews on multiple (BungeeCord) Servers, define a shared Database below at 'multiServerDB' # So enable this if you want to make recipe cheating harder, but don't share any brews by world download, schematics, or other means. [false] enableEncode: false encodeKey: 0 @@ -774,6 +775,22 @@ useGMInventories: true useLogBlock: true +# -- MultiServer/BungeeCord -- +# If Brewery is running on multiple connected Servers (via BungeeCord) +# a shared Database can be used here to synchronise drunkeness and to be able to use encoded brews between them. + +multiServerDB: + # If using the Database is enabled + enabled: false + # If the drunkeness of players should be synchronised between Servers + syncDrunkeness: true + host: localhost + port: '3306' + user: minec + password: xyz + database: base + + # -- Imostazioni di distorsione della chat -- # If written Chat is distorted when the Player is Drunk, diff --git a/resources/config/v13/zh/config.yml b/resources/config/v13/zh/config.yml index 4342df9..5412b0b 100644 --- a/resources/config/v13/zh/config.yml +++ b/resources/config/v13/zh/config.yml @@ -68,6 +68,7 @@ maxBrewsInMCBarrels: 6 # hacked clients from reading what exactly was used to brew an item, the data can be encoded/scrambled. # This is a fast process to stop players from hacking out recipes, once they get hold of a brew. # Only drawback: brew items can only be used on another server with the same encodeKey. +# When using Brews on multiple (BungeeCord) Servers, define a shared Database below at 'multiServerDB' # So enable this if you want to make recipe cheating harder, but don't share any brews by world download, schematics, or other means. [false] enableEncode: false encodeKey: 0 @@ -778,6 +779,22 @@ useGMInventories: true useLogBlock: true +# -- MultiServer/BungeeCord -- +# If Brewery is running on multiple connected Servers (via BungeeCord) +# a shared Database can be used here to synchronise drunkeness and to be able to use encoded brews between them. + +multiServerDB: + # If using the Database is enabled + enabled: false + # If the drunkeness of players should be synchronised between Servers + syncDrunkeness: true + host: localhost + port: '3306' + user: minec + password: xyz + database: base + + # -- 口糊设置 -- # 醉酒的玩家会口糊, diff --git a/src/com/dre/brewery/BPlayer.java b/src/com/dre/brewery/BPlayer.java index bf268a5..a7ed72a 100644 --- a/src/com/dre/brewery/BPlayer.java +++ b/src/com/dre/brewery/BPlayer.java @@ -29,7 +29,7 @@ import java.lang.reflect.Method; import java.util.*; public class BPlayer { - private static Map players = new HashMap<>();// Players name/uuid and BPlayer + private static Map players = new HashMap<>();// Players uuid and BPlayer private static Map pTasks = new HashMap<>();// Player and count private static int taskId; private static boolean modAge = true; @@ -37,21 +37,24 @@ public class BPlayer { private static Method itemHandle; private static Field age; + private final String uuid; private int quality = 0;// = quality of drunkeness * drunkeness private int drunkeness = 0;// = amount of drunkeness private int offlineDrunk = 0;// drunkeness when gone offline private Vector push = new Vector(0, 0, 0); private int time = 20; - public BPlayer() { + public BPlayer(String uuid) { + this.uuid = uuid; } // reading from file - public BPlayer(String name, int quality, int drunkeness, int offlineDrunk) { + public BPlayer(String uuid, int quality, int drunkeness, int offlineDrunk) { this.quality = quality; this.drunkeness = drunkeness; this.offlineDrunk = offlineDrunk; - players.put(name, this); + this.uuid = uuid; + players.put(uuid, this); } @Nullable @@ -111,13 +114,16 @@ public class BPlayer { // Create a new BPlayer and add it to the list public static BPlayer addPlayer(Player player) { - BPlayer bPlayer = new BPlayer(); + BPlayer bPlayer = new BPlayer(BUtil.playerString(player)); players.put(BUtil.playerString(player), bPlayer); return bPlayer; } public static void remove(Player player) { players.remove(BUtil.playerString(player)); + if (BConfig.sqlDrunkSync && BConfig.sqlSync != null) { + BConfig.sqlSync.removePlayer(player.getUniqueId()); + } } public static int numDrunkPlayers() { @@ -128,6 +134,9 @@ public class BPlayer { for (Iterator> iterator = players.entrySet().iterator(); iterator.hasNext(); ) { Map.Entry entry = iterator.next(); if (entry.getValue() == this) { + if (BConfig.sqlDrunkSync && BConfig.sqlSync != null) { + BConfig.sqlSync.removePlayer(UUID.fromString(entry.getKey())); + } iterator.remove(); return; } @@ -183,6 +192,7 @@ public class BPlayer { if (bPlayer.drunkeness > 100) { bPlayer.drinkCap(player); } + bPlayer.syncToSQL(); //player.sendMessage("Betrunkenheit: §8[§7⭑⭑⭑⭒§0⭑§8] §8[§6|||||||||||||||||§0|||||||||§8]"); return true; } @@ -191,6 +201,7 @@ public class BPlayer { public void drinkCap(Player player) { quality = getQuality() * 100; drunkeness = 100; + syncToSQL(); if (BConfig.overdrinkKick && !player.hasPermission("brewery.bypass.overdrink")) { P.p.getServer().getScheduler().scheduleSyncDelayedTask(P.p, () -> passOut(player), 1); } else { @@ -233,9 +244,11 @@ public class BPlayer { } quality = getQuality(); if (drunkeness <= -offlineDrunk) { + syncToSQL(); return drunkeness <= -BConfig.hangoverTime; } } + syncToSQL(); return false; } @@ -291,6 +304,7 @@ public class BPlayer { public void passOut(Player player) { player.kickPlayer(P.p.languageReader.get("Player_DrunkPassOut")); offlineDrunk = drunkeness; + syncToSQL(); } @@ -344,7 +358,7 @@ public class BPlayer { } hangoverEffects(player); // wird der spieler noch gebraucht? - players.remove(BUtil.playerString(player)); + remove(player); } else if (offlineDrunk - drunkeness >= 30) { Location randomLoc = Wakeup.getRandom(player.getLocation()); @@ -357,10 +371,13 @@ public class BPlayer { } offlineDrunk = 0; + syncToSQL(); + } public void disconnecting() { offlineDrunk = drunkeness; + syncToSQL(); } public void goHome(final Player player) { @@ -658,19 +675,29 @@ public class BPlayer { Iterator> iter = players.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = iter.next(); - String name = entry.getKey(); + String uuid = entry.getKey(); BPlayer bplayer = entry.getValue(); if (bplayer.drunkeness == soberPerMin) { // Prevent 0 drunkeness soberPerMin++; } - if (bplayer.drain(BUtil.getPlayerfromString(name), soberPerMin)) { + if (bplayer.drain(BUtil.getPlayerfromString(uuid), soberPerMin)) { iter.remove(); + if (BConfig.sqlDrunkSync && BConfig.sqlSync != null) { + BConfig.sqlSync.removePlayer(UUID.fromString(uuid)); + } } } } } + // Sync Drunkeness Data to SQL if enabled + public void syncToSQL() { + if (BConfig.sqlDrunkSync && BConfig.sqlSync != null) { + BConfig.sqlSync.updatePlayer(UUID.fromString(uuid), this); + } + } + // save all data public static void save(ConfigurationSection config) { for (Map.Entry entry : players.entrySet()) { @@ -687,6 +714,11 @@ public class BPlayer { // #### getter/setter #### + + public String getUuid() { + return uuid; + } + public int getDrunkeness() { return drunkeness; } @@ -702,6 +734,7 @@ public class BPlayer { } } this.drunkeness = drunkeness; + syncToSQL(); } public int getQuality() { diff --git a/src/com/dre/brewery/api/BreweryApi.java b/src/com/dre/brewery/api/BreweryApi.java index b53def9..b6c8494 100644 --- a/src/com/dre/brewery/api/BreweryApi.java +++ b/src/com/dre/brewery/api/BreweryApi.java @@ -27,6 +27,14 @@ import java.util.List; */ public class BreweryApi { + /** + * Get the Current Version of the Brewery API. + *

Higher numbers mean newer API, but it doesn't necessarily mean that something has changed, may be additions only + */ + public static int getApiVersion() { + return 2; + } + /** * Remove any data that this Plugin may associate with the given Block. *

Currently Cauldrons and Barrels (Cauldron, Wood, Woodstairs, Fence, Sign) diff --git a/src/com/dre/brewery/filedata/BConfig.java b/src/com/dre/brewery/filedata/BConfig.java index 052b952..5cdf3c0 100644 --- a/src/com/dre/brewery/filedata/BConfig.java +++ b/src/com/dre/brewery/filedata/BConfig.java @@ -80,7 +80,6 @@ public class BConfig { //MySQL public static String sqlHost, sqlPort, sqlDB; - private static String sqlUser, sqlPW; public static SQLSync sqlSync; public static boolean sqlDrunkSync; @@ -345,9 +344,9 @@ public class BConfig { sqlDrunkSync = sqlCfg.getBoolean("syncDrunkeness"); sqlHost = sqlCfg.getString("host", null); sqlPort = sqlCfg.getString("port", null); - sqlUser = sqlCfg.getString("user", null); sqlDB = sqlCfg.getString("database", null); - sqlPW = sqlCfg.getString("password", null); + String sqlUser = sqlCfg.getString("user", null); + String sqlPW = sqlCfg.getString("password", null); sqlSync = new SQLSync(); if (!sqlSync.init(sqlUser, sqlPW)) { diff --git a/src/com/dre/brewery/filedata/BData.java b/src/com/dre/brewery/filedata/BData.java index 6b8cac3..6adea4e 100644 --- a/src/com/dre/brewery/filedata/BData.java +++ b/src/com/dre/brewery/filedata/BData.java @@ -164,11 +164,11 @@ public class BData { // loading BPlayer section = data.getConfigurationSection("Player"); if (section != null) { - // keys have players name - for (String name : section.getKeys(false)) { + // keys have players uuid + for (String uuid : section.getKeys(false)) { try { //noinspection ResultOfMethodCallIgnored - UUID.fromString(name); + UUID.fromString(uuid); if (!P.useUUID) { continue; } @@ -178,11 +178,11 @@ public class BData { } } - int quality = section.getInt(name + ".quality"); - int drunk = section.getInt(name + ".drunk"); - int offDrunk = section.getInt(name + ".offDrunk", 0); + int quality = section.getInt(uuid + ".quality"); + int drunk = section.getInt(uuid + ".drunk"); + int offDrunk = section.getInt(uuid + ".offDrunk", 0); - new BPlayer(name, quality, drunk, offDrunk); + new BPlayer(uuid, quality, drunk, offDrunk); } } diff --git a/src/com/dre/brewery/listeners/PlayerListener.java b/src/com/dre/brewery/listeners/PlayerListener.java index ad0cdec..d92504c 100644 --- a/src/com/dre/brewery/listeners/PlayerListener.java +++ b/src/com/dre/brewery/listeners/PlayerListener.java @@ -186,8 +186,17 @@ public class PlayerListener implements Listener { DistortChat.playerCommand(event); } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerLoginAsync(AsyncPlayerPreLoginEvent event) { + if (event.getLoginResult() == AsyncPlayerPreLoginEvent.Result.ALLOWED) { + if (BConfig.sqlDrunkSync && BConfig.sqlSync != null) { + BConfig.sqlSync.fetchPlayerLoginData(event.getUniqueId()); + } + } + } + // player joins while passed out - @EventHandler() + @EventHandler public void onPlayerLogin(PlayerLoginEvent event) { if (event.getResult() == PlayerLoginEvent.Result.ALLOWED) { final Player player = event.getPlayer(); diff --git a/src/com/dre/brewery/utility/SQLSync.java b/src/com/dre/brewery/utility/SQLSync.java index cf4f37c..ebf0d93 100644 --- a/src/com/dre/brewery/utility/SQLSync.java +++ b/src/com/dre/brewery/utility/SQLSync.java @@ -3,13 +3,8 @@ package com.dre.brewery.utility; import com.dre.brewery.BPlayer; import com.dre.brewery.P; import com.dre.brewery.filedata.BConfig; -import org.bukkit.entity.Player; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.sql.Statement; +import java.sql.*; import java.util.UUID; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; @@ -24,10 +19,10 @@ public class SQLSync { private String user, password; - public void updatePlayer(Player player, BPlayer bPlayer) { - removePlayer(player.getUniqueId()); + public void updatePlayer(UUID uuid, BPlayer bPlayer) { + removePlayer(uuid); SQLData_BP bP = new SQLData_BP(); - bP.uuid = player.getUniqueId(); + bP.uuid = uuid; bP.drunkeness = bPlayer.getDrunkeness(); bP.offlineDrunk = bPlayer.getOfflineDrunkeness(); bP.quality = bPlayer.getQuality(); @@ -72,6 +67,32 @@ public class SQLSync { } } + // Run Async + public void fetchPlayerLoginData(final UUID uuid) { + try { + if (!checkConnection()) { + if (!openConnection()) { + P.p.errorLog("Opening SQL Connection failed"); + return; + } + } + + Statement statement = connection.createStatement(); + if (statement.execute("SELECT * FROM BreweryZ_BPlayers WHERE uuid = " + uuid.toString() + ";")) { + final ResultSet result = statement.getResultSet(); + P.p.getServer().getScheduler().runTask(P.p, () -> { + try { + new BPlayer(uuid.toString(), result.getInt("quality"), result.getInt("drunkeness"), result.getInt("offlineDrunk")); + } catch (SQLException e) { + e.printStackTrace(); + } + }); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + private void initAsyncTask() { if (sqlTaskRunning) return; sqlTaskRunning = true;