diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml index 27df5ab..8f865a7 100644 --- a/dependency-reduced-pom.xml +++ b/dependency-reduced-pom.xml @@ -4,7 +4,7 @@ com.adzel.velocitybroadcast velocitybroadcast VelocityBroadcast - 0.2-pre + 0.3-pre Broadcast plugin for Minecraft Velocity proxy. @@ -25,7 +25,7 @@ shade - true + false @@ -37,6 +37,10 @@ velocitypowered-repo https://repo.velocitypowered.com/releases/ + + central + https://repo.maven.apache.org/maven2 + diff --git a/pom.xml b/pom.xml index 4bfc26d..dac361d 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.adzel.velocitybroadcast velocitybroadcast - 0.2-pre + 0.3-pre jar VelocityBroadcast Broadcast plugin for Minecraft Velocity proxy. @@ -21,6 +21,10 @@ velocitypowered-repo https://repo.velocitypowered.com/releases/ + + central + https://repo.maven.apache.org/maven2 + @@ -45,6 +49,34 @@ adventure-text-minimessage 4.15.0 + + + + org.json + json + 20240303 + + + + + org.xerial + sqlite-jdbc + 3.43.2.2 + + + + + com.mysql + mysql-connector-j + 8.4.0 + + + + + org.yaml + snakeyaml + 2.2 + @@ -71,8 +103,7 @@ shade - true - + false @@ -80,3 +111,5 @@ + \ No newline at end of file diff --git a/src/main/java/com/adzel/velocitybroadcast/BroadcastCommand.java b/src/main/java/com/adzel/velocitybroadcast/BroadcastCommand.java index 21d1fd5..d70d6e2 100644 --- a/src/main/java/com/adzel/velocitybroadcast/BroadcastCommand.java +++ b/src/main/java/com/adzel/velocitybroadcast/BroadcastCommand.java @@ -2,8 +2,10 @@ package com.adzel.velocitybroadcast; import java.util.List; +import com.adzel.velocitybroadcast.util.DatabaseManager; import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.command.SimpleCommand; +import com.velocitypowered.api.proxy.Player; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; @@ -11,9 +13,11 @@ import net.kyori.adventure.text.minimessage.MiniMessage; public class BroadcastCommand implements SimpleCommand { private final VelocityBroadcast plugin; + private final DatabaseManager databaseManager; public BroadcastCommand(VelocityBroadcast plugin) { this.plugin = plugin; + this.databaseManager = plugin.getDatabaseManager(); } @Override @@ -42,5 +46,13 @@ public class BroadcastCommand implements SimpleCommand { if (plugin.getConfigHandler().isDebugEnabled()) { plugin.getLogger().info("[Broadcast] Sent: " + fullMessage); } + + // ✅ Log to the database + String sender = (source instanceof Player) + ? ((Player) source).getUsername() + : "Console"; + + String sourceServer = plugin.getServer().getBoundAddress().toString(); // optional + databaseManager.logBroadcast(sender, messageRaw, sourceServer); } } diff --git a/src/main/java/com/adzel/velocitybroadcast/ConfigHandler.java b/src/main/java/com/adzel/velocitybroadcast/ConfigHandler.java index 634da63..bb3fd04 100644 --- a/src/main/java/com/adzel/velocitybroadcast/ConfigHandler.java +++ b/src/main/java/com/adzel/velocitybroadcast/ConfigHandler.java @@ -1,16 +1,16 @@ package com.adzel.velocitybroadcast; -import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import org.slf4j.Logger; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.representer.Representer; public class ConfigHandler { private final Path configPath; @@ -20,14 +20,34 @@ public class ConfigHandler { private boolean versionCheckEnabled = true; private String prefix = "&9&l[&3&lServer&9&l]&r "; + private String dbType = "sqlite"; + private String dbHost = "localhost"; + private int dbPort = 3306; + private String dbName = "velocitybroadcast"; + private String dbUser = "vb_user"; + private String dbPassword = "securepassword"; + private static final String CURRENT_VERSION = VelocityBroadcast.PLUGIN_VERSION; private static final String VERSION_LINE = "# DO NOT EDIT\nPlugin Version: '" + CURRENT_VERSION + "' # Do not edit this value, as it will mess up version checking and break the plugin"; + private final Yaml yaml; + public ConfigHandler(Path configPath, Logger logger) { this.configPath = configPath; this.logger = logger; + + DumperOptions options = new DumperOptions(); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + options.setIndent(2); + options.setPrettyFlow(true); + + Representer representer = new Representer(options); + representer.getPropertyUtils().setSkipMissingProperties(true); + + yaml = new Yaml(representer, options); } + @SuppressWarnings("unchecked") public void load() { try { Files.createDirectories(configPath.getParent()); @@ -39,38 +59,34 @@ public class ConfigHandler { return; } - List lines = Files.readAllLines(configPath); - String fileVersion = null; - - for (String line : lines) { - if (line.trim().startsWith("Plugin Version:")) { - fileVersion = line.replaceAll(".*'(.*?)'.*", "$1").trim(); - break; - } - } + String fileVersion = Files.readAllLines(configPath).stream() + .filter(line -> line.startsWith("Plugin Version:")) + .map(line -> line.replaceAll(".*'(.*?)'.*", "$1").trim()) + .findFirst() + .orElse(null); if (fileVersion == null || !fileVersion.equals(CURRENT_VERSION)) { shouldSave = true; } - try (BufferedReader reader = Files.newBufferedReader(configPath)) { - Map configMap = reader.lines() - .filter(line -> line.contains(":") && !line.trim().startsWith("#")) - .map(line -> line.replaceAll("#.*", "").split(":", 2)) - .collect(Collectors.toMap( - a -> a[0].trim(), - a -> a[1].trim().replaceAll("^['\"]|['\"]$", ""), - (a, b) -> b, - LinkedHashMap::new - )); + Map root = yaml.load(Files.newBufferedReader(configPath)); + if (root == null) root = new LinkedHashMap<>(); - debugEnabled = Boolean.parseBoolean(configMap.getOrDefault("debug-messages-enabled", "false")); - versionCheckEnabled = Boolean.parseBoolean(configMap.getOrDefault("version-check-enabled", "true")); - prefix = configMap.getOrDefault("prefix", "&9&l[&3&lServer&9&l]&r "); - } + Map general = (Map) root.getOrDefault("general", new LinkedHashMap<>()); + debugEnabled = Boolean.parseBoolean(String.valueOf(general.getOrDefault("debug-messages-enabled", "false"))); + versionCheckEnabled = Boolean.parseBoolean(String.valueOf(general.getOrDefault("version-check-enabled", "true"))); + prefix = String.valueOf(general.getOrDefault("prefix", "&9&l[&3&lServer&9&l]&r ")); + + Map database = (Map) root.getOrDefault("database", new LinkedHashMap<>()); + dbType = String.valueOf(database.getOrDefault("type", "sqlite")); + dbHost = String.valueOf(database.getOrDefault("host", "localhost")); + dbPort = Integer.parseInt(String.valueOf(database.getOrDefault("port", "3306"))); + dbName = String.valueOf(database.getOrDefault("name", "velocitybroadcast")); + dbUser = String.valueOf(database.getOrDefault("user", "vb_user")); + dbPassword = String.valueOf(database.getOrDefault("password", "securepassword")); if (shouldSave) { - save(); // Update config with new version and preserve user values + save(); } } catch (IOException e) { @@ -82,26 +98,28 @@ public class ConfigHandler { try { Files.createDirectories(configPath.getParent()); - String editableSection = ""; - if (Files.exists(configPath)) { - editableSection = Files.readAllLines(configPath).stream() - .dropWhile(line -> !line.trim().equalsIgnoreCase("# ONLY EDIT BELOW THIS LINE")) - .skip(1) - .collect(Collectors.joining("\n")); - } + Map general = new LinkedHashMap<>(); + general.put("debug-messages-enabled", debugEnabled); + general.put("version-check-enabled", versionCheckEnabled); + general.put("prefix", prefix); + + Map database = new LinkedHashMap<>(); + database.put("type", dbType); + database.put("host", dbHost); + database.put("port", dbPort); + database.put("name", dbName); + database.put("user", dbUser); + database.put("password", dbPassword); + + Map root = new LinkedHashMap<>(); + root.put("general", general); + root.put("database", database); try (BufferedWriter writer = Files.newBufferedWriter(configPath)) { writer.write(VERSION_LINE + "\n\n"); - writer.write("# ONLY EDIT BELOW THIS LINE\n"); - - if (!editableSection.isEmpty()) { - writer.write(editableSection + "\n"); - } else { - writer.write("debug-messages-enabled: false # Enables/disables debug messages (Default: false)\n"); - writer.write("version-check-enabled: true # Toggles version update messages for admins (Default: true)\n"); - writer.write("prefix: '&9&l[&3&lServer&9&l]&r ' # The prefix for broadcasts and messages\n"); - } + yaml.dump(root, writer); } + } catch (IOException e) { logger.error("Failed to save VelocityBroadcast config!", e); } @@ -127,4 +145,28 @@ public class ConfigHandler { this.prefix = newPrefix; save(); } + + public String getDbType() { + return dbType; + } + + public String getDbHost() { + return dbHost; + } + + public int getDbPort() { + return dbPort; + } + + public String getDbName() { + return dbName; + } + + public String getDbUser() { + return dbUser; + } + + public String getDbPassword() { + return dbPassword; + } } diff --git a/src/main/java/com/adzel/velocitybroadcast/LoginListener.java b/src/main/java/com/adzel/velocitybroadcast/LoginListener.java new file mode 100644 index 0000000..eb61998 --- /dev/null +++ b/src/main/java/com/adzel/velocitybroadcast/LoginListener.java @@ -0,0 +1,50 @@ +package com.adzel.velocitybroadcast; + +import com.adzel.velocitybroadcast.util.DatabaseManager; +import com.adzel.velocitybroadcast.util.UpdateChecker; +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.connection.PostLoginEvent; +import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.proxy.ProxyServer; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; + +public class LoginListener { + private final ProxyServer server; + private final String currentVersion; + private final UpdateChecker updateChecker; + private final DatabaseManager databaseManager; + + private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage(); + + public LoginListener(ProxyServer server, String currentVersion, UpdateChecker updateChecker, DatabaseManager databaseManager) { + this.server = server; + this.currentVersion = currentVersion; + this.updateChecker = updateChecker; + this.databaseManager = databaseManager; + } + + @Subscribe + public void onPlayerJoin(PostLoginEvent event) { + Player player = event.getPlayer(); + if (player.hasPermission("vb.admin")) { + // ✅ Log admin join to DB + String serverName = server.getBoundAddress().toString(); // Optional + databaseManager.logAdminJoin(player.getUsername(), serverName); + + // ✅ Notify if update is available + updateChecker.checkForUpdate().thenAccept(latest -> { + if (latest != null && !latest.equalsIgnoreCase(currentVersion)) { + Component message = MINI_MESSAGE.deserialize( + "[VelocityBroadcast] " + + "A new version is available: " + + "" + latest + " " + + "(You are on " + currentVersion + ")" + ); + player.sendMessage(message); + } + }); + } + } +} diff --git a/src/main/java/com/adzel/velocitybroadcast/UpdateChecker.java b/src/main/java/com/adzel/velocitybroadcast/UpdateChecker.java new file mode 100644 index 0000000..d9b8892 --- /dev/null +++ b/src/main/java/com/adzel/velocitybroadcast/UpdateChecker.java @@ -0,0 +1,63 @@ +package com.adzel.velocitybroadcast.util; + +import com.velocitypowered.api.proxy.ProxyServer; +import net.kyori.adventure.text.Component; +import com.velocitypowered.api.proxy.Player; + +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.concurrent.CompletableFuture; +import java.util.logging.Logger; +import org.json.JSONObject; +import org.json.JSONTokener; + +public class UpdateChecker { + private static final String ENDPOINT = "https://api.github.com/repos/AdzelFirestar/velocitybroadcast-reborn/releases/latest"; + private final String currentVersion; + private final Logger logger; + + public UpdateChecker(String currentVersion, Logger logger) { + this.currentVersion = currentVersion; + this.logger = logger; + } + + public CompletableFuture checkForUpdate() { + return CompletableFuture.supplyAsync(() -> { + try { + HttpURLConnection connection = (HttpURLConnection) new URL(ENDPOINT).openConnection(); + connection.setRequestProperty("Accept", "application/json"); + connection.setConnectTimeout(3000); + connection.setReadTimeout(3000); + + try (InputStreamReader reader = new InputStreamReader(connection.getInputStream())) { + JSONObject json = new JSONObject(new JSONTokener(reader)); + String latestVersion = json.getString("tag_name").trim(); + + if (!latestVersion.equalsIgnoreCase(currentVersion)) { + logger.info("[VelocityBroadcast] Update available: " + latestVersion + " (you are on " + currentVersion + ")"); + return latestVersion; + } else { + logger.info("[VelocityBroadcast] You are running the latest version (" + currentVersion + ")."); + return null; + } + } + } catch (Exception e) { + logger.warning("[VelocityBroadcast] Failed to check for updates: " + e.getMessage()); + return null; + } + }); + } + + public void notifyPlayerIfOutdated(ProxyServer server, String latestVersion) { + if (latestVersion != null && !latestVersion.equalsIgnoreCase(currentVersion)) { + String message = String.format("[VelocityBroadcast] A new version (%s) is available! You are running %s.", latestVersion, currentVersion); + Component component = Component.text(message); + for (Player player : server.getAllPlayers()) { + if (player.hasPermission("vb.admin")) { + player.sendMessage(component); + } + } + } + } +} diff --git a/src/main/java/com/adzel/velocitybroadcast/VBCommand.java b/src/main/java/com/adzel/velocitybroadcast/VBCommand.java index eaddd1a..617c20b 100644 --- a/src/main/java/com/adzel/velocitybroadcast/VBCommand.java +++ b/src/main/java/com/adzel/velocitybroadcast/VBCommand.java @@ -2,8 +2,10 @@ package com.adzel.velocitybroadcast; import java.util.List; +import com.adzel.velocitybroadcast.util.DatabaseManager; import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.command.SimpleCommand; +import com.velocitypowered.api.proxy.Player; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; @@ -11,10 +13,12 @@ import net.kyori.adventure.text.minimessage.MiniMessage; public class VBCommand implements SimpleCommand { private final VelocityBroadcast plugin; + private final DatabaseManager databaseManager; private final MiniMessage mm = MiniMessage.miniMessage(); public VBCommand(VelocityBroadcast plugin) { this.plugin = plugin; + this.databaseManager = plugin.getDatabaseManager(); } @Override @@ -22,68 +26,91 @@ public class VBCommand implements SimpleCommand { CommandSource source = invocation.source(); List args = List.of(invocation.arguments()); - if (args.isEmpty() || args.get(0).equalsIgnoreCase("help")) { - source.sendMessage(parseFormatted("VelocityBroadcast Commands:")); - source.sendMessage(parseFormatted("/vb - Broadcast a message to all players")); + String fullCommand = "/vb" + (args.isEmpty() ? "" : " " + String.join(" ", args)); + String username = (source instanceof Player) ? ((Player) source).getUsername() : "Console"; - if (source.hasPermission("vb.admin")) { - source.sendMessage(parseFormatted("/vb prefix - Change the broadcast prefix")); - source.sendMessage(parseFormatted("/vb reload - Reload the plugin config")); + boolean success = true; + + try { + if (args.isEmpty() || args.get(0).equalsIgnoreCase("help")) { + source.sendMessage(parseFormatted("VelocityBroadcast Commands:")); + source.sendMessage(parseFormatted("/vb - Broadcast a message to all players")); + + if (source.hasPermission("vb.admin")) { + source.sendMessage(parseFormatted("/vb prefix - Change the broadcast prefix")); + source.sendMessage(parseFormatted("/vb reload - Reload the plugin config")); + } + + success = false; + return; } - return; - } - String sub = args.get(0).toLowerCase(); - List subArgs = args.subList(1, args.size()); + String sub = args.get(0).toLowerCase(); + List subArgs = args.subList(1, args.size()); - switch (sub) { - case "prefix": - if (!source.hasPermission("vb.admin")) { - source.sendMessage(parseFormatted("You don't have permission to change the broadcast prefix.")); - return; + switch (sub) { + case "prefix" -> { + if (!source.hasPermission("vb.admin")) { + source.sendMessage(parseFormatted("You don't have permission to change the broadcast prefix.")); + success = false; + return; + } + + if (subArgs.isEmpty()) { + source.sendMessage(parseFormatted("Usage: /vb prefix ")); + success = false; + return; + } + + String newPrefix = String.join(" ", subArgs); + plugin.getConfigHandler().setPrefix(newPrefix); + source.sendMessage(parseFormatted("Prefix updated to: " + newPrefix + "")); + + if (plugin.getConfigHandler().isDebugEnabled()) { + plugin.getLogger().info("[Prefix] Updated prefix to: " + newPrefix); + } } - if (subArgs.isEmpty()) { - source.sendMessage(parseFormatted("Usage: /vb prefix ")); - return; + case "reload" -> { + if (!source.hasPermission("vb.admin")) { + source.sendMessage(parseFormatted("You don't have permission to reload the config.")); + success = false; + return; + } + + plugin.getConfigHandler().reload(); + source.sendMessage(parseFormatted("VelocityBroadcast config reloaded.")); + + if (plugin.getConfigHandler().isDebugEnabled()) { + plugin.getLogger().info("[Reload] Config reloaded by " + source.toString()); + } } - String newPrefix = String.join(" ", subArgs); - plugin.getConfigHandler().setPrefix(newPrefix); - source.sendMessage(parseFormatted("Prefix updated to: " + newPrefix + "")); - if (plugin.getConfigHandler().isDebugEnabled()) { - plugin.getLogger().info("[Prefix] Updated prefix to: " + newPrefix); - } - break; + default -> { + // Treat as broadcast message + if (!source.hasPermission("vb.broadcast")) { + source.sendMessage(parseFormatted("You don't have permission to broadcast.")); + success = false; + return; + } - case "reload": - if (!source.hasPermission("vb.admin")) { - source.sendMessage(parseFormatted("You don't have permission to reload the config.")); - return; - } + String fullMessage = plugin.getConfigHandler().getPrefix() + String.join(" ", args); + Component broadcast = parseFormatted(fullMessage); - plugin.getConfigHandler().reload(); - source.sendMessage(parseFormatted("VelocityBroadcast config reloaded.")); - if (plugin.getConfigHandler().isDebugEnabled()) { - plugin.getLogger().info("[Reload] Config reloaded by " + source.toString()); - } - break; + plugin.getServer().getAllPlayers().forEach(p -> p.sendMessage(broadcast)); - default: - // Treat as broadcast message - if (!source.hasPermission("vb.broadcast")) { - source.sendMessage(parseFormatted("You don't have permission to broadcast.")); - return; + if (plugin.getConfigHandler().isDebugEnabled()) { + plugin.getLogger().info("[Broadcast] Sent: " + fullMessage); + } } - - String fullMessage = plugin.getConfigHandler().getPrefix() + String.join(" ", args); - Component broadcast = parseFormatted(fullMessage); - plugin.getServer().getAllPlayers().forEach(p -> p.sendMessage(broadcast)); - - if (plugin.getConfigHandler().isDebugEnabled()) { - plugin.getLogger().info("[Broadcast] Sent: " + fullMessage); - } - break; + } + } catch (Exception e) { + plugin.getLogger().error("Error executing /vb command", e); + source.sendMessage(parseFormatted("An error occurred while executing the command.")); + success = false; + } finally { + // ✅ Log the command usage + databaseManager.logCommand(username, fullCommand, success); } } diff --git a/src/main/java/com/adzel/velocitybroadcast/VelocityBroadcast.java b/src/main/java/com/adzel/velocitybroadcast/VelocityBroadcast.java index e11f208..857df2f 100644 --- a/src/main/java/com/adzel/velocitybroadcast/VelocityBroadcast.java +++ b/src/main/java/com/adzel/velocitybroadcast/VelocityBroadcast.java @@ -4,6 +4,8 @@ import java.nio.file.Path; import org.slf4j.Logger; +import com.adzel.velocitybroadcast.util.DatabaseManager; +import com.adzel.velocitybroadcast.util.UpdateChecker; import com.google.inject.Inject; import com.velocitypowered.api.event.PostOrder; import com.velocitypowered.api.event.Subscribe; @@ -18,19 +20,21 @@ import net.kyori.adventure.text.minimessage.MiniMessage; @Plugin( id = "velocitybroadcast", name = "VelocityBroadcast", - version = "0.2-pre", + version = "0.3-pre", description = "A proxy-wide broadcast plugin for Velocity.", authors = {"Adzel"} ) public class VelocityBroadcast { - public static final String PLUGIN_VERSION = "0.2-pre"; + public static final String PLUGIN_VERSION = "0.3-pre"; public static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage(); private final ProxyServer server; private final Logger logger; private final Path dataDirectory; + private ConfigHandler config; + private DatabaseManager databaseManager; @Inject public VelocityBroadcast(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) { @@ -49,7 +53,25 @@ public class VelocityBroadcast { logger.info("[VelocityBroadcast] Debug mode is enabled."); } - // Register the root /vb command handler + // Initialize database manager + java.util.logging.Logger jdkLogger = java.util.logging.Logger.getLogger("VelocityBroadcast"); + this.databaseManager = new DatabaseManager(config, jdkLogger, dataDirectory); + databaseManager.initialize(); + + // Check for updates (async) + UpdateChecker updateChecker = new UpdateChecker(PLUGIN_VERSION, jdkLogger); + updateChecker.checkForUpdate().thenAccept(latest -> { + if (latest != null) { + logger.warn("[VelocityBroadcast] A new version is available: " + latest + " (You are on " + PLUGIN_VERSION + ")"); + } else { + logger.info("[VelocityBroadcast] You are running the latest version (" + PLUGIN_VERSION + ")."); + } + }); + + // ✅ Register login listener with DatabaseManager + server.getEventManager().register(this, new LoginListener(server, PLUGIN_VERSION, updateChecker, databaseManager)); + + // Register root command server.getCommandManager().register( server.getCommandManager().metaBuilder("vb").plugin(this).build(), new VBCommand(this) @@ -78,4 +100,8 @@ public class VelocityBroadcast { public ConfigHandler getConfigHandler() { return config; } + + public DatabaseManager getDatabaseManager() { + return databaseManager; + } } diff --git a/src/main/java/com/adzel/velocitybroadcast/util/DatabaseManager.java b/src/main/java/com/adzel/velocitybroadcast/util/DatabaseManager.java new file mode 100644 index 0000000..dc1a5be --- /dev/null +++ b/src/main/java/com/adzel/velocitybroadcast/util/DatabaseManager.java @@ -0,0 +1,127 @@ +package com.adzel.velocitybroadcast.util; + +import java.nio.file.Path; +import java.sql.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.logging.Logger; + +import com.adzel.velocitybroadcast.ConfigHandler; + +public class DatabaseManager { + private final Logger logger; + private final ConfigHandler config; + private final Path dataDirectory; + private Connection connection; + private final ExecutorService executor = Executors.newSingleThreadExecutor(); + + public DatabaseManager(ConfigHandler config, Logger logger, Path dataDirectory) { + this.config = config; + this.logger = logger; + this.dataDirectory = dataDirectory; + } + + public void initialize() { + try { + if (config.getDbType().equalsIgnoreCase("mysql")) { + Class.forName("com.mysql.cj.jdbc.Driver"); + connection = DriverManager.getConnection( + "jdbc:mysql://" + config.getDbHost() + ":" + config.getDbPort() + "/" + config.getDbName() + "?useSSL=false&autoReconnect=true", + config.getDbUser(), + config.getDbPassword() + ); + } else { + Class.forName("org.sqlite.JDBC"); + Path dbFile = dataDirectory.resolve(config.getDbName() + ".db"); + connection = DriverManager.getConnection("jdbc:sqlite:" + dbFile.toAbsolutePath()); + } + + logger.info("[VelocityBroadcast] Connected to " + config.getDbType().toUpperCase() + " database."); + initializeTables(); + + } catch (Exception e) { + logger.warning("[VelocityBroadcast] Failed to connect to database: " + e.getMessage()); + } + } + + private void initializeTables() { + boolean isMySQL = config.getDbType().equalsIgnoreCase("mysql"); + String idSyntax = isMySQL ? "INT AUTO_INCREMENT PRIMARY KEY" : "INTEGER PRIMARY KEY AUTOINCREMENT"; + + String broadcastTable = "CREATE TABLE IF NOT EXISTS vb_broadcast_logs (" + + "id " + idSyntax + "," + + "timestamp DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP," + + "sender VARCHAR(64) NOT NULL," + + "message TEXT NOT NULL," + + "source_server VARCHAR(64)" + + ");"; + + String commandTable = "CREATE TABLE IF NOT EXISTS vb_command_logs (" + + "id " + idSyntax + "," + + "timestamp DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP," + + "user VARCHAR(64) NOT NULL," + + "command TEXT NOT NULL," + + "success BOOLEAN" + + ");"; + + String joinTable = "CREATE TABLE IF NOT EXISTS vb_admin_joins (" + + "id " + idSyntax + "," + + "timestamp DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP," + + "username VARCHAR(64) NOT NULL," + + "server VARCHAR(64)" + + ");"; + + executeUpdate(broadcastTable); + executeUpdate(commandTable); + executeUpdate(joinTable); + } + + public void logBroadcast(String sender, String message, String sourceServer) { + String sql = "INSERT INTO vb_broadcast_logs (sender, message, source_server) VALUES (?, ?, ?)"; + executeAsync(sql, sender, message, sourceServer); + } + + public void logCommand(String user, String command, boolean success) { + String sql = "INSERT INTO vb_command_logs (user, command, success) VALUES (?, ?, ?)"; + executeAsync(sql, user, command, success); + } + + public void logAdminJoin(String username, String serverName) { + String sql = "INSERT INTO vb_admin_joins (username, server) VALUES (?, ?)"; + executeAsync(sql, username, serverName); + } + + private void executeAsync(String sql, Object... params) { + executor.submit(() -> { + try (PreparedStatement stmt = connection.prepareStatement(sql)) { + for (int i = 0; i < params.length; i++) { + stmt.setObject(i + 1, params[i]); + } + stmt.executeUpdate(); + } catch (SQLException e) { + logger.warning("[VelocityBroadcast] Database query failed: " + e.getMessage()); + } + }); + } + + private void executeUpdate(String sql) { + executor.submit(() -> { + try (Statement stmt = connection.createStatement()) { + stmt.executeUpdate(sql); + } catch (SQLException e) { + logger.warning("[VelocityBroadcast] Failed to initialize table: " + e.getMessage()); + } + }); + } + + public void close() { + try { + if (connection != null && !connection.isClosed()) { + connection.close(); + executor.shutdown(); + } + } catch (SQLException e) { + logger.warning("[VelocityBroadcast] Failed to close database: " + e.getMessage()); + } + } +} diff --git a/src/main/resources/plugin.json b/src/main/resources/plugin.json index d071f91..484681b 100644 --- a/src/main/resources/plugin.json +++ b/src/main/resources/plugin.json @@ -1,7 +1,7 @@ { "id": "velocitybroadcast", "name": "VelocityBroadcast", - "version": "0.2-pre", + "version": "0.3-pre", "authors": ["Adzel"], "main": "com.adzel.velocitybroadcast.VelocityBroadcast", "description": "A proxy-wide broadcast plugin for Velocity.", diff --git a/target/classes/plugin.json b/target/classes/plugin.json index d071f91..484681b 100644 --- a/target/classes/plugin.json +++ b/target/classes/plugin.json @@ -1,7 +1,7 @@ { "id": "velocitybroadcast", "name": "VelocityBroadcast", - "version": "0.2-pre", + "version": "0.3-pre", "authors": ["Adzel"], "main": "com.adzel.velocitybroadcast.VelocityBroadcast", "description": "A proxy-wide broadcast plugin for Velocity.", diff --git a/target/classes/velocity-plugin.json b/target/classes/velocity-plugin.json index 31be600..081c28b 100644 --- a/target/classes/velocity-plugin.json +++ b/target/classes/velocity-plugin.json @@ -1 +1 @@ -{"id":"velocitybroadcast","name":"VelocityBroadcast","version":"0.2-pre","description":"A proxy-wide broadcast plugin for Velocity.","authors":["Adzel"],"dependencies":[],"main":"com.adzel.velocitybroadcast.VelocityBroadcast"} \ No newline at end of file +{"id":"velocitybroadcast","name":"VelocityBroadcast","version":"0.3-pre","description":"A proxy-wide broadcast plugin for Velocity.","authors":["Adzel"],"dependencies":[],"main":"com.adzel.velocitybroadcast.VelocityBroadcast"} \ No newline at end of file diff --git a/target/maven-archiver/pom.properties b/target/maven-archiver/pom.properties index 5b954b7..663f2ed 100644 --- a/target/maven-archiver/pom.properties +++ b/target/maven-archiver/pom.properties @@ -1,3 +1,3 @@ artifactId=velocitybroadcast groupId=com.adzel.velocitybroadcast -version=0.2-pre +version=0.3-pre diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst index fe04c2a..abe6263 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -4,4 +4,7 @@ com\adzel\velocitybroadcast\BroadcastCommand.class com\adzel\velocitybroadcast\ConfigHandler.class com\adzel\velocitybroadcast\ReloadCommand.class velocity-plugin.json +com\adzel\velocitybroadcast\util\DatabaseManager.class com\adzel\velocitybroadcast\PrefixCommand.class +com\adzel\velocitybroadcast\util\UpdateChecker.class +com\adzel\velocitybroadcast\LoginListener.class diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst index f3d21d8..689ac39 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -2,5 +2,8 @@ C:\Users\theon\OneDrive\Desktop\VelocityBroadcast\src\main\java\com\adzel\veloci C:\Users\theon\OneDrive\Desktop\VelocityBroadcast\src\main\java\com\adzel\velocitybroadcast\ReloadCommand.java C:\Users\theon\OneDrive\Desktop\VelocityBroadcast\src\main\java\com\adzel\velocitybroadcast\BroadcastCommand.java C:\Users\theon\OneDrive\Desktop\VelocityBroadcast\src\main\java\com\adzel\velocitybroadcast\ConfigHandler.java +C:\Users\theon\OneDrive\Desktop\VelocityBroadcast\src\main\java\com\adzel\velocitybroadcast\UpdateChecker.java +C:\Users\theon\OneDrive\Desktop\VelocityBroadcast\src\main\java\com\adzel\velocitybroadcast\util\DatabaseManager.java +C:\Users\theon\OneDrive\Desktop\VelocityBroadcast\src\main\java\com\adzel\velocitybroadcast\LoginListener.java C:\Users\theon\OneDrive\Desktop\VelocityBroadcast\src\main\java\com\adzel\velocitybroadcast\VelocityBroadcast.java C:\Users\theon\OneDrive\Desktop\VelocityBroadcast\src\main\java\com\adzel\velocitybroadcast\PrefixCommand.java