diff --git a/README.md b/README.md
index a4210ed..f76a987 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,49 @@
# WHIMC-PositionTracker
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/whimc/Position-Tracker?label=download&logo=github)](https://github.com/whimc/Position-Tracker/releases/latest)
-Track player positions to a database
+PositionTracker is a Minecraft plugin that tracks player positions and stores them in an SQL database.
+
+---
## Building
Build the source with Maven:
```
$ mvn install
-```
\ No newline at end of file
+```
+
+---
+
+## Configuration
+
+`debug` is a `boolean` that toggles debug messages in the console.
+
+### MySQL
+| Key | Type | Description |
+|------------------|-----------|---------------------------------|
+| `mysql.host` | `string` | The host of the database |
+| `mysql.port` | `integer` | The port of the database |
+| `mysql.database` | `string` | The name of the database to use |
+| `mysql.username` | `string` | Username for credentials |
+| `mysql.password` | `string` | Password for credentials |
+
+#### Example
+```yaml
+debug: false
+mysql:
+ host: localhost
+ port: 3306
+ database: minecraft
+ username: user
+ password: pass
+```
+
+---
+
+## Commands
+| Command | Description |
+|---------------------------|--------------------------------------|
+| `/positiontracker status` | Get the status of the tracker |
+| `/positiontracker debug` | Toggle the debug messages in console |
+| `/positiontracker start` | Start the tracker |
+| `/positiontracker stop` | Stop the tracker |
+
diff --git a/pom.xml b/pom.xml
index 560c72b..b5db782 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
edu.whimc
WHIMC-PositionTracker
- 2.0.5
+ 2.1.0
WHIMC Position Tracker
Track player positions to a database
diff --git a/src/main/java/edu/whimc/positiontracker/JoinLeaveListener.java b/src/main/java/edu/whimc/positiontracker/JoinLeaveListener.java
index 1e20340..b0f5ac8 100644
--- a/src/main/java/edu/whimc/positiontracker/JoinLeaveListener.java
+++ b/src/main/java/edu/whimc/positiontracker/JoinLeaveListener.java
@@ -6,20 +6,38 @@
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
+/**
+ * Handles toggling of data collection based on number of current online players.
+ */
public class JoinLeaveListener implements Listener {
-
+ /** The instance of the plugin. */
private Tracker plugin;
-
+
+ /**
+ * Constructs a JoinLeaveListener.
+ *
+ * @param plugin
+ */
public JoinLeaveListener(Tracker plugin) {
this.plugin = plugin;
}
-
+
+ /**
+ * Starts data collection if it's not running already.
+ *
+ * @param event the event called when a player joins the server.
+ */
@EventHandler
public void onJoin(PlayerJoinEvent event) {
if (plugin.isRunning()) return;
plugin.startRunner();
}
-
+
+ /**
+ * Stops data collection when there are no players online.
+ *
+ * @param event the event called when a player joins the server.
+ */
@EventHandler
public void onLeave(PlayerQuitEvent event) {
if (Bukkit.getOnlinePlayers().size() != 0) return;
diff --git a/src/main/java/edu/whimc/positiontracker/Tracker.java b/src/main/java/edu/whimc/positiontracker/Tracker.java
index fd79b04..a953170 100644
--- a/src/main/java/edu/whimc/positiontracker/Tracker.java
+++ b/src/main/java/edu/whimc/positiontracker/Tracker.java
@@ -5,12 +5,20 @@
import edu.whimc.positiontracker.sql.Queryer;
+/**
+ * The main plugin class.
+ */
public class Tracker extends JavaPlugin {
-
+ /** The current Task's ID. */
private int taskID = -1;
+ /** The debug mode status. */
private boolean debug = false;
+ /** The Queryer for the SQL database */
private Queryer queryer;
-
+
+ /**
+ * {@inheritDoc}
+ */
@Override
public void onEnable() {
saveDefaultConfig();
@@ -34,7 +42,13 @@ public void onEnable() {
}
+ /**
+ * Starts player location data collection.
+ *
+ * @return whether or not the data collection has been successfully started.
+ */
public boolean startRunner() {
+ // check if already running
if (taskID != -1) {
this.getLogger().warning("The runner has already been started!");
return false;
@@ -50,7 +64,13 @@ public boolean startRunner() {
return true;
}
+ /**
+ * Stops player data collection.
+ *
+ * @return whether or not the data collection has been successfully stopped.
+ */
public boolean stopRunner() {
+ // check if already stopped
if (!isRunning()) {
return false;
}
@@ -60,23 +80,41 @@ public boolean stopRunner() {
return true;
}
+ /**
+ * @return if the data collection is running.
+ */
public boolean isRunning() {
return Bukkit.getScheduler().isQueued(taskID);
}
+ /**
+ * @return the current task ID.
+ */
public int getTaskID() {
return taskID;
}
+ /**
+ * Prints the passed String into the server logs.
+ *
+ * @param str the String to print.
+ */
public void debugLog(String str) {
+ // check if in debug mode
if (!this.debug) return;
this.getLogger().info(str);
}
+ /**
+ * @return whether or not debug mode is enabled.
+ */
public boolean getDebug() {
return this.debug;
}
+ /**
+ * @param bool the debug desired status (true = on, false = off).
+ */
public void setDebug(boolean bool) {
this.debug = bool;
}
diff --git a/src/main/java/edu/whimc/positiontracker/TrackerCommand.java b/src/main/java/edu/whimc/positiontracker/TrackerCommand.java
index 523eb18..4653798 100644
--- a/src/main/java/edu/whimc/positiontracker/TrackerCommand.java
+++ b/src/main/java/edu/whimc/positiontracker/TrackerCommand.java
@@ -5,27 +5,41 @@
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
+/**
+ * Main handler for the /positiontracker root command.
+ */
public class TrackerCommand implements CommandExecutor{
-
+ /** The instance of the plugin. */
private Tracker plugin;
-
+
+ /**
+ * Constructs a TrackerCommand.
+ *
+ * @param plugin the instance of the plugin.
+ */
public TrackerCommand(Tracker plugin) {
this.plugin = plugin;
}
-
+
+ /**
+ * {@inheritDoc}
+ */
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
+ // ensure sender is an operator
if (!sender.isOp()) {
sender.sendMessage(ChatColor.RED + "You must be OP to use this command!");
return true;
}
-
+
+ // send valid command list if no arguments provided
if (args.length == 0) {
sendCommands(sender);
return true;
}
String arg = args[0];
-
+
+ // toggling debug mode
if (arg.equalsIgnoreCase("debug")) {
String message = ChatColor.YELLOW + "Console debug messages are now ";
if (plugin.getDebug()) {
@@ -41,7 +55,8 @@ public boolean onCommand(CommandSender sender, Command cmd, String label, String
}
boolean running = plugin.isRunning();
-
+
+ // checking plugin status
if (arg.equalsIgnoreCase("status")) {
String message = ChatColor.YELLOW + "PositionTracker is currently ";
@@ -56,8 +71,10 @@ public boolean onCommand(CommandSender sender, Command cmd, String label, String
sender.sendMessage(message);
return true;
}
-
+
+ // starting the tracker
if (arg.equalsIgnoreCase("start")) {
+ // notify sender if already running
if (running) {
sender.sendMessage(ChatColor.RED + "The tracker is already running!");
return true;
@@ -72,8 +89,10 @@ public boolean onCommand(CommandSender sender, Command cmd, String label, String
return true;
}
-
+
+ // stopping the tracker
if (arg.equalsIgnoreCase("stop")) {
+ // notify sender if already stopped
if (!running) {
sender.sendMessage(ChatColor.RED + "The tracker is already stopped!");
return true;
@@ -88,11 +107,16 @@ public boolean onCommand(CommandSender sender, Command cmd, String label, String
return true;
}
-
+
sendCommands(sender);
return true;
}
-
+
+ /**
+ * Sends the list of commands and their usage to the sender.
+ *
+ * @param sender the command's sender.
+ */
private void sendCommands(CommandSender sender) {
sender.sendMessage(ChatColor.DARK_RED + "" + ChatColor.BOLD + "Position Tracker");
sender.sendMessage(ChatColor.RED + "" + ChatColor.ITALIC +
diff --git a/src/main/java/edu/whimc/positiontracker/sql/MySQLConnection.java b/src/main/java/edu/whimc/positiontracker/sql/MySQLConnection.java
index d937df2..4ad3957 100644
--- a/src/main/java/edu/whimc/positiontracker/sql/MySQLConnection.java
+++ b/src/main/java/edu/whimc/positiontracker/sql/MySQLConnection.java
@@ -7,10 +7,15 @@
import edu.whimc.positiontracker.Tracker;
+/**
+ * Handles the connection to the SQL database.
+ */
public class MySQLConnection {
-
+ /** The SQL Driver class package. */
public static final String DRIVER_CLASS = "com.mysql.jdbc.Driver";
+ /** The template for the URL. */
public static final String URL_TEMPLATE = "jdbc:mysql://%s:%s/%s";
+ /** The SQL command to create a table. */
public static final String CREATE_TABLE =
"CREATE TABLE IF NOT EXISTS `whimc_player_positions` (" +
" `rowid` BIGINT AUTO_INCREMENT NOT NULL," +
@@ -23,27 +28,44 @@ public class MySQLConnection {
" `uuid` VARCHAR(36) NOT NULL," +
" `time` BIGINT NOT NULL," +
" PRIMARY KEY (`rowid`));";
-
+
+ /** The connection to the SQL database. */
private Connection connection;
+ /** The SQL database credentials. */
private String host, database, username, password, url;
+ /** The SQL database port. */
private int port;
-
+
+ /**
+ * Constructs a MySQLConnection.
+ *
+ * @param plugin The instance of the plugin.
+ */
public MySQLConnection(Tracker plugin) {
+ // fetch credentials and database info from config
this.host = plugin.getConfig().getString("mysql.host", "localhost");
this.port = plugin.getConfig().getInt("mysql.port", 3306);
this.database = plugin.getConfig().getString("mysql.database", "minecraft");
this.username = plugin.getConfig().getString("mysql.username", "user");
this.password = plugin.getConfig().getString("mysql.password", "pass");
-
+
+ // create the URL with the fetched information
this.url = String.format(URL_TEMPLATE, host, port, database);
}
-
+
+ /**
+ * Initializes the MySQLConnection.
+ *
+ * @return true if the connection succeeds.
+ */
public boolean initialize() {
+ // ensure there is a connection
if (getConnection() == null) {
return false;
}
try {
+ // create a table
PreparedStatement statement = this.connection.prepareStatement(CREATE_TABLE);
statement.execute();
} catch (SQLException e) {
@@ -52,13 +74,20 @@ public boolean initialize() {
return true;
}
-
+
+ /**
+ * Fetches the connection to the SQL database.
+ *
+ * @return the SQL database Connection.
+ */
public Connection getConnection() {
try {
+ // ensure connection exists and is open
if (this.connection != null && !this.connection.isClosed()) {
return this.connection;
}
-
+
+ // try connecting if a connection doesn't currently exist
Class.forName(DRIVER_CLASS);
this.connection = DriverManager.getConnection(this.url, this.username, this.password);
} catch (SQLException | ClassNotFoundException e) {
@@ -67,8 +96,12 @@ public Connection getConnection() {
return this.connection;
}
-
+
+ /**
+ * Closes the connection to the SQL database.
+ */
public void closeConnection() {
+ // ensure connection exists
if (this.connection != null) {
try {
this.connection.close();
diff --git a/src/main/java/edu/whimc/positiontracker/sql/Queryer.java b/src/main/java/edu/whimc/positiontracker/sql/Queryer.java
index b611dac..c5add41 100644
--- a/src/main/java/edu/whimc/positiontracker/sql/Queryer.java
+++ b/src/main/java/edu/whimc/positiontracker/sql/Queryer.java
@@ -15,15 +15,29 @@
import edu.whimc.positiontracker.Tracker;
+/**
+ * Handles adding position data to the SQL Database.
+ */
public class Queryer {
+ /**
+ * An entry containing data on the current player's position and time it was created.
+ */
public class PositionEntry {
-
+ /** The x, y, and z coordinates representing the position. */
private final int x, y, z;
+ /** The current world, biome, and player's username. */
private final String world, biome, username;
+ /** The unique ID for this entry. */
private final UUID uuid;
+ /** The time the entry was created. */
private final Timestamp time;
+ /**
+ * Constructs a PositionEntry.
+ *
+ * @param player the current player.
+ */
public PositionEntry(Player player) {
Location loc = player.getLocation();
this.x = loc.getBlockX();
@@ -42,6 +56,12 @@ public PositionEntry(Player player) {
this.time = new Timestamp(System.currentTimeMillis());
}
+ /**
+ * Adds this entry's data to the PreparedStatement's batch
+ *
+ * @param statement the SQL PreparedStatement.
+ * @throws SQLException when the statement cannot be added.
+ */
public void addInsertionToBatch(PreparedStatement statement) throws SQLException {
statement.setInt(1, this.x);
statement.setInt(2, this.y);
@@ -56,14 +76,23 @@ public void addInsertionToBatch(PreparedStatement statement) throws SQLException
}
+ /** SQL query to insert position data. */
private static final String INSERT_FORMAT =
"INSERT INTO `whimc_player_positions` " +
"(x, y, z, world, biome, username, uuid, time) " +
"VALUES(?, ?, ?, ?, ?, ?, ?, ?)";
+ /** The instance of the plugin. */
private Tracker plugin;
+ /** The connection to the SQL database. */
private MySQLConnection sqlConnection;
+ /**
+ * Constructs a Queryer.
+ *
+ * @param plugin the instance of the plugin.
+ * @param callback the event callback.
+ */
public Queryer(Tracker plugin, Consumer callback) {
this.plugin = plugin;
this.sqlConnection = new MySQLConnection(plugin);
@@ -76,11 +105,16 @@ public Queryer(Tracker plugin, Consumer callback) {
});
}
+ /**
+ * Stores the position data.
+ */
public void storePositionData() {
+ // get position data for all online players
final List entries = Bukkit.getOnlinePlayers().stream()
.map(PositionEntry::new)
.collect(Collectors.toList());
+ // add data to database asynchronously
Bukkit.getScheduler().runTaskAsynchronously(this.plugin, () -> {
try (Connection connection = this.sqlConnection.getConnection()) {
connection.setAutoCommit(false);