From 2df775a11ead0254ae4dff5eb140a4890af00188 Mon Sep 17 00:00:00 2001 From: Stephen Olsen Date: Wed, 30 Dec 2020 22:11:31 -0600 Subject: [PATCH] Version 1.0 --- README.md | 20 ++- pom.xml | 11 +- src/findPlayer/FindPlayer.java | 92 ++++++++--- src/findPlayer/IPlayerCache.java | 8 + src/findPlayer/PlayerCache_Base.java | 4 +- src/findPlayer/PlayerCache_Json.java | 139 ++++++++++++---- src/findPlayer/PlayerCache_SQL.java | 202 ++++++++++++++++------- src/main/resources/conifg.yml | 7 +- src/main/resources/plugin.yml | 2 +- target/classes/conifg.yml | 7 +- target/classes/main/resources/conifg.yml | 7 +- target/classes/main/resources/plugin.yml | 2 +- target/classes/plugin.yml | 2 +- target/maven-archiver/pom.properties | 4 +- 14 files changed, 374 insertions(+), 133 deletions(-) diff --git a/README.md b/README.md index c180b26..f00d31d 100644 --- a/README.md +++ b/README.md @@ -10,14 +10,28 @@ Includes optional integration into WorldGuard and will display whichever regions ## Configuration Nothing special needed. Just place the .jar file into your plugins directory and restart the server. -by default it will log to a json file so player's last location will be logged. -Logging options include: mysql, json or none. +By default it will log to a json file so player's last location will be logged. +Logging options include: mysql, sqlite, json or none. default configuration: ![config](/images/config1.png) The online and offline player messages are fully customizeable to show only the items you want to see, change colors and more. +## Permissions + +* FindPlayer.findp - basic permission to allow looking up player's locations +* FindPlayer.reload - reload the configuration +* FindPlayer.purge - delete any cached entries from memory and disk + ## Examples: ![example1](/images/image1.png) -![example2](/images/image2.png) \ No newline at end of file +![example2](/images/image2.png) + +## Misc + +Credit goes out to [ellienntatar] for making the original [FindPlayer]. +I wanted to improve on it so make this version from the original concept. + +[ellienntatar]: https://www.spigotmc.org/resources/authors/ellienntatar.886090/ +[FindPlayer]: https://www.spigotmc.org/resources/findplayer.75642/ \ No newline at end of file diff --git a/pom.xml b/pom.xml index e55bdea..177f3b6 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 FindPlayer FindPlayer - 0.5 + 1.0 src @@ -45,6 +45,10 @@ sk89q-snapshots http://maven.sk89q.com/artifactory/repo + + org.xerial + https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc + @@ -82,6 +86,11 @@ worldedit-bukkit 7.2.1-SNAPSHOT + + org.xerial + sqlite-jdbc + 3.34.0 + \ No newline at end of file diff --git a/src/findPlayer/FindPlayer.java b/src/findPlayer/FindPlayer.java index eedb2ec..0142eca 100644 --- a/src/findPlayer/FindPlayer.java +++ b/src/findPlayer/FindPlayer.java @@ -8,7 +8,9 @@ import org.bukkit.Location; import org.bukkit.World; import org.bukkit.ChatColor; +import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.command.Command; @@ -21,7 +23,7 @@ public class FindPlayer extends JavaPlugin implements Listener { private final Logger logger = Logger.getLogger("Minecraft"); public FileConfiguration config; private LoggingType loggingType = LoggingType.None; - public Boolean UseVerboseLogging; + public Boolean useDebug; private IPlayerCache playerCache; private String playerOnlinePreformedString; private String playerOfflinePreformedString; @@ -35,16 +37,15 @@ public void onEnable() { config = getConfig(); this.hasWorldGuard = WorldGuardStuff.CheckForWorldGuard(); - processConfig(false); + processConfig(null); playerCache.PopulateData(); - - + this.getCommand("findp").setExecutor(this); getServer().getPluginManager().registerEvents(this, this); PluginDescriptionFile pdf = this.getDescription(); - logger.info("Has WorldGuard: " + this.hasWorldGuard.toString()); + if (this.useDebug) logger.info("Has WorldGuard: " + this.hasWorldGuard.toString()); String msg = String.format("%s (%s) has been enabled", pdf.getName(), pdf.getVersion()); logger.info(msg); } @@ -52,7 +53,7 @@ public void onEnable() { @Override public void onDisable() { PluginDescriptionFile pdf = this.getDescription(); - logger.info(pdf.getName() + " has been disabled"); + if (this.useDebug) logger.info(pdf.getName() + " has been disabled"); } @Override @@ -60,27 +61,53 @@ public boolean onCommand(CommandSender sender, Command cmd, String label, String if (cmd.getName().equalsIgnoreCase("findp")) { if(args.length == 1) { if (args[0].equalsIgnoreCase("reload")) { + if (!sender.hasPermission("FindPlayer.reload")) { + sender.sendMessage(ChatColor.RED + "You don't have permisisons for this command"); + return true; + } + saveDefaultConfig(); this.reloadConfig(); config = getConfig(); - processConfig(true); - sender.sendMessage(ChatColor.YELLOW + "Reloaded the config."); + processConfig(sender); + sender.sendMessage(ChatColor.YELLOW + "Reloaded the config."); } - else if (args[0].equalsIgnoreCase("test")) { - // not used right now + else if (args[0].equalsIgnoreCase("purge")) { + if (!sender.hasPermission("FindPlayer.purge")) { + sender.sendMessage(ChatColor.RED + "You don't have permisisons for this command"); + return true; + } + playerCache.PurgeData(); + sender.sendMessage(ChatColor.YELLOW + "Purged all cached data."); } else { String SendMsg = getMessageForPlayer(args[0]); sender.sendMessage(SendMsg); } } else { - sender.sendMessage(ChatColor.YELLOW + "Usage: /findp PlayerName|reload"); + ChatColor g = ChatColor.GREEN; + ChatColor y = ChatColor.YELLOW; + sender.sendMessage(y + "Usage: /findp PlayerName" + g + "|" + y + "reload" + g + "|" + y + "purge"); } } return true; } + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event){ + if (this.loggingType == LoggingType.None) return; + + Player p = event.getPlayer(); + if (p == null) return; + Location loc = p.getLocation(); + + PlayerStoreInfo psi = new PlayerStoreInfo(p.getUniqueId(), p.getName(), + p.getWorld().getName(), loc); + + playerCache.AddOrUpdatePlayerInfo(psi); + } + private String getMessageForPlayer(String playerName) { // try to find player entity from name. Will only work if they are online Player p = Bukkit.getPlayer(playerName); @@ -108,38 +135,57 @@ private String getMessageForPlayer(String playerName) { return formulateMessage(this.playerOfflinePreformedString, psi, null, this.hasWorldGuard); } - private void processConfig(Boolean isReload) { - this.UseVerboseLogging = config.getBoolean("verbose-logging", false); + private void processConfig(CommandSender sender) { + this.useDebug = config.getBoolean("debug", false); + long writeTimeMs = config.getLong("json-write-time-ms", 5000L); + String loggingType = config.getString("player-logging-type"); + if (Helpers.isNullOrEmpty(loggingType)) loggingType = "json"; + + Boolean isReload = (sender != null); if (!isReload) { // can only change this by restarting server - String loggingType = config.getString("player-logging-type"); - if (Helpers.isNullOrEmpty(loggingType)) loggingType = "json"; switch (loggingType.toLowerCase()) { case "mysql": this.loggingType = LoggingType.Mysql; - PlayerCache_SQL.SQL_ConfigInfo sconfig = new PlayerCache_SQL.SQL_ConfigInfo(); + PlayerCache_SQL.MySQL_ConfigInfo sconfig = new PlayerCache_SQL.MySQL_ConfigInfo(); sconfig.database = config.getString("mysql-database"); sconfig.hostname = config.getString("mysql-hostname"); sconfig.username = config.getString("mysql-username"); sconfig.password = config.getString("mysql-password"); - PlayerCache_SQL sql = new PlayerCache_SQL(sconfig); - playerCache = sql; - if (!sql.openConnection()) - logger.warning("Unable to open mysql connection"); + PlayerCache_SQL mysql = new PlayerCache_SQL(sconfig, useDebug); + playerCache = mysql; + mysql.openConnection(); + break; + case "sqlite": + this.loggingType = LoggingType.Sqlite; + PlayerCache_SQL sqlite = new PlayerCache_SQL(this.getDataFolder(), useDebug); + playerCache = sqlite; + sqlite.openConnection(); break; case "json": this.loggingType = LoggingType.Json; - playerCache = new PlayerCache_Json(this.getDataFolder()); + playerCache = new PlayerCache_Json(this.getDataFolder(), writeTimeMs, useDebug); break; default: this.loggingType = LoggingType.None; break; } - if (this.UseVerboseLogging) logger.info("Using logging type of " + this.loggingType.toString()); + if (this.useDebug) logger.info("Using logging type of " + this.loggingType.toString()); + } + else { + // is reload + if (playerCache != null) { + playerCache.UpdateDebug(useDebug); + playerCache.UpdateFileWriteTime(writeTimeMs); + } + + if (this.loggingType.toString().toLowerCase() != loggingType) { + sender.sendMessage(ChatColor.RED + "Warning! You must restart the server to change the logging type."); + } } String[] PreformedMessages = new String[] { @@ -262,6 +308,6 @@ private String preformulateMessage(String str) { } private enum LoggingType{ - None, Json, Mysql + None, Json, Mysql, Sqlite } } diff --git a/src/findPlayer/IPlayerCache.java b/src/findPlayer/IPlayerCache.java index 34a3389..b518072 100644 --- a/src/findPlayer/IPlayerCache.java +++ b/src/findPlayer/IPlayerCache.java @@ -10,4 +10,12 @@ public interface IPlayerCache { PlayerStoreInfo GetPlayerInfo(UUID userId); void PopulateData(); + + void PurgeData(); + + void Close(); + + void UpdateDebug(Boolean useDebug); + + void UpdateFileWriteTime(long fileWriteTimeMs); } diff --git a/src/findPlayer/PlayerCache_Base.java b/src/findPlayer/PlayerCache_Base.java index 9612b72..aa55c17 100644 --- a/src/findPlayer/PlayerCache_Base.java +++ b/src/findPlayer/PlayerCache_Base.java @@ -1,5 +1,6 @@ package findPlayer; +import java.io.File; import java.util.HashMap; import java.util.TreeMap; import java.util.UUID; @@ -14,7 +15,8 @@ public PlayerCache_Base() { public final Logger logger; public HashMap Mapping; - public TreeMap NameMappings; + public final TreeMap NameMappings; + public File dataFile; public PlayerStoreInfo GetPlayerInfo(String Playername) { if (!NameMappings.containsKey(Playername)) return null; diff --git a/src/findPlayer/PlayerCache_Json.java b/src/findPlayer/PlayerCache_Json.java index c77a3fc..6252fac 100644 --- a/src/findPlayer/PlayerCache_Json.java +++ b/src/findPlayer/PlayerCache_Json.java @@ -9,6 +9,8 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; +import java.time.Duration; +import java.time.Instant; import java.time.LocalDateTime; import java.util.HashMap; import java.util.UUID; @@ -17,56 +19,86 @@ import com.google.gson.Gson; public class PlayerCache_Json extends PlayerCache_Base implements IPlayerCache { - public PlayerCache_Json(File dataDirectory) { + public PlayerCache_Json(File dataDirectory, long writeTimeMs, Boolean debugEnabled) { + this.useDebug = debugEnabled; gs = new Gson(); + this.dataFile = new File(dataDirectory, "PlayerInfo.json"); + this.writeTimeMs = writeTimeMs; + writer = new WriterClass(); + Thread thread = new Thread(writer); + thread.start(); } - private Boolean _isDirty; // used for flat file writes - private File dataFile; + private Boolean _isDirty = false; // used for flat file writes private Gson gs; + private WriterClass writer; + private long writeTimeMs; + private Boolean useDebug; + private final Object lockObj = new Object(); public Boolean getIsDirty(){ return _isDirty; } + + public void Close() { + if (writer != null) writer.doLoop = false; + if (!_isDirty) return; + + //TODO: once there is a disk writer queue then we'll need to make sure all is written here + WriteToDisk(); + } + + public void UpdateDebug(Boolean useDebug) { + this.useDebug = useDebug; + } + + public void UpdateFileWriteTime(long fileWriteTimeMs) { + this.writeTimeMs = fileWriteTimeMs; + } + + public void PurgeData() { + synchronized(lockObj) { + this.Mapping.clear(); + this.NameMappings.clear(); + this._isDirty = true; + } + } public void AddOrUpdatePlayerInfo(PlayerStoreInfo psi) { psi.lastOnline = LocalDateTime.now(); - Mapping.put(psi.userId, psi); - NameMappings.put(psi.playerName, psi.userId); - this._isDirty = true; - - // TODO: queue the disk writes instead of writing on each add entry - try { - WriteToDisk(); - } catch (IOException e) { - e.printStackTrace(); + synchronized(lockObj) { + Mapping.put(psi.userId, psi); + NameMappings.put(psi.playerName, psi.userId); + this._isDirty = true; } } - public void WriteToDisk() throws IOException { - String fileJson = gs.toJson(this.Mapping); + public void WriteToDisk() { + + synchronized(lockObj) { + String fileJson = gs.toJson(this.Mapping); - Writer fr = null; - try { - fr = new OutputStreamWriter(new FileOutputStream(this.dataFile), StandardCharsets.UTF_8); - fr.write(fileJson); - this._isDirty = false; - } catch (IOException e) { - e.printStackTrace(); - }finally{ - try { - if (fr != null) fr.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } + Writer fr = null; + try { + fr = new OutputStreamWriter(new FileOutputStream(this.dataFile), StandardCharsets.UTF_8); + fr.write(fileJson); + this._isDirty = false; + } catch (IOException e) { + logger.warning("Error writing to disk. " + e.getMessage()); + }finally{ + try { + if (fr != null) fr.close(); + } catch (IOException e) { } + } + this._isDirty = false; + } // end lock } public void PopulateData() { if (!this.dataFile.exists()) return; - //logger.info("about to read: " + dataFile.getAbsolutePath()); + if (useDebug) logger.info("about to read: " + dataFile.getAbsolutePath()); String jsonStr = null; try { @@ -84,6 +116,53 @@ public void PopulateData() { NameMappings.put(v.playerName, k); }); - //logger.info("items count: " + Mapping.size() + ", name mappings: " + NameMappings.size()); + if (useDebug) logger.info("items count: " + Mapping.size() + ", name mappings: " + NameMappings.size()); + } + +private class WriterClass implements Runnable{ + + private volatile Boolean needsWrite = false; + public Boolean doLoop = true; + + public void run() { + Instant starts = Instant.now(); + //Instant ends = Instant.now(); + //System.out.println(Duration.between(starts, ends)); + + if (useDebug) logger.info("json writer ready"); + + try { + // --------------------- begin writer loop ----------------------- + while (doLoop) { + if (!needsWrite) { + Thread.sleep(50); + + Instant ends = Instant.now(); + Duration dur = Duration.between(starts, ends); + if (dur.toMillis() < writeTimeMs) continue; + } + // loop above here if no work + + synchronized(lockObj){ + if (!_isDirty) { + needsWrite = false; + starts = Instant.now(); + continue; + } + } + + if (useDebug) logger.info("writer queue has work"); + + WriteToDisk(); + needsWrite = false; + starts = Instant.now(); + } + // --------------------- end writer loop ---------------------- + } + catch (InterruptedException e) { + return; + } + + } // end run } } diff --git a/src/findPlayer/PlayerCache_SQL.java b/src/findPlayer/PlayerCache_SQL.java index 97537f9..5367114 100644 --- a/src/findPlayer/PlayerCache_SQL.java +++ b/src/findPlayer/PlayerCache_SQL.java @@ -1,5 +1,6 @@ package findPlayer; +import java.io.File; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; @@ -8,47 +9,59 @@ import java.sql.Timestamp; import java.time.LocalDateTime; import java.sql.PreparedStatement; -import java.util.logging.Logger; import java.util.UUID; import java.util.concurrent.ConcurrentLinkedQueue; public class PlayerCache_SQL extends PlayerCache_Base implements IPlayerCache { - public PlayerCache_SQL(SQL_ConfigInfo config) { + public PlayerCache_SQL(MySQL_ConfigInfo config, Boolean debugEnabled) { + // since this constructor was used we are using mysql + this.useDebug = debugEnabled; this.config = config; + this.isSqlLite = false; } - private SQL_ConfigInfo config; + public PlayerCache_SQL(File dataDirectory, Boolean debugEnabled) { + // if no constructor is used, then this is sqlite + this.useDebug = debugEnabled; + this.isSqlLite = true; + this.whichSQL = "sqlite"; + this.dataFile = new File(dataDirectory, "PlayerInfo.db"); + } + + private MySQL_ConfigInfo config; private Connection connection; private Boolean isReady = false; private Boolean writerIsWorking; private final int port = 3306; - private final Logger logger = Logger.getLogger("Minecraft"); private WriterClass writer; + private Boolean useDebug; + private final Boolean isSqlLite; + private String whichSQL = "mysql"; public Boolean openConnection() { try { if (connection != null && !connection.isClosed()) return true; } catch (SQLException e) { - logger.warning("Error checking mysql connection. " + e.getMessage()); + logger.warning("Error checking " + whichSQL + " connection. " + e.getMessage()); return false; } - String connString = String.format( - "jdbc:mysql://%s:%s/%s?useSSL=false", - config.hostname, this.port, config.database); - - try { - Class.forName("com.mysql.jdbc.Driver"); - connection = DriverManager.getConnection(connString, config.username, config.password); - } catch (Exception e) { - logger.warning("Unable to open mysql. " + e.getMessage()); - return false; - } + String connString = null; + String createStatement = null; - try { - openConnection(); - Statement statement = connection.createStatement(); - statement.execute("CREATE TABLE IF NOT EXISTS playerLocations (" + if (this.isSqlLite) { + createStatement = "CREATE TABLE IF NOT EXISTS \"playerLocations\" (" + + " \"userId\" TEXT NOT NULL UNIQUE," + + " \"playerName\" TEXT NOT NULL," + + " \"locationX\" INTEGER NOT NULL," + + " \"locationY\" INTEGER NOT NULL," + + " \"locationZ\" INTEGER NOT NULL," + + " \"playerWorld\" TEXT NOT NULL," + + " \"lastSeen\" TEXT NOT NULL," + + " \"wgRegions\" TEXT," + + " PRIMARY KEY(\"userId\"))"; + } else { + createStatement = "CREATE TABLE IF NOT EXISTS playerLocations (" + "userId VARCHAR(255) PRIMARY KEY," + "playerName VARCHAR(255)," + "locationX INT," @@ -57,9 +70,32 @@ public Boolean openConnection() { + "playerWorld VARCHAR(255)," + "lastSeen TIMESTAMP," + "wgRegions VARCHAR(255)" - + ");"); + + ");"; + + connString = String.format( + "jdbc:mysql://%s:%s/%s?useSSL=false", + config.hostname, this.port, config.database); + } + + try { + if (this.isSqlLite) { + Class.forName("org.sqlite.JDBC"); + connection = DriverManager.getConnection("jdbc:sqlite:" + this.dataFile.getPath()); + } else { + Class.forName("com.mysql.jdbc.Driver"); + connection = DriverManager.getConnection(connString, config.username, config.password); + } + } catch (Exception e) { + logger.warning("Unable to open " + whichSQL + ". " + e.getMessage()); + return false; + } + + try { + openConnection(); + Statement statement = connection.createStatement(); + statement.execute(createStatement); } catch (SQLException e) { - logger.warning("Error executing mysql query. " + e.getMessage()); + logger.warning("Error executing " + whichSQL +" query. " + e.getMessage()); return false; } @@ -71,6 +107,46 @@ public Boolean openConnection() { return true; } + public void Close(){ + if (writer != null && writerIsWorking) { + writer.doLoop = false; + // wait up to 100 milliseconds to complete + try { + for (int i = 0; i < 50; i++) { + Thread.sleep(2); + if (!writerIsWorking) break; + } + } + catch (InterruptedException e) { } + } + + try { + if (connection != null && !connection.isClosed()) + connection.close(); + } catch(SQLException e) { } + } + + public void UpdateDebug(Boolean useDebug) { + this.useDebug = useDebug; + } + + public void UpdateFileWriteTime(long fileWriteTimeMs) { + // not used in this class + } + + public void PurgeData() { + if (writer != null) writer.PurgeQueue(); + this.Mapping.clear(); + this.NameMappings.clear(); + + try { + Statement query = connection.createStatement(); + query.execute("DELETE FROM playerLocations"); + } + catch (SQLException e) { + logger.warning("Error deleting from " + whichSQL + ". " + e.getMessage()); + } + } public void AddOrUpdatePlayerInfo(PlayerStoreInfo psi) { if (!isReady) return; @@ -123,7 +199,7 @@ private PlayerStoreInfo QueryDB(String userId, String playerName) { return psi; } catch (SQLException e) { - logger.warning("Error querying mysql. " + e.getMessage()); + logger.warning("Error querying " + whichSQL + ". " + e.getMessage()); } return null; @@ -142,7 +218,7 @@ public void PopulateData() { } } catch (SQLException e) { - logger.warning("Unable to query mysql." + e.getMessage()); + logger.warning("Unable to query " + whichSQL + "." + e.getMessage()); if (writer != null) writer.doLoop = false; isReady = false; return; @@ -152,10 +228,10 @@ public void PopulateData() { NameMappings.put(v.playerName, k); }); - logger.info("items count: " + Mapping.size() + ", name mappings: " + NameMappings.size()); + if (useDebug) logger.info("items count: " + Mapping.size() + ", name mappings: " + NameMappings.size()); } - private static PlayerStoreInfo getPlayerInfoFromQuery(ResultSet result) throws SQLException { + private PlayerStoreInfo getPlayerInfoFromQuery(ResultSet result) throws SQLException { UUID id = UUID.fromString(result.getString(1)); PlayerStoreInfo psi = new PlayerStoreInfo(id); psi.playerName = result.getString(2); @@ -163,8 +239,13 @@ private static PlayerStoreInfo getPlayerInfoFromQuery(ResultSet result) throws S psi.locationY = result.getInt(4); psi.locationZ = result.getInt(5); psi.worldName = result.getString(6); - Timestamp ts = (Timestamp)result.getObject(7); - psi.lastOnline = ts.toLocalDateTime(); + if (this.isSqlLite) { + psi.lastOnline = LocalDateTime.parse(result.getString(7)); + } else { + Timestamp ts = (Timestamp)result.getObject(7); + psi.lastOnline = ts.toLocalDateTime(); + } + psi.regionNames = result.getString(8); return psi; @@ -185,6 +266,13 @@ public void addItem(PlayerStoreInfo psi) { } } + public void PurgeQueue() { + synchronized(lockObj) { + queue.clear(); + hasWork = false; + } + } + public void run() { queue = new ConcurrentLinkedQueue(); @@ -192,11 +280,15 @@ public void run() { String cmdText = "INSERT INTO playerLocations (userId, playerName, locationX, locationY, locationZ, playerWorld, lastSeen, wgRegions)" // 1 2 3 4 5 6 7 8 + "VALUES (?, ?, ?, ?, ?, ?, ?, ?) " - // 9 10 11 12 13 14 - + "ON DUPLICATE KEY UPDATE userId = ?, playerName = ?, locationX = ?, locationY = ?, locationZ = ?, playerWorld = ?" + - // 15 16 + // 9 10 11 12 13 + + "ON DUPLICATE KEY UPDATE playerName = ?, locationX = ?, locationY = ?, locationZ = ?, playerWorld = ?" + + // 14 15 ", lastSeen = ?, wgRegions = ?"; + if (isSqlLite) { + cmdText = cmdText.replace("ON DUPLICATE KEY UPDATE", "ON CONFLICT(userId) DO UPDATE SET"); + } + try { statement = connection.prepareStatement(cmdText); } @@ -206,7 +298,7 @@ public void run() { } isReady = true; - logger.info("mysql ready for updates"); + if (useDebug) logger.info("sql ready for updates"); try { // --------------------- begin writer loop ----------------------- @@ -217,7 +309,7 @@ public void run() { } // loop above here if no work - logger.info("writer queue has work"); + if (useDebug) logger.info("writer queue has work"); PlayerStoreInfo item = null; @@ -235,21 +327,22 @@ public void run() { statement.setInt(4, item.locationY); statement.setInt(5, item.locationZ); statement.setString(6, item.worldName); - statement.setObject(7, item.lastOnline); + if (isSqlLite) statement.setString(7, item.lastOnline.toString()); + else statement.setObject(7, item.lastOnline); statement.setString(8, item.regionNames); - // now duplicate the values for the update statement (good old java eh?) - statement.setString(9, item.userId.toString()); - statement.setString(10, item.playerName); - statement.setInt(11, item.locationX); - statement.setInt(12, item.locationY); - statement.setInt(13, item.locationZ); - statement.setString(14, item.worldName); - statement.setObject(15, item.lastOnline); - statement.setString(16, item.regionNames); + // now (mostly) duplicate the values for the update statement (good old java eh?) + statement.setString(9, item.playerName); + statement.setInt(10, item.locationX); + statement.setInt(11, item.locationY); + statement.setInt(12, item.locationZ); + statement.setString(13, item.worldName); + if (isSqlLite) statement.setString(14, item.lastOnline.toString()); + else statement.setObject(14, item.lastOnline); + statement.setString(15, item.regionNames); statement.execute(); - logger.info("inserted or updated entry to mysql"); + if (useDebug) logger.info("inserted or updated entry to sql"); } // --------------------- end writer loop ---------------------- } @@ -262,27 +355,8 @@ public void run() { } // end run } - - public void closeConnection() { - if (writer != null && writerIsWorking) { - writer.doLoop = false; - // wait up to 100 milliseconds to complete - try { - for (int i = 0; i < 50; i++) { - Thread.sleep(2); - if (!writerIsWorking) break; - } - } - catch (InterruptedException e) { } - } - try { - if (connection != null && !connection.isClosed()) - connection.close(); - } catch(SQLException e) { } - } - - public static class SQL_ConfigInfo{ + public static class MySQL_ConfigInfo{ public String hostname; public String username; public String password; diff --git a/src/main/resources/conifg.yml b/src/main/resources/conifg.yml index 798eff1..a84e498 100644 --- a/src/main/resources/conifg.yml +++ b/src/main/resources/conifg.yml @@ -2,7 +2,7 @@ # this will be used to store player locations when they go offline. # if 'none' is selected then only online players' locations will be retrievable. -# options are mysql, json or none +# options are mysql, sqlite, json or none player-logging-type: json # these next 4 fields are only required if configured with mysql above @@ -11,7 +11,10 @@ mysql-database: "" mysql-username: "" mysql-password: "" -verbose-logging: false +# json only, how often to write to disk. It caches player information and writes only when there are changes +json-write-time-ms: 5000 # by default will write every 5 seconds + +debug: false # WorldGuard integration is supported. If installed the region(s) the target player is within will be shown. # The WG region placeholder is {WorldGuardRegion} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index b89c3e9..9649d3f 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: FindPlayer main: findPlayer.FindPlayer -version: 0.5 +version: 1.0 authors: - PenalBuffalo api-version: 1.13 diff --git a/target/classes/conifg.yml b/target/classes/conifg.yml index 798eff1..a84e498 100644 --- a/target/classes/conifg.yml +++ b/target/classes/conifg.yml @@ -2,7 +2,7 @@ # this will be used to store player locations when they go offline. # if 'none' is selected then only online players' locations will be retrievable. -# options are mysql, json or none +# options are mysql, sqlite, json or none player-logging-type: json # these next 4 fields are only required if configured with mysql above @@ -11,7 +11,10 @@ mysql-database: "" mysql-username: "" mysql-password: "" -verbose-logging: false +# json only, how often to write to disk. It caches player information and writes only when there are changes +json-write-time-ms: 5000 # by default will write every 5 seconds + +debug: false # WorldGuard integration is supported. If installed the region(s) the target player is within will be shown. # The WG region placeholder is {WorldGuardRegion} diff --git a/target/classes/main/resources/conifg.yml b/target/classes/main/resources/conifg.yml index 798eff1..a84e498 100644 --- a/target/classes/main/resources/conifg.yml +++ b/target/classes/main/resources/conifg.yml @@ -2,7 +2,7 @@ # this will be used to store player locations when they go offline. # if 'none' is selected then only online players' locations will be retrievable. -# options are mysql, json or none +# options are mysql, sqlite, json or none player-logging-type: json # these next 4 fields are only required if configured with mysql above @@ -11,7 +11,10 @@ mysql-database: "" mysql-username: "" mysql-password: "" -verbose-logging: false +# json only, how often to write to disk. It caches player information and writes only when there are changes +json-write-time-ms: 5000 # by default will write every 5 seconds + +debug: false # WorldGuard integration is supported. If installed the region(s) the target player is within will be shown. # The WG region placeholder is {WorldGuardRegion} diff --git a/target/classes/main/resources/plugin.yml b/target/classes/main/resources/plugin.yml index b89c3e9..9649d3f 100644 --- a/target/classes/main/resources/plugin.yml +++ b/target/classes/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: FindPlayer main: findPlayer.FindPlayer -version: 0.5 +version: 1.0 authors: - PenalBuffalo api-version: 1.13 diff --git a/target/classes/plugin.yml b/target/classes/plugin.yml index b89c3e9..9649d3f 100644 --- a/target/classes/plugin.yml +++ b/target/classes/plugin.yml @@ -1,6 +1,6 @@ name: FindPlayer main: findPlayer.FindPlayer -version: 0.5 +version: 1.0 authors: - PenalBuffalo api-version: 1.13 diff --git a/target/maven-archiver/pom.properties b/target/maven-archiver/pom.properties index 7ce7dbd..62adc20 100644 --- a/target/maven-archiver/pom.properties +++ b/target/maven-archiver/pom.properties @@ -1,5 +1,5 @@ #Generated by Maven -#Wed Dec 30 13:26:42 CST 2020 +#Wed Dec 30 18:27:49 CST 2020 groupId=FindPlayer artifactId=FindPlayer -version=0.5 +version=1.0