From 531518a69be92f7a3d1bdccf1993ba18b5be8386 Mon Sep 17 00:00:00 2001 From: CreeperSeth Date: Thu, 15 Jun 2017 15:10:46 -0700 Subject: [PATCH 1/2] Implement a CoreProtect bridge --- pom.xml | 8 + .../totalfreedommod/TotalFreedomMod.java | 3 + .../bridge/CoreProtectBridge.java | 241 ++++++++++++++++++ .../totalfreedommod/command/Command_gtfo.java | 3 + .../command/Command_wipecoreprotectdata.java | 31 +++ .../command/Command_wipeflatlands.java | 17 +- .../totalfreedommod/config/ConfigEntry.java | 3 + src/main/resources/config.yml | 8 + 8 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 src/main/java/me/totalfreedom/totalfreedommod/bridge/CoreProtectBridge.java create mode 100644 src/main/java/me/totalfreedom/totalfreedommod/command/Command_wipecoreprotectdata.java diff --git a/pom.xml b/pom.xml index 62df513ff..9e863957e 100644 --- a/pom.xml +++ b/pom.xml @@ -104,6 +104,14 @@ system ${project.basedir}/lib/LibsDisguises-9.0.9.jar + + + net.coreprotect + CoreProtect + 2.14.2 + system + ${project.basedir}/lib/CoreProtect_2.14.2.jar + diff --git a/src/main/java/me/totalfreedom/totalfreedommod/TotalFreedomMod.java b/src/main/java/me/totalfreedom/totalfreedommod/TotalFreedomMod.java index 38bd7f451..5c14144d4 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/TotalFreedomMod.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/TotalFreedomMod.java @@ -15,6 +15,7 @@ import me.totalfreedom.totalfreedommod.blocking.PotionBlocker; import me.totalfreedom.totalfreedommod.blocking.command.CommandBlocker; import me.totalfreedom.totalfreedommod.bridge.BukkitTelnetBridge; +import me.totalfreedom.totalfreedommod.bridge.CoreProtectBridge; import me.totalfreedom.totalfreedommod.bridge.EssentialsBridge; import me.totalfreedom.totalfreedommod.bridge.LibsDisguisesBridge; import me.totalfreedom.totalfreedommod.bridge.WorldEditBridge; @@ -101,6 +102,7 @@ public class TotalFreedomMod extends AeroPlugin // Bridges public ServiceManager bridges; public BukkitTelnetBridge btb; + public CoreProtectBridge cpb; public EssentialsBridge esb; public LibsDisguisesBridge ldb; public WorldEditBridge web; @@ -202,6 +204,7 @@ public void enable() // Start bridges bridges = new ServiceManager<>(plugin); btb = bridges.registerService(BukkitTelnetBridge.class); + cpb = bridges.registerService(CoreProtectBridge.class); esb = bridges.registerService(EssentialsBridge.class); ldb = bridges.registerService(LibsDisguisesBridge.class); web = bridges.registerService(WorldEditBridge.class); diff --git a/src/main/java/me/totalfreedom/totalfreedommod/bridge/CoreProtectBridge.java b/src/main/java/me/totalfreedom/totalfreedommod/bridge/CoreProtectBridge.java new file mode 100644 index 000000000..3e96b89da --- /dev/null +++ b/src/main/java/me/totalfreedom/totalfreedommod/bridge/CoreProtectBridge.java @@ -0,0 +1,241 @@ +package me.totalfreedom.totalfreedommod.bridge; + +import me.totalfreedom.totalfreedommod.FreedomService; +import me.totalfreedom.totalfreedommod.TotalFreedomMod; +import me.totalfreedom.totalfreedommod.util.FLog; +import me.totalfreedom.totalfreedommod.config.ConfigEntry; +import net.coreprotect.CoreProtect; +import net.coreprotect.CoreProtectAPI; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; +import org.bukkit.World; +import org.bukkit.scheduler.BukkitTask; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.plugin.PluginManager; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.ResultSet; +import java.io.File; +import java.util.List; +import java.util.Arrays; +import me.totalfreedom.totalfreedommod.util.FUtil; + +public class CoreProtectBridge extends FreedomService +{ + private CoreProtectAPI coreProtectAPI = null; + + private final List tables = Arrays.asList("co_sign", "co_session", "co_container", "co_block"); + + private BukkitTask wiper; + + public CoreProtectBridge(TotalFreedomMod plugin) + { + super(plugin); + } + + @Override + protected void onStart() + { + final long interval = 10 * 20L; + final File databaseFile = getDatabase(); + + if (!ConfigEntry.COREPROTECT_AUTO_WIPING_ENABLED.getBoolean() || getCoreProtect() == null) + { + return; + } + + wiper = new BukkitRunnable() + { + @Override + public void run() + { + final CoreProtect coreProtect = getCoreProtect(); + double bytes = databaseFile.length(); + double kilobytes = (bytes / 1024); + double megabytes = (kilobytes / 1024); + double gigabytes = (megabytes / 1024); + if (gigabytes > ConfigEntry.COREPROTECT_FILE_LIMIT.getInteger()) + { + FLog.info("The CoreProtect log file has grown too big for the server to cope, the data will be wiped!"); + PluginManager pluginManager = server.getPluginManager(); + pluginManager.disablePlugin(coreProtect); + FUtil.deleteFolder(databaseFile); + pluginManager.enablePlugin(coreProtect); + } + } + }.runTaskTimer(plugin, interval, interval); + } + + @Override + protected void onStop() + { + } + + public CoreProtect getCoreProtect() + { + CoreProtect coreProtect = null; + try + { + final Plugin coreProtectPlugin = Bukkit.getServer().getPluginManager().getPlugin("CoreProtect"); + + if (coreProtectPlugin != null && coreProtectPlugin instanceof CoreProtect) + { + coreProtect = (CoreProtect)coreProtectPlugin; + } + } + catch (Exception ex) + { + FLog.severe(ex); + } + return coreProtect; + } + + public CoreProtectAPI getCoreProtectAPI() + { + if (coreProtectAPI == null) + { + try + { + final CoreProtect coreProtect = getCoreProtect(); + + coreProtectAPI = coreProtect.getAPI(); + + // Check if the plugin or api is not enabled, if so, return null + if (!coreProtect.isEnabled() || !coreProtectAPI.isEnabled()) + { + return null; + } + } + catch (Exception ex) + { + FLog.severe(ex); + } + } + + return coreProtectAPI; + } + + public boolean isEnabled() + { + final CoreProtect coreProtect = getCoreProtect(); + + return coreProtect != null && coreProtect.isEnabled(); + } + + // Rollback the specifed player's edits that were in the last 24 hours. + public void rollback(final String name) + { + final CoreProtectAPI coreProtect = getCoreProtectAPI(); + + if (!isEnabled()) + { + return; + } + + new BukkitRunnable() + { + @Override + public void run() + { + coreProtect.performRollback(86400, Arrays.asList(name), null, null, null, null, 0, null); + } + }.runTaskAsynchronously(plugin); + } + + // Reverts a rollback for the specifed player's edits that were in the last 24 hours. + public void undoRollback(final String name) + { + final CoreProtectAPI coreProtect = getCoreProtectAPI(); + + if (!isEnabled()) + { + return; + } + + new BukkitRunnable() + { + @Override + public void run() + { + coreProtect.performRestore(86400, Arrays.asList(name), null, null, null, null, 0, null); + } + }.runTaskAsynchronously(plugin); + } + + public File getDatabase() + { + if (!isEnabled()) + { + return null; + } + + return(new File(getCoreProtect().getDataFolder(), "database.db")); + } + + // Wipes DB for the specified world + public void clearDatabase(World world) + { + clearDatabase(world, false); + } + + // Wipes DB for the specified world + public void clearDatabase(World world, Boolean shutdown) + { + final CoreProtect coreProtect = getCoreProtect(); + + if (coreProtect == null) + { + return; + } + + /* As CoreProtect doesn't have an api method for deleting all of the data for a specific world + we have to do this manually via sql */ + File databaseFile = getDatabase(); + Connection connection = null; + try + { + connection = DriverManager.getConnection("jdbc:sqlite:" + databaseFile); + final Statement statement = connection.createStatement(); + statement.setQueryTimeout(30); + + // Obtain world ID from CoreProtect database + ResultSet resultSet = statement.executeQuery("SELECT id FROM co_world WHERE world = '" + world.getName() + "'"); + String worldID = null; + while (resultSet.next()) + { + worldID = String.valueOf(resultSet.getInt("id")); + } + + // Ensure the world ID is not null + if (worldID == null) + { + FLog.warning("Failed to obtain the world ID for the " + world.getName()); + return; + } + + // Iterate through each table and delete their data if the world ID matches + for (String table : tables) + { + statement.executeUpdate("DELETE FROM " + table + " WHERE wid = " + worldID); + } + + // This shrinks down the file size + statement.executeUpdate("VACUUM"); + + connection.close(); + + } + catch (SQLException e) + { + FLog.warning("Failed to delete the CoreProtect data for the " + world.getName()); + } + + // This exits for flatlands wipes + if (shutdown) + { + server.shutdown(); + } + } +} diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_gtfo.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_gtfo.java index 80a832ddd..a7d12bf78 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_gtfo.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_gtfo.java @@ -54,6 +54,9 @@ public boolean run(CommandSender sender, Player playerSender, Command cmd, Strin // Rollback plugin.rb.rollback(player.getName()); + // Rollback with CoreProtect + plugin.cpb.rollback(player.getName()); + // Deop player.setOp(false); diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_wipecoreprotectdata.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_wipecoreprotectdata.java new file mode 100644 index 000000000..cd4d1ef31 --- /dev/null +++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_wipecoreprotectdata.java @@ -0,0 +1,31 @@ +package me.totalfreedom.totalfreedommod.command; + +import me.totalfreedom.totalfreedommod.rank.Rank; +import me.totalfreedom.totalfreedommod.util.FUtil; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +@CommandPermissions(level = Rank.TELNET_ADMIN, source = SourceType.ONLY_CONSOLE) +@CommandParameters(description = "Wipes the CoreProtect data for the flatlands", usage = "/") +public class Command_wipecoreprotectdata extends FreedomCommand +{ + + @Override + public boolean run(final CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole) + { + FUtil.adminAction(sender.getName(), "Wiping CoreProtect data for the flatlands", true); + + new BukkitRunnable() + { + @Override + public void run() + { + plugin.cpb.clearDatabase(plugin.wm.flatlands.getWorld()); + } + }.runTaskAsynchronously(plugin); + + return true; + } +} diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_wipeflatlands.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_wipeflatlands.java index 532ab1ee7..a54983ff7 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_wipeflatlands.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_wipeflatlands.java @@ -6,6 +6,7 @@ import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; @CommandPermissions(level = Rank.SENIOR_ADMIN, source = SourceType.ONLY_CONSOLE, blockHostConsole = true) @CommandParameters(description = "Wipe the flatlands map. Requires manual restart after command is used.", usage = "/") @@ -24,7 +25,21 @@ public boolean run(final CommandSender sender, Player playerSender, Command cmd, player.kickPlayer("Server is going offline for flatlands wipe, come back in a few minutes."); } - server.shutdown(); + if (!plugin.cpb.isEnabled()) + { + server.shutdown(); + } + else + { + new BukkitRunnable() + { + @Override + public void run() + { + plugin.cpb.clearDatabase(plugin.wm.flatlands.getWorld(), true); + } + }.runTaskAsynchronously(plugin); + } return true; } diff --git a/src/main/java/me/totalfreedom/totalfreedommod/config/ConfigEntry.java b/src/main/java/me/totalfreedom/totalfreedommod/config/ConfigEntry.java index 01fa9ed8a..bd6959b40 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/config/ConfigEntry.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/config/ConfigEntry.java @@ -41,6 +41,9 @@ public enum ConfigEntry ADMINLIST_CLEAN_THESHOLD_HOURS(Integer.class, "adminlist.clean_threshold_hours"), ADMINLIST_CONSOLE_IS_SENIOR(Boolean.class, "adminlist.console_is_senior"), // + COREPROTECT_AUTO_WIPING_ENABLED(Boolean.class, "coreprotect.auto_wipe"), + COREPROTECT_FILE_LIMIT(Integer.class, "coreprotect.file_limit"), + // DISABLE_NIGHT(Boolean.class, "disable.night"), DISABLE_WEATHER(Boolean.class, "disable.weather"), // diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 4de2c205b..2ea5037fc 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -36,6 +36,14 @@ adminlist: # Give the default CONSOLE senior admin privileges. # Handy in development environments. console_is_senior: true + +# CoreProtect configuration +coreprotect: + # Should the datebase be wiped automatically? + auto_wipe: false + + # How big (in gigabytes) should the plugin wipe the database at + file_limit: 10 # ForceIP configuration forceip: From 9403050f981a21327b3216d8fbc944b80c45dd62 Mon Sep 17 00:00:00 2001 From: CreeperSeth Date: Sat, 24 Jun 2017 20:47:02 -0700 Subject: [PATCH 2/2] Give the db file size checker it's own method --- .../bridge/CoreProtectBridge.java | 55 ++++++++++--------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/src/main/java/me/totalfreedom/totalfreedommod/bridge/CoreProtectBridge.java b/src/main/java/me/totalfreedom/totalfreedommod/bridge/CoreProtectBridge.java index 3e96b89da..bc4390e0e 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/bridge/CoreProtectBridge.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/bridge/CoreProtectBridge.java @@ -38,34 +38,10 @@ public CoreProtectBridge(TotalFreedomMod plugin) @Override protected void onStart() { - final long interval = 10 * 20L; - final File databaseFile = getDatabase(); - - if (!ConfigEntry.COREPROTECT_AUTO_WIPING_ENABLED.getBoolean() || getCoreProtect() == null) + if (ConfigEntry.COREPROTECT_AUTO_WIPING_ENABLED.getBoolean() && getCoreProtect() != null) { - return; + createAutomaticWiper(); } - - wiper = new BukkitRunnable() - { - @Override - public void run() - { - final CoreProtect coreProtect = getCoreProtect(); - double bytes = databaseFile.length(); - double kilobytes = (bytes / 1024); - double megabytes = (kilobytes / 1024); - double gigabytes = (megabytes / 1024); - if (gigabytes > ConfigEntry.COREPROTECT_FILE_LIMIT.getInteger()) - { - FLog.info("The CoreProtect log file has grown too big for the server to cope, the data will be wiped!"); - PluginManager pluginManager = server.getPluginManager(); - pluginManager.disablePlugin(coreProtect); - FUtil.deleteFolder(databaseFile); - pluginManager.enablePlugin(coreProtect); - } - } - }.runTaskTimer(plugin, interval, interval); } @Override @@ -174,6 +150,33 @@ public File getDatabase() return(new File(getCoreProtect().getDataFolder(), "database.db")); } + private void createAutomaticWiper() + { + final long interval = 10 * 20L; + final File databaseFile = getDatabase(); + + wiper = new BukkitRunnable() + { + @Override + public void run() + { + final CoreProtect coreProtect = getCoreProtect(); + double bytes = databaseFile.length(); + double kilobytes = (bytes / 1024); + double megabytes = (kilobytes / 1024); + double gigabytes = (megabytes / 1024); + if (gigabytes > ConfigEntry.COREPROTECT_FILE_LIMIT.getInteger()) + { + FLog.info("The CoreProtect log file has grown too big for the server to cope, the data will be wiped!"); + PluginManager pluginManager = server.getPluginManager(); + pluginManager.disablePlugin(coreProtect); + FUtil.deleteFolder(databaseFile); + pluginManager.enablePlugin(coreProtect); + } + } + }.runTaskTimer(plugin, interval, interval); + } + // Wipes DB for the specified world public void clearDatabase(World world) {