From 68be779b75fba58ef96b68af126dba5b76ce6806 Mon Sep 17 00:00:00 2001 From: ceze88 Date: Wed, 27 Mar 2024 11:24:10 +0100 Subject: [PATCH] Update database stuff --- pom.xml | 2 +- .../UltimateModeration.java | 9 + .../database/DataHelper.java | 206 +++++++++++++++++- .../ultimatemoderation/settings/Settings.java | 10 +- .../ultimatemoderation/tasks/DataTask.java | 31 +++ 5 files changed, 245 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/craftaro/ultimatemoderation/tasks/DataTask.java diff --git a/pom.xml b/pom.xml index 7d9acf7..3d3fad5 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.craftaro UltimateModeration - 3.0.0 + 3.0.1 UltimateModeration Take complete control over your server with punishment templates via a simplified yet powerful moderation system diff --git a/src/main/java/com/craftaro/ultimatemoderation/UltimateModeration.java b/src/main/java/com/craftaro/ultimatemoderation/UltimateModeration.java index 63e65cf..a182a5c 100644 --- a/src/main/java/com/craftaro/ultimatemoderation/UltimateModeration.java +++ b/src/main/java/com/craftaro/ultimatemoderation/UltimateModeration.java @@ -46,6 +46,7 @@ import com.craftaro.ultimatemoderation.punish.template.Template; import com.craftaro.ultimatemoderation.punish.template.TemplateManager; import com.craftaro.ultimatemoderation.settings.Settings; import com.craftaro.ultimatemoderation.staffchat.StaffChatManager; +import com.craftaro.ultimatemoderation.tasks.DataTask; import com.craftaro.ultimatemoderation.tasks.SlowModeTask; import com.craftaro.ultimatemoderation.tickets.Ticket; import com.craftaro.ultimatemoderation.tickets.TicketManager; @@ -65,6 +66,7 @@ public class UltimateModeration extends SongodaPlugin { private StaffChatManager staffChatManager; private ModerationManager moderationManager; private DataHelper dataHelper; + private DataTask dataTask; /** * @deprecated Use {@link JavaPlugin#getPlugin(Class)} instead. @@ -80,6 +82,9 @@ public class UltimateModeration extends SongodaPlugin { @Override public void onPluginDisable() { + if (dataTask != null) { + dataTask.cancel(); + } } @Override @@ -181,6 +186,10 @@ public class UltimateModeration extends SongodaPlugin { } }); }); + if (dataTask != null) { + dataTask.cancel(); + } + dataTask = new DataTask(this.dataHelper); } @Override diff --git a/src/main/java/com/craftaro/ultimatemoderation/database/DataHelper.java b/src/main/java/com/craftaro/ultimatemoderation/database/DataHelper.java index 64a40ab..b1af512 100644 --- a/src/main/java/com/craftaro/ultimatemoderation/database/DataHelper.java +++ b/src/main/java/com/craftaro/ultimatemoderation/database/DataHelper.java @@ -2,15 +2,24 @@ package com.craftaro.ultimatemoderation.database; import com.craftaro.core.database.DataManager; import com.craftaro.core.database.DatabaseConnector; +import com.craftaro.core.utils.TextUtils; +import com.craftaro.core.utils.TimeUtils; +import com.craftaro.ultimatemoderation.UltimateModeration; import com.craftaro.ultimatemoderation.punish.AppliedPunishment; +import com.craftaro.ultimatemoderation.punish.Punishment; import com.craftaro.ultimatemoderation.punish.PunishmentNote; import com.craftaro.ultimatemoderation.punish.PunishmentType; +import com.craftaro.ultimatemoderation.punish.player.PlayerPunishData; +import com.craftaro.ultimatemoderation.punish.player.PunishmentManager; import com.craftaro.ultimatemoderation.punish.template.Template; +import com.craftaro.ultimatemoderation.punish.template.TemplateManager; import com.craftaro.ultimatemoderation.tickets.Ticket; import com.craftaro.ultimatemoderation.tickets.TicketResponse; import com.craftaro.ultimatemoderation.tickets.TicketStatus; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import java.sql.Connection; @@ -18,6 +27,8 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -27,9 +38,14 @@ import java.util.function.Consumer; public class DataHelper { private final DatabaseConnector databaseConnector; private final DataManager dataManager; - private final Plugin plugin; + private final UltimateModeration plugin; - public DataHelper(DataManager dataManager, Plugin plugin) { + //Store highest punishment id for each type, we query for new punishment ids regular to keep data up to date + //Table, id + private final HashMap punishmentIds = new HashMap<>(); + public final List TABLES = Arrays.asList("punishments", "templates", "notes", "tickets"); //TODO: Add ticket_responses? + + public DataHelper(DataManager dataManager, UltimateModeration plugin) { this.dataManager = dataManager; this.databaseConnector = dataManager.getDatabaseConnector(); this.plugin = plugin; @@ -47,6 +63,176 @@ public class DataHelper { return this.dataManager.getTablePrefix(); } + private int getHighestPunishmentId(String table) { + return this.punishmentIds.getOrDefault(table, 0); + } + + private void setHighestPunishmentId(String table, int id) { + this.punishmentIds.put(table, id); + } + + //Method is called async, no need to make it async here + public void updateData() { + //We query all table ids to get the highest id for each punishment type + for (String table : TABLES) { + try (Connection connection = this.databaseConnector.getConnection()) { + Statement statement = connection.createStatement(); + String selectHighestId = "SELECT MAX(id) FROM " + this.getTablePrefix() + table; + ResultSet result = statement.executeQuery(selectHighestId); + if (result.next()) { + int maxId = result.getInt(1); + //Check if the id is higher than the current highest id we cached + if (maxId > this.getHighestPunishmentId(table)) { + int oldId = this.getHighestPunishmentId(table); + this.setHighestPunishmentId(table, maxId); + + //Load all new data + switch (table) { + case "punishments": + PreparedStatement punishmentStatement = connection.prepareStatement("SELECT * FROM " + this.getTablePrefix() + "punishments WHERE id > ?"); + punishmentStatement.setInt(1, oldId); + ResultSet punishmentResult = punishmentStatement.executeQuery(); + while (punishmentResult.next()) { + int id = punishmentResult.getInt("id"); + PunishmentType punishmentType = PunishmentType.valueOf(punishmentResult.getString("type")); + long duration = punishmentResult.getLong("duration"); + String reason = punishmentResult.getString("reason"); + UUID victim = UUID.fromString(punishmentResult.getString("victim")); + UUID punisher = UUID.fromString(punishmentResult.getString("punisher")); + long expiration = punishmentResult.getLong("expiration"); + AppliedPunishment punishment = new AppliedPunishment(punishmentType, duration, reason, victim, punisher, expiration, id); + plugin.getPunishmentManager().getPlayer(punishment.getVictim()).addPunishment(punishment); + + //If punishment is a BAN check if the player is online and kick them + OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(punishment.getVictim()); + switch (punishmentType) { + case BAN: + if (offlinePlayer.isOnline()) { + Bukkit.getScheduler().runTask(plugin, () -> offlinePlayer.getPlayer().kickPlayer(plugin.getLocale() + .getMessage("event.ban.message") + .processPlaceholder("reason", reason == null ? "" : reason) + .processPlaceholder("duration", TimeUtils.makeReadable(duration)).getMessage())); + } + break; + case KICK: + if (offlinePlayer.isOnline()) { + Bukkit.getScheduler().runTask(plugin, () -> offlinePlayer.getPlayer().kickPlayer(plugin.getLocale() + .getMessage("event.kick.message") + .processPlaceholder("reason", reason == null ? "" : reason).getMessage())); + } + break; + case MUTE: + PlayerPunishData playerPunishData = plugin.getPunishmentManager().getPlayer(offlinePlayer); + if (!playerPunishData.getActivePunishments(PunishmentType.MUTE).isEmpty()) { + return; + } + sendMessage(offlinePlayer, punishment); + break; + case WARNING: + sendMessage(offlinePlayer, punishment); + } + } + break; + case "templates": + PreparedStatement templateStatement = connection.prepareStatement("SELECT * FROM " + this.getTablePrefix() + "templates WHERE id > ?"); + templateStatement.setInt(1, oldId); + ResultSet templateResult = templateStatement.executeQuery(); + while (templateResult.next()) { + int id = templateResult.getInt("id"); + PunishmentType punishmentType = PunishmentType.valueOf(templateResult.getString("punishment_type")); + long duration = templateResult.getLong("duration"); + String reason = templateResult.getString("reason"); + String name = templateResult.getString("name"); + UUID creator = UUID.fromString(templateResult.getString("creator")); + Template template = new Template(punishmentType, duration, reason, creator, name, id); + plugin.getTemplateManager().addTemplate(template); + } + break; + case "notes": + PreparedStatement noteStatement = connection.prepareStatement("SELECT * FROM " + this.getTablePrefix() + "notes WHERE id > ?"); + noteStatement.setInt(1, oldId); + ResultSet noteResult = noteStatement.executeQuery(); + while (noteResult.next()) { + int id = noteResult.getInt("id"); + String noteString = noteResult.getString("note"); + UUID author = UUID.fromString(noteResult.getString("author")); + UUID subject = UUID.fromString(noteResult.getString("subject")); + long creation = noteResult.getLong("creation"); + PunishmentNote note = new PunishmentNote(id, noteString, author, subject, creation); + plugin.getPunishmentManager().getPlayer(note.getSubject()).addNotes(note); + } + break; + case "tickets": + PreparedStatement ticketStatement = connection.prepareStatement("SELECT * FROM " + this.getTablePrefix() + "tickets WHERE id > ?"); + ticketStatement.setInt(1, oldId); + ResultSet ticketResult = ticketStatement.executeQuery(); + while (ticketResult.next()) { + int id = ticketResult.getInt("id"); + UUID victim = UUID.fromString(ticketResult.getString("victim")); + String subject = ticketResult.getString("subject"); + String type = ticketResult.getString("type"); + TicketStatus status = TicketStatus.valueOf(ticketResult.getString("status")); + + String world = ticketResult.getString("world"); + double x = ticketResult.getDouble("x"); + double y = ticketResult.getDouble("y"); + double z = ticketResult.getDouble("z"); + float pitch = ticketResult.getFloat("pitch"); + float yaw = ticketResult.getFloat("yaw"); + + Location location = Bukkit.getWorld(world) == null ? null : new Location(Bukkit.getWorld(world), x, y, z, yaw, pitch); + + Ticket ticket = new Ticket(id, victim, subject, type, status, location); + ticket.setId(id); + + //Query ticket responses for the ticket and load them if they exist + PreparedStatement responseStatement = connection.prepareStatement("SELECT * FROM " + this.getTablePrefix() + "ticket_responses WHERE ticket_id = ?"); + responseStatement.setInt(1, id); + ResultSet responseResult = responseStatement.executeQuery(); + while (responseResult.next()) { + UUID author = UUID.fromString(responseResult.getString("author")); + String message = responseResult.getString("message"); + long postedDate = responseResult.getLong("posted_date"); + TicketResponse ticketResponse = new TicketResponse(author, message, postedDate); + ticketResponse.setTicketId(id); + ticket.addResponse(ticketResponse); + } + + plugin.getTicketManager().addTicket(ticket); + } + break; + } + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + + private void sendMessage(OfflinePlayer offlineVictim, Punishment punishment) { + if (!offlineVictim.isOnline()) { + return; + } + Player victim = offlineVictim.getPlayer(); + UltimateModeration plugin = UltimateModeration.getInstance(); + + String punishSuccess = plugin.getLocale() + .getMessage("event." + punishment.getPunishmentType().name().toLowerCase() + ".message").getPrefixedMessage(); + + if (punishment.getReason() != null) { + punishSuccess += plugin.getLocale().getMessage("event.punish.reason") + .processPlaceholder("reason", punishment.getReason()).getMessage(); + } + + if (punishment.getDuration() != -1) { + punishSuccess += plugin.getLocale().getMessage("event.punish.yourduration") + .processPlaceholder("duration", TimeUtils.makeReadable(punishment.getDuration())).getMessage(); + } + + victim.sendMessage(punishSuccess + TextUtils.formatText("&7.")); + } + public void createTemplate(Template template) { this.runAsync(() -> { try (Connection connection = this.databaseConnector.getConnection()) { @@ -100,6 +286,9 @@ public class DataHelper { templates.add(template); } + //Get the highest id for the table and cache it + this.setHighestPunishmentId("templates", templates.stream().mapToInt(Template::getId).max().orElse(0)); + this.sync(() -> callback.accept(templates)); } catch (Exception ex) { ex.printStackTrace(); @@ -179,6 +368,9 @@ public class DataHelper { appliedPunishments.add(new AppliedPunishment(punishmentType, duration, reason, victim, punisher, expiration, id)); } + //Get the highest id for the table and cache it + this.setHighestPunishmentId("punishments", appliedPunishments.stream().mapToInt(AppliedPunishment::getId).max().orElse(0)); + this.sync(() -> callback.accept(appliedPunishments)); } catch (Exception ex) { ex.printStackTrace(); @@ -235,6 +427,9 @@ public class DataHelper { notes.add(new PunishmentNote(id, note, author, subject, creation)); } + //Get the highest id for the table and cache it + this.setHighestPunishmentId("notes", notes.stream().mapToInt(PunishmentNote::getId).max().orElse(0)); + this.sync(() -> callback.accept(notes)); } catch (Exception ex) { ex.printStackTrace(); @@ -345,10 +540,13 @@ public class DataHelper { Location location = Bukkit.getWorld(world) == null ? null : new Location(Bukkit.getWorld(world), x, y, z, yaw, pitch); Ticket ticket = new Ticket(id, victim, subject, type, status, location); - ticket.setId(id) - ; + ticket.setId(id); + tickets.put(id, ticket); } + + //Get the highest id for the table and cache it + this.setHighestPunishmentId("tickets", tickets.keySet().stream().max(Integer::compareTo).orElse(0)); } try (Statement statement = connection.createStatement()) { diff --git a/src/main/java/com/craftaro/ultimatemoderation/settings/Settings.java b/src/main/java/com/craftaro/ultimatemoderation/settings/Settings.java index 32bfa39..e5279ae 100644 --- a/src/main/java/com/craftaro/ultimatemoderation/settings/Settings.java +++ b/src/main/java/com/craftaro/ultimatemoderation/settings/Settings.java @@ -56,14 +56,8 @@ public class Settings { public static final ConfigSetting NOTIFY_BLOCK_LIST = new ConfigSetting(CONFIG, "Main.Notify Blocks List", Arrays.asList("DIAMOND_ORE", "EMERALD_ORE"), "Blocks that will give a notification when mined."); - public static final ConfigSetting MYSQL_ENABLED = new ConfigSetting(CONFIG, "MySQL.Enabled", false, "Set to 'true' to use MySQL instead of SQLite for data storage."); - public static final ConfigSetting MYSQL_HOSTNAME = new ConfigSetting(CONFIG, "MySQL.Hostname", "localhost"); - public static final ConfigSetting MYSQL_PORT = new ConfigSetting(CONFIG, "MySQL.Port", 3306); - public static final ConfigSetting MYSQL_DATABASE = new ConfigSetting(CONFIG, "MySQL.Database", "your-database"); - public static final ConfigSetting MYSQL_USERNAME = new ConfigSetting(CONFIG, "MySQL.Username", "user"); - public static final ConfigSetting MYSQL_PASSWORD = new ConfigSetting(CONFIG, "MySQL.Password", "pass"); - public static final ConfigSetting MYSQL_USE_SSL = new ConfigSetting(CONFIG, "MySQL.Use SSL", false); - public static final ConfigSetting MYSQL_POOL_SIZE = new ConfigSetting(CONFIG, "MySQL.Pool Size", 3, "Determines the number of connections the pool is using. Increase this value if you are getting timeout errors when more players online."); + public static final ConfigSetting DATA_UPDATE_INTERVAL = new ConfigSetting(CONFIG, "Main.Data Update Interval", 20, + "The amount of time in between updating the data from the database in ticks."); public static void setupConfig() { CONFIG.load(); diff --git a/src/main/java/com/craftaro/ultimatemoderation/tasks/DataTask.java b/src/main/java/com/craftaro/ultimatemoderation/tasks/DataTask.java new file mode 100644 index 0000000..c931c03 --- /dev/null +++ b/src/main/java/com/craftaro/ultimatemoderation/tasks/DataTask.java @@ -0,0 +1,31 @@ +package com.craftaro.ultimatemoderation.tasks; + +import com.craftaro.ultimatemoderation.UltimateModeration; +import com.craftaro.ultimatemoderation.database.DataHelper; +import com.craftaro.ultimatemoderation.punish.Punishment; +import com.craftaro.ultimatemoderation.punish.player.PunishmentManager; +import com.craftaro.ultimatemoderation.settings.Settings; +import org.bukkit.Bukkit; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; + +public class DataTask implements Runnable { + + private BukkitTask task; + private final DataHelper dataHelper; + + public DataTask(DataHelper dataHelper) { + this.dataHelper = dataHelper; + this.task = Bukkit.getScheduler().runTaskTimerAsynchronously(UltimateModeration.getPlugin(UltimateModeration.class), this, 0, Settings.DATA_UPDATE_INTERVAL.getInt()); + } + + @Override + public void run() { + //Update punisment data + dataHelper.updateData(); + } + + public void cancel() { + task.cancel(); + } +}