diff --git a/default.code-workspace b/default.code-workspace index 6aaf09d..2b38439 100644 --- a/default.code-workspace +++ b/default.code-workspace @@ -11,6 +11,7 @@ "java.jdt.ls.vmargs": "-Dfile.encoding=UTF-8", "javac-linter.javac": "javac -Dfile.encoding=UTF-8", "java.configuration.updateBuildConfiguration": "automatic", - "java.format.settings.url": "eclipse-formatter.xml" + "java.format.settings.url": "eclipse-formatter.xml", + "java.compile.nullAnalysis.mode": "automatic" } } \ No newline at end of file diff --git a/ic_plugin/src/main/java/nl/interestingcorner/App.java b/ic_plugin/src/main/java/nl/interestingcorner/App.java index 88f5591..e241fdd 100644 --- a/ic_plugin/src/main/java/nl/interestingcorner/App.java +++ b/ic_plugin/src/main/java/nl/interestingcorner/App.java @@ -1,24 +1,47 @@ package nl.interestingcorner; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.PluginCommand; import org.bukkit.plugin.java.JavaPlugin; +import nl.interestingcorner.commands.GetCoordinatesCommand; import nl.interestingcorner.db.DatabaseManager; public class App extends JavaPlugin { + @Override public void onEnable() { getLogger().info("Eyooo we boutta get lit!"); - - // saveDefaultConfig(); // create config.yml if not exists - if (!DatabaseManager.INSTANCE.initialize(this)) - { + + if (!DatabaseManager.INSTANCE.initialize(this)) { getLogger().severe("Could not initialize database. Exiting!"); setEnabled(false); return; } + + registerCommands(); + } + @Override public void onDisable() { getLogger().info("Eyooo we outta here!"); + + if (!DatabaseManager.INSTANCE.close()) { + getLogger().severe("Error while trying to close db connection"); + } + } + + private void registerCommands() { + registerSimgleCommand("get_coords", new GetCoordinatesCommand()); + } + + private void registerSimgleCommand(String name, CommandExecutor executor) + { + PluginCommand pc = this.getCommand(name); + if (pc != null) + { + pc.setExecutor(executor); + } } } diff --git a/ic_plugin/src/main/java/nl/interestingcorner/commands/GetCoordinatesCommand.java b/ic_plugin/src/main/java/nl/interestingcorner/commands/GetCoordinatesCommand.java new file mode 100644 index 0000000..561e0f4 --- /dev/null +++ b/ic_plugin/src/main/java/nl/interestingcorner/commands/GetCoordinatesCommand.java @@ -0,0 +1,34 @@ +package nl.interestingcorner.commands; + +import java.sql.PreparedStatement; +import java.util.List; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import nl.interestingcorner.db.Coordinate; +import nl.interestingcorner.db.DatabaseManager; + +public class GetCoordinatesCommand implements CommandExecutor{ + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (sender instanceof Player player) + { + List coords = DatabaseManager.INSTANCE.getAllCoordinates(); + StringBuilder res = new StringBuilder("Coordinates: "); + + for (Coordinate coordinate : coords) { + res.append(coordinate.toString()); + } + + player.sendMessage(res.toString()); + } + return true; + + } + + +} \ No newline at end of file diff --git a/ic_plugin/src/main/java/nl/interestingcorner/db/Coordinate.java b/ic_plugin/src/main/java/nl/interestingcorner/db/Coordinate.java new file mode 100644 index 0000000..883458b --- /dev/null +++ b/ic_plugin/src/main/java/nl/interestingcorner/db/Coordinate.java @@ -0,0 +1,89 @@ +package nl.interestingcorner.db; + +/** + * +-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+------+-----+---------+----------------+ + * | Field | Type | Null | Key | Default | Extra | + * +-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+------+-----+---------+----------------+ + * | id | int | NO | PRI | NULL | auto_increment | + * | name | varchar(255) | NO | | NULL | | + * | x | int | NO | | NULL | | + * | y | int | NO | | NULL | | + * | z | int | NO | | NULL | | + * | description | varchar(255) | NO | | NULL | | + * | color | + * enum('dark_red','red','black','blue','aqua','dark_aqua','green','gold','dark_purple','light_purple','yellow','dark_green','gray','dark_gray','white','dark_blue') + * | YES | | white | | + * | nether | tinyint(1) | YES | | 0 | | + * +-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+------+-----+---------+----------------+ + */ + +public class Coordinate { + /** + * auto-generated ID + */ + public int id; + + /** + * name of the coordinate + */ + public String name; + + /** + * description of the coordinate + */ + public String description; + + /** + * position in x,y,z + */ + public Position position; + + /** + * If the coordinate is in the nether + */ + public boolean nether; + + /** + * The color to display the coordinate name in + */ + public MinecraftColor color; + + /** + * the world for this coordinate. This corresponds to the name of the world in + * Multiverse + */ + public String world; + + public record Position(int x, int y, int z) { + } + + public static String createTableStatement = """ + CREATE TABLE IF NOT EXISTS coordinates ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) NOT NULL, + description VARCHAR(255), + x INT NOT NULL, + y INT NOT NULL, + z INT NOT NULL, + nether BOOLEAN NOT NULL DEFAULT FALSE, + color VARCHAR(255), + world VARCHAR(255) DEFAULT "white" + ); + """; + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("{ "); + sb.append("id: ").append(id) + .append(", name: '").append(name).append('\'') + .append(", description: '").append(description).append('\'') + .append(", position: { x: ").append(position.x()) + .append(", y: ").append(position.y()) + .append(", z: ").append(position.z()).append(" }") + .append(", nether: ").append(nether) + .append(", color: ").append(color != null ? color.toString() : "null") + .append(", world: '").append(world).append('\'') + .append(" }"); + return sb.toString(); + } +} diff --git a/ic_plugin/src/main/java/nl/interestingcorner/db/DatabaseManager.java b/ic_plugin/src/main/java/nl/interestingcorner/db/DatabaseManager.java index 68015d0..54cf0d3 100644 --- a/ic_plugin/src/main/java/nl/interestingcorner/db/DatabaseManager.java +++ b/ic_plugin/src/main/java/nl/interestingcorner/db/DatabaseManager.java @@ -6,7 +6,11 @@ import java.io.FileReader; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; @@ -20,11 +24,95 @@ public enum DatabaseManager { private Connection connection; private JavaPlugin app; + /** + * Initializes the database. Creates the file and sets up the db structure. + * + * @param app the app to use for logging + * @return true if the database was initialized successfully. False if not. + */ public boolean initialize(JavaPlugin app) { this.app = app; - if (!app.getDataFolder().exists()) { - if (!app.getDataFolder().mkdirs()) { + if (!setupDatabase()) { + return false; + } + + if (!initializeTables()) { + return false; + } + + return true; + } + + /** + * Closes the connectino to the database + * + * @return true if the connection closed succesfully, false if not. + */ + public boolean close() { + try { + if (this.connection != null && !this.connection.isClosed()) { + this.connection.close(); + } + } catch (SQLException ex) { + this.app.getLogger().log(Level.SEVERE, "Error while closing the databse connection: {0}", ex.getMessage()); + return false; + } + + return true; + } + + /** + * Gets all coordinates from the database + * + * @return a list with all coordinates from the database. Empty if an error + * occurred. + */ + public List getAllCoordinates() { + List result = new ArrayList<>(); + try { + PreparedStatement getAllCoordinatesStatement = this.connection + .prepareStatement("SELECT * FROM coordinates"); + ResultSet allCoordinates = getAllCoordinatesStatement.executeQuery(); + + while (allCoordinates.next()) { + Coordinate c = new Coordinate(); + + c.id = allCoordinates.getInt("id"); + c.name = allCoordinates.getString("name"); + c.description = allCoordinates.getString("description"); + c.position = new Coordinate.Position( + allCoordinates.getInt("x"), + allCoordinates.getInt("y"), + allCoordinates.getInt("z")); + c.nether = allCoordinates.getBoolean("nether"); + + MinecraftColor color = MinecraftColor.fromString(allCoordinates.getString("color")); + if (color == null) { + color = MinecraftColor.WHITE; + } + c.color = color; + + c.world = allCoordinates.getString("world"); + + result.add(c); + } + + } catch (SQLException e) { + this.app.getLogger().log(Level.SEVERE, "Could not get commands! {0}", e.getMessage()); + } + return result; + } + + /** + * Sets up the connectino to the database. Creates a new .db file if it doesn't + * exist yet. + * + * @return true if the connection was set up successfully. False if not. + */ + private boolean setupDatabase() { + if (!this.app.getDataFolder().exists()) { + if (!this.app.getDataFolder().mkdirs()) { app.getLogger().severe("Could not create data folder"); return false; } @@ -35,16 +123,36 @@ public enum DatabaseManager { try { this.connection = DriverManager.getConnection(url); - } - catch (SQLException e) { - app.getLogger().log(Level.SEVERE, "Could not connect to database file {0}: {1}", + } catch (SQLException e) { + this.app.getLogger().log(Level.SEVERE, "Could not connect to database file {0}: {1}", new Object[] { dbFile, e.getMessage() }); } - - app.getLogger().log(Level.INFO, "Connected to SQLite database: {0}", dbFile.getName()); + + this.app.getLogger().log(Level.INFO, "Connected to SQLite database: {0}", dbFile.getName()); return true; + } + /** + * initializes the tables for the database. + * + * @return true if the tables were initialized successfully. False if not. + */ + private boolean initializeTables() { + try { + PreparedStatement createTableStatement = this.connection.prepareStatement(Coordinate.createTableStatement); + createTableStatement.executeUpdate(); + this.app.getLogger().fine("Executed create table statement"); + + PreparedStatement getTablesStatement = this.connection.prepareStatement("show tables"); + ResultSet results = getTablesStatement.executeQuery(); + + this.app.getLogger().info(results.getString(1)); + } catch (SQLException e) { + this.app.getLogger().log(Level.SEVERE, "Could not create table: {0}", e.getMessage()); + return false; + } + return true; } } diff --git a/ic_plugin/src/main/java/nl/interestingcorner/db/MinecraftColor.java b/ic_plugin/src/main/java/nl/interestingcorner/db/MinecraftColor.java new file mode 100644 index 0000000..9476f9d --- /dev/null +++ b/ic_plugin/src/main/java/nl/interestingcorner/db/MinecraftColor.java @@ -0,0 +1,54 @@ +package nl.interestingcorner.db; + +public enum MinecraftColor { + DARK_RED("dark_red"), + RED("red"), + BLACK("black"), + BLUE("blue"), + AQUA("aqua"), + DARK_AQUA("dark_aqua"), + GREEN("green"), + GOLD("gold"), + DARK_PURPLE("dark_purple"), + LIGHT_PURPLE("light_purple"), + YELLOW("yellow"), + DARK_GREEN("dark_green"), + GRAY("gray"), + DARK_GRAY("dark_gray"), + WHITE("white"), + DARK_BLUE("dark_blue"); + + private final String name; + + MinecraftColor(String name) { + this.name = name; + } + + public boolean equalsName(String otherName) { + return name.equalsIgnoreCase(otherName); + } + + @Override + public String toString() { + return this.name; + } + + /** + * Finds a MinecraftColor from a string value + * + * @param name the name to find the MinecraftColor from + * @return the MinecraftColor if found, null if not found. + */ + public static MinecraftColor fromString(String name) { + if (name == null) { + return null; + } + + for (MinecraftColor color : MinecraftColor.values()) { + if (color.equalsName(name)) { + return color; + } + } + return null; + } +}