commit 3cf919c46074b49d55500d9f8a1598b13842db15 Author: Big Pappa Date: Thu Jun 11 13:58:08 2026 -0500 Initial RS-ServerAdmnin commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0e86c19 --- /dev/null +++ b/.gitignore @@ -0,0 +1,47 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ +.kotlin +.idea/ +*.iml + +out/ + +dependency-reduced-pom.xml + +logs/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..9ed3ddf --- /dev/null +++ b/pom.xml @@ -0,0 +1,94 @@ + + + 4.0.0 + + com.rsscripting + RS-ServerAdmin + RS-ServerAdmin + 1.0.0 + + + 21 + UTF-8 + + + + + + papermc + https://repo.papermc.io/repository/maven-public/ + + + + + + + + io.papermc.paper + paper-api + 1.21.8-R0.1-SNAPSHOT + provided + + + + org.xerial + sqlite-jdbc + 3.50.3.0 + + + + + + + + + + src/main/resources + true + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + + 21 + 21 + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.3 + + + + package + + + shade + + + + false + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/rsscripting/serveradmin/RSServerAdmin.java b/src/main/java/com/rsscripting/serveradmin/RSServerAdmin.java new file mode 100644 index 0000000..4cc3866 --- /dev/null +++ b/src/main/java/com/rsscripting/serveradmin/RSServerAdmin.java @@ -0,0 +1,137 @@ +package com.rsscripting.serveradmin; + +import com.rsscripting.serveradmin.database.DatabaseManager; +import com.rsscripting.serveradmin.database.SettingsDAO; +import com.rsscripting.serveradmin.commands.RSAdminCommand; +import com.rsscripting.serveradmin.keepinventory.KeepInventoryDAO; +import com.rsscripting.serveradmin.listeners.CreeperListener; +import com.rsscripting.serveradmin.security.SecurityManager; +import com.rsscripting.serveradmin.listeners.InventoryListener; +import com.rsscripting.serveradmin.listeners.CreeperEntityDamageListener; +import com.rsscripting.serveradmin.update.GitHubUpdateChecker; + +import com.rsscripting.serveradmin.settings.SettingKey; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.Bukkit; +import org.bukkit.World; + +import java.util.logging.Level; + +public class RSServerAdmin extends JavaPlugin { + + private static RSServerAdmin instance; + private KeepInventoryDAO keepInventoryDAO; + private DatabaseManager databaseManager; + private SettingsDAO settingsDAO; + private SecurityManager securityManager; + + @Override + public void onEnable() { + + instance = this; + + saveDefaultConfig(); + + databaseManager = new DatabaseManager(this); + + try { + + databaseManager.connect(); + + settingsDAO = new SettingsDAO(databaseManager); + + settingsDAO.initializeDefaults(); + + keepInventoryDAO = new KeepInventoryDAO(databaseManager); + + securityManager = new SecurityManager(this); + + boolean keepInventoryDefault = + settingsDAO.getDefault( + SettingKey.KEEP_INVENTORY_NEW_WORLD + ); + + for (World world : Bukkit.getWorlds()) { + + keepInventoryDAO.ensureWorldExists( + world.getName(), + keepInventoryDefault + ); + + } + + if (getCommand("rsadmin") != null) { + + getCommand("rsadmin").setExecutor( + new RSAdminCommand(this) + ); + + } else { + + getLogger().severe( + "Command 'rsadmin' not found in plugin.yml!" + ); + + } + + getServer().getPluginManager().registerEvents( + new InventoryListener(), + this + ); + + getServer().getPluginManager().registerEvents( + new CreeperListener(), + this + ); + + getServer().getPluginManager().registerEvents( + new CreeperEntityDamageListener(), + this + ); + + + } catch (Exception ex) { + + getLogger().log( + Level.SEVERE, + "Failed to initialize database.", + ex + ); + + getServer().getPluginManager().disablePlugin(this); + + return; + } + + new GitHubUpdateChecker( + this + ).checkForUpdates(); + + getLogger().info("RS-ServerAdmin enabled."); + } + + @Override + public void onDisable() { + + if (databaseManager != null) { + databaseManager.disconnect(); + } + + getLogger().info("RS-ServerAdmin disabled."); + } + + public KeepInventoryDAO getKeepInventoryDAO() {return keepInventoryDAO;} + public static RSServerAdmin getInstance() { + return instance; + } + public DatabaseManager getDatabaseManager() { + return databaseManager; + } + public SettingsDAO getSettingsDAO() { + return settingsDAO; + } + public SecurityManager getSecurityManager() { + return securityManager; + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/serveradmin/commands/RSAdminCommand.java b/src/main/java/com/rsscripting/serveradmin/commands/RSAdminCommand.java new file mode 100644 index 0000000..f8ad9e8 --- /dev/null +++ b/src/main/java/com/rsscripting/serveradmin/commands/RSAdminCommand.java @@ -0,0 +1,50 @@ +package com.rsscripting.serveradmin.commands; + +import com.rsscripting.serveradmin.RSServerAdmin; +import com.rsscripting.serveradmin.security.UserRole; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class RSAdminCommand implements CommandExecutor { + + private final RSServerAdmin plugin; + + public RSAdminCommand(RSServerAdmin plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand( + CommandSender sender, + Command command, + String label, + String[] args + ) { + + if (!(sender instanceof Player player)) { + sender.sendMessage("Players only."); + return true; + } + + UserRole role = + plugin.getSecurityManager().getRole( + player.getUniqueId() + ); + + if (role == UserRole.NONE) { + + player.sendMessage("§cYou do not have access."); + + return true; + } + + player.openInventory( + com.rsscripting.serveradmin.gui.MainMenu.create() + ); + + return true; + + } +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/serveradmin/database/DatabaseManager.java b/src/main/java/com/rsscripting/serveradmin/database/DatabaseManager.java new file mode 100644 index 0000000..33aa8f2 --- /dev/null +++ b/src/main/java/com/rsscripting/serveradmin/database/DatabaseManager.java @@ -0,0 +1,97 @@ +package com.rsscripting.serveradmin.database; + +import com.rsscripting.serveradmin.RSServerAdmin; + +import java.io.File; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; + +public class DatabaseManager { + + private final RSServerAdmin plugin; + private Connection connection; + + public DatabaseManager(RSServerAdmin plugin) { + this.plugin = plugin; + } + + public void connect() throws SQLException { + + File dataFolder = plugin.getDataFolder(); + + if (!dataFolder.exists()) { + dataFolder.mkdirs(); + } + + File databaseFile = new File( + dataFolder, + plugin.getConfig().getString( + "database.file", + "serveradmin.db" + ) + ); + + connection = DriverManager.getConnection( + "jdbc:sqlite:" + databaseFile.getAbsolutePath() + ); + + createTables(); + } + + private void createTables() throws SQLException { + + try (Statement statement = connection.createStatement()) { + + statement.execute(""" + CREATE TABLE IF NOT EXISTS settings ( + world_name TEXT NOT NULL, + setting_key TEXT NOT NULL, + value INTEGER NOT NULL, + PRIMARY KEY(world_name, setting_key) + ) + """); + + statement.execute(""" + CREATE TABLE IF NOT EXISTS worlds ( + world_name TEXT PRIMARY KEY + ) + """); + + statement.execute(""" + CREATE TABLE IF NOT EXISTS defaults ( + setting_key TEXT PRIMARY KEY, + value INTEGER NOT NULL + ) + """); + + statement.execute( + """ + CREATE TABLE IF NOT EXISTS keep_inventory + ( + world_name TEXT PRIMARY KEY, + enabled INTEGER NOT NULL + ) + """ + ); + + } + } + + public Connection getConnection() { + return connection; + } + + public void disconnect() { + + if (connection == null) { + return; + } + + try { + connection.close(); + } catch (SQLException ignored) { + } + } +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/serveradmin/database/SettingsDAO.java b/src/main/java/com/rsscripting/serveradmin/database/SettingsDAO.java new file mode 100644 index 0000000..e4e0314 --- /dev/null +++ b/src/main/java/com/rsscripting/serveradmin/database/SettingsDAO.java @@ -0,0 +1,134 @@ +package com.rsscripting.serveradmin.database; + +import com.rsscripting.serveradmin.settings.SettingKey; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class SettingsDAO { + + private final DatabaseManager databaseManager; + + public SettingsDAO(DatabaseManager databaseManager) { + this.databaseManager = databaseManager; + } + + public void initializeDefaults() throws SQLException { + + for (SettingKey key : SettingKey.values()) { + + if (!defaultExists(key)) { + + boolean value = getDefaultValue(key); + + setDefault(key, value); + } + } + } + + private boolean defaultExists(SettingKey key) throws SQLException { + + Connection connection = databaseManager.getConnection(); + + try (PreparedStatement statement = connection.prepareStatement( + "SELECT setting_key FROM defaults WHERE setting_key = ?")) { + + statement.setString(1, key.name()); + + try (ResultSet rs = statement.executeQuery()) { + return rs.next(); + } + } + } + + private boolean getDefaultValue(SettingKey key) { + + return switch (key) { + + case KEEP_INVENTORY -> true; + + case CREEPER_BLOCK_DAMAGE, + CREEPER_ENTITY_DAMAGE -> false; + + case KEEP_INVENTORY_NEW_WORLD -> false; + }; + } + + public void setDefault( + SettingKey key, + boolean value + ) throws SQLException { + + Connection connection = databaseManager.getConnection(); + + try (PreparedStatement statement = connection.prepareStatement( + """ + INSERT OR REPLACE INTO defaults + (setting_key, value) + VALUES (?, ?) + """ + )) { + + statement.setString(1, key.name()); + statement.setInt(2, value ? 1 : 0); + + statement.executeUpdate(); + } + + } + + public boolean getDefault( + SettingKey key + ) throws SQLException { + + Connection connection = + databaseManager.getConnection(); + + try (PreparedStatement statement = + connection.prepareStatement( + """ + SELECT value + FROM defaults + WHERE setting_key = ? + """ + )) { + + statement.setString( + 1, + key.name() + ); + + try (ResultSet rs = + statement.executeQuery()) { + + if (rs.next()) { + + return rs.getInt("value") == 1; + + } + + } + + } + + return false; + + } + + public void toggleDefault( + SettingKey key + ) throws SQLException { + + boolean current = + getDefault(key); + + setDefault( + key, + !current + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/serveradmin/gui/CreeperMenu.java b/src/main/java/com/rsscripting/serveradmin/gui/CreeperMenu.java new file mode 100644 index 0000000..4a4afa6 --- /dev/null +++ b/src/main/java/com/rsscripting/serveradmin/gui/CreeperMenu.java @@ -0,0 +1,171 @@ +package com.rsscripting.serveradmin.gui; + +import com.rsscripting.serveradmin.RSServerAdmin; +import com.rsscripting.serveradmin.settings.SettingKey; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +public class CreeperMenu { + + public static Inventory create() { + + RSMenuHolder holder = + new RSMenuHolder("creeper"); + + Inventory inventory = + Bukkit.createInventory( + holder, + 27, + "Creeper Settings" + ); + + try { + + try { + + boolean disableBlockDamage = + RSServerAdmin.getInstance() + .getSettingsDAO() + .getDefault( + SettingKey.CREEPER_BLOCK_DAMAGE + ); + + ItemStack blockDamage = + new ItemStack(Material.TNT); + + ItemMeta blockMeta = + blockDamage.getItemMeta(); + + if (blockMeta != null) { + + blockMeta.setDisplayName( + "§aBlock Damage" + ); + + blockMeta.setLore( + java.util.List.of( + "§7Disable Creeper damage to blocks", + "", + disableBlockDamage + ? "§aCurrent: Explosion will not damage blocks" + : "§cCurrent: Explosion will damage blocks" + ) + ); + + blockDamage.setItemMeta( + blockMeta + ); + + } + + if (disableBlockDamage) { + + GUIUtils.addGlow( + blockDamage + ); + + } + + inventory.setItem( + 11, + blockDamage + ); + + boolean disableEntityDamage = + RSServerAdmin.getInstance() + .getSettingsDAO() + .getDefault( + SettingKey.CREEPER_ENTITY_DAMAGE + ); + + ItemStack entityDamage = + new ItemStack( + Material.TOTEM_OF_UNDYING + ); + + ItemMeta entityMeta = + entityDamage.getItemMeta(); + + if (entityMeta != null) { + + entityMeta.setDisplayName( + "§aEntity Damage" + ); + + entityMeta.setLore( + java.util.List.of( + "§7Disable Creeper damage to players and mobs", + "", + disableEntityDamage + ? "§aCurrent: Explosion will not damage entities" + : "§cCurrent: Explosion will damage entities" + ) + ); + + entityDamage.setItemMeta( + entityMeta + ); + + } + + if (disableEntityDamage) { + + GUIUtils.addGlow( + entityDamage + ); + + } + + inventory.setItem( + 15, + entityDamage + ); + + } catch (Exception ex) { + + ex.printStackTrace(); + + } + + } catch (Exception ex) { + + ex.printStackTrace(); + + } + + ItemStack back = + new ItemStack(Material.ARROW); + + ItemMeta backMeta = + back.getItemMeta(); + + if (backMeta != null) { + + backMeta.setDisplayName( + "§cBack" + ); + + back.setItemMeta( + backMeta + ); + + } + + inventory.setItem( + 22, + back + ); + + GUIUtils.fillEmptySlots( + inventory + ); + + return inventory; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/serveradmin/gui/GUIUtils.java b/src/main/java/com/rsscripting/serveradmin/gui/GUIUtils.java new file mode 100644 index 0000000..fab1cce --- /dev/null +++ b/src/main/java/com/rsscripting/serveradmin/gui/GUIUtils.java @@ -0,0 +1,66 @@ +package com.rsscripting.serveradmin.gui; + +import org.bukkit.Material; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemFlag; + +public class GUIUtils { + + private GUIUtils() { + } + + public static ItemStack createFiller() { + + ItemStack item = + new ItemStack(Material.LIGHT_BLUE_STAINED_GLASS_PANE); + + ItemMeta meta = item.getItemMeta(); + + if (meta != null) { + meta.setDisplayName(" "); + item.setItemMeta(meta); + } + + return item; + } + + public static void fillEmptySlots(Inventory inventory) { + + ItemStack filler = createFiller(); + + for (int slot = 0; slot < inventory.getSize(); slot++) { + + if (inventory.getItem(slot) == null) { + inventory.setItem(slot, filler); + } + + } + + } + + public static void addGlow(ItemStack item) { + + ItemMeta meta = item.getItemMeta(); + + if (meta == null) { + return; + } + + meta.addEnchant( + Enchantment.UNBREAKING, + 1, + true + ); + + meta.addItemFlags( + ItemFlag.HIDE_ENCHANTS + ); + + item.setItemMeta(meta); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/serveradmin/gui/KeepInventoryMenu.java b/src/main/java/com/rsscripting/serveradmin/gui/KeepInventoryMenu.java new file mode 100644 index 0000000..b8fd309 --- /dev/null +++ b/src/main/java/com/rsscripting/serveradmin/gui/KeepInventoryMenu.java @@ -0,0 +1,227 @@ +package com.rsscripting.serveradmin.gui; + +import com.rsscripting.serveradmin.RSServerAdmin; +import com.rsscripting.serveradmin.keepinventory.KeepInventoryDAO; +import com.rsscripting.serveradmin.gui.RSMenuHolder; +import com.rsscripting.serveradmin.settings.SettingKey; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.sql.SQLException; +import java.util.List; + +public class KeepInventoryMenu { + + private static final int WORLDS_PER_PAGE = 45; + + public static Inventory create( + int page + ) throws SQLException { + + RSMenuHolder holder = + new RSMenuHolder( + "KEEP_INVENTORY" + ); + + holder.setPage( + page + ); + + Inventory inventory = + Bukkit.createInventory( + holder, + 54, + "Keep Inventory" + ); + + GUIUtils.fillEmptySlots( + inventory + ); + + createBackButton( + inventory + ); + + createDefaultButton( + inventory + ); + + populateWorlds( + inventory, + page + ); + + return inventory; + + } + + private static void createBackButton( + Inventory inventory + ) { + + ItemStack item = + new ItemStack( + Material.ARROW + ); + + ItemMeta meta = + item.getItemMeta(); + + if (meta != null) { + + meta.setDisplayName( + "§cBack" + ); + + item.setItemMeta( + meta + ); + + } + + inventory.setItem( + 0, + item + ); + + } + + private static void createDefaultButton( + Inventory inventory + ) throws SQLException { + + boolean enabled = + RSServerAdmin.getInstance() + .getSettingsDAO() + .getDefault( + SettingKey.KEEP_INVENTORY_NEW_WORLD + ); + + ItemStack item = + new ItemStack( + Material.CHEST + ); + + ItemMeta meta = + item.getItemMeta(); + + if (meta != null) { + + meta.setDisplayName( + "§eDefault For New Worlds" + ); + + meta.setLore( + List.of( + "§7Controls newly detected worlds", + "", + enabled + ? "§aCurrent: New worlds keep inventory" + : "§cCurrent: New worlds drop inventory" + ) + ); + + item.setItemMeta( + meta + ); + + } + + if (enabled) { + + GUIUtils.addGlow( + item + ); + + } + + inventory.setItem( + 4, + item + ); + + } + + private static void populateWorlds( + Inventory inventory, + int page + ) throws SQLException { + + KeepInventoryDAO dao = + RSServerAdmin.getInstance() + .getKeepInventoryDAO(); + + List worlds = + dao.getAllWorlds(); + + int start = + page * WORLDS_PER_PAGE; + + int slot = + 9; + + for (int i = start; + i < worlds.size() && slot < 54; + i++) { + + String worldName = + worlds.get(i); + + boolean enabled = + dao.getWorldSetting( + worldName + ); + + ItemStack item = + new ItemStack( + Material.CHEST + ); + + ItemMeta meta = + item.getItemMeta(); + + if (meta != null) { + + meta.setDisplayName( + "§e" + worldName + ); + + meta.setLore( + List.of( + "§7Keep Inventory", + "", + enabled + ? "§aCurrent: Players keep inventory on death" + : "§cCurrent: Players drop inventory on death" + ) + ); + + item.setItemMeta( + meta + ); + + } + + if (enabled) { + + GUIUtils.addGlow( + item + ); + + } + + inventory.setItem( + slot, + item + ); + + slot++; + + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/serveradmin/gui/MainMenu.java b/src/main/java/com/rsscripting/serveradmin/gui/MainMenu.java new file mode 100644 index 0000000..3d54de9 --- /dev/null +++ b/src/main/java/com/rsscripting/serveradmin/gui/MainMenu.java @@ -0,0 +1,57 @@ +package com.rsscripting.serveradmin.gui; + +import com.rsscripting.serveradmin.gui.GUIUtils; +import com.rsscripting.serveradmin.gui.RSMenuHolder; +import com.rsscripting.serveradmin.gui.KeepInventoryMenu; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +public class MainMenu { + + public static Inventory create() { + + RSMenuHolder holder = + new RSMenuHolder("main"); + + Inventory inventory = + Bukkit.createInventory( + holder, + 27, + "Main Menu" + ); + + ItemStack creeper = new ItemStack(Material.CREEPER_HEAD); + + ItemMeta creeperMeta = creeper.getItemMeta(); + + if (creeperMeta != null) { + creeperMeta.setDisplayName("§aCreepers"); + creeper.setItemMeta(creeperMeta); + } + + inventory.setItem(11, creeper); + + ItemStack keepInventory = + new ItemStack(Material.CHEST); + + ItemMeta keepMeta = + keepInventory.getItemMeta(); + + if (keepMeta != null) { + keepMeta.setDisplayName("§aKeep Inventory"); + keepInventory.setItemMeta(keepMeta); + } + + inventory.setItem(15, keepInventory); + + GUIUtils.fillEmptySlots(inventory); + + return inventory; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/serveradmin/gui/RSMenuHolder.java b/src/main/java/com/rsscripting/serveradmin/gui/RSMenuHolder.java new file mode 100644 index 0000000..9ce94d3 --- /dev/null +++ b/src/main/java/com/rsscripting/serveradmin/gui/RSMenuHolder.java @@ -0,0 +1,57 @@ +package com.rsscripting.serveradmin.gui; + +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.jetbrains.annotations.NotNull; + +public class RSMenuHolder + implements InventoryHolder { + + private final String menuId; + + private int page = 1; + + public RSMenuHolder( + String menuId + ) { + + this.menuId = menuId; + + } + + public String getMenuId() { + + return menuId; + + } + + public int getPage() { + + return page; + + } + + public void setPage( + int page + ) { + + if (page < 1) { + + page = 1; + + } + + this.page = page; + + } + + @Override + public @NotNull Inventory getInventory() { + + throw new UnsupportedOperationException( + "RSMenuHolder does not store an inventory." + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/serveradmin/keepinventory/KeepInventoryDAO.java b/src/main/java/com/rsscripting/serveradmin/keepinventory/KeepInventoryDAO.java new file mode 100644 index 0000000..7683c49 --- /dev/null +++ b/src/main/java/com/rsscripting/serveradmin/keepinventory/KeepInventoryDAO.java @@ -0,0 +1,179 @@ +package com.rsscripting.serveradmin.keepinventory; + +import com.rsscripting.serveradmin.database.DatabaseManager; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class KeepInventoryDAO { + + private final DatabaseManager databaseManager; + + public KeepInventoryDAO( + DatabaseManager databaseManager + ) { + + this.databaseManager = databaseManager; + + } + + public boolean getWorldSetting( + String worldName + ) throws SQLException { + + Connection connection = + databaseManager.getConnection(); + + try (PreparedStatement statement = + connection.prepareStatement( + """ + SELECT enabled + FROM keep_inventory + WHERE world_name = ? + """ + )) { + + statement.setString( + 1, + worldName + ); + + try (ResultSet rs = + statement.executeQuery()) { + + if (rs.next()) { + + return rs.getInt( + "enabled" + ) == 1; + + } + + } + + } + + return false; + + } + + public void setWorldSetting( + String worldName, + boolean enabled + ) throws SQLException { + + Connection connection = + databaseManager.getConnection(); + + try (PreparedStatement statement = + connection.prepareStatement( + """ + INSERT OR REPLACE INTO keep_inventory + ( + world_name, + enabled + ) + VALUES + ( + ?, + ? + ) + """ + )) { + + statement.setString( + 1, + worldName + ); + + statement.setInt( + 2, + enabled ? 1 : 0 + ); + + statement.executeUpdate(); + + } + + } + + public void ensureWorldExists( + String worldName, + boolean defaultValue + ) throws SQLException { + + Connection connection = + databaseManager.getConnection(); + + try (PreparedStatement statement = + connection.prepareStatement( + """ + INSERT OR IGNORE INTO keep_inventory + ( + world_name, + enabled + ) + VALUES + ( + ?, + ? + ) + """ + )) { + + statement.setString( + 1, + worldName + ); + + statement.setInt( + 2, + defaultValue ? 1 : 0 + ); + + statement.executeUpdate(); + + } + + } + + public java.util.List getAllWorlds() + throws SQLException { + + java.util.List worlds = + new java.util.ArrayList<>(); + + Connection connection = + databaseManager.getConnection(); + + try (PreparedStatement statement = + connection.prepareStatement( + """ + SELECT world_name + FROM keep_inventory + ORDER BY world_name + """ + ); + + ResultSet rs = + statement.executeQuery()) { + + while (rs.next()) { + + worlds.add( + rs.getString( + "world_name" + ) + ); + + } + + } + + return worlds; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/serveradmin/listeners/CreeperEntityDamageListener.java b/src/main/java/com/rsscripting/serveradmin/listeners/CreeperEntityDamageListener.java new file mode 100644 index 0000000..bb917de --- /dev/null +++ b/src/main/java/com/rsscripting/serveradmin/listeners/CreeperEntityDamageListener.java @@ -0,0 +1,44 @@ +package com.rsscripting.serveradmin.listeners; + +import com.rsscripting.serveradmin.RSServerAdmin; +import com.rsscripting.serveradmin.settings.SettingKey; +import org.bukkit.entity.Creeper; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; + +public class CreeperEntityDamageListener implements Listener { + + @EventHandler + public void onEntityDamage( + EntityDamageByEntityEvent event + ) { + + if (!(event.getDamager() instanceof Creeper)) { + return; + } + + try { + + boolean disableEntityDamage = + RSServerAdmin.getInstance() + .getSettingsDAO() + .getDefault( + SettingKey.CREEPER_ENTITY_DAMAGE + ); + + if (!disableEntityDamage) { + return; + } + + event.setCancelled(true); + + } catch (Exception ex) { + + ex.printStackTrace(); + + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/serveradmin/listeners/CreeperListener.java b/src/main/java/com/rsscripting/serveradmin/listeners/CreeperListener.java new file mode 100644 index 0000000..51dfae1 --- /dev/null +++ b/src/main/java/com/rsscripting/serveradmin/listeners/CreeperListener.java @@ -0,0 +1,45 @@ +package com.rsscripting.serveradmin.listeners; + +import com.rsscripting.serveradmin.RSServerAdmin; +import com.rsscripting.serveradmin.settings.SettingKey; +import org.bukkit.entity.Creeper; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityExplodeEvent; + +public class CreeperListener implements Listener { + + @EventHandler + public void onEntityExplode( + EntityExplodeEvent event + ) { + + if (!(event.getEntity() instanceof Creeper)) { + return; + } + + try { + + boolean disableBlockDamage = + RSServerAdmin.getInstance() + .getSettingsDAO() + .getDefault( + SettingKey.CREEPER_BLOCK_DAMAGE + ); + + if (!disableBlockDamage) { + return; + } + + event.blockList().clear(); + event.setYield(0F); + + } catch (Exception ex) { + + ex.printStackTrace(); + + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/serveradmin/listeners/InventoryListener.java b/src/main/java/com/rsscripting/serveradmin/listeners/InventoryListener.java new file mode 100644 index 0000000..a41dbdf --- /dev/null +++ b/src/main/java/com/rsscripting/serveradmin/listeners/InventoryListener.java @@ -0,0 +1,133 @@ +package com.rsscripting.serveradmin.listeners; + +import com.rsscripting.serveradmin.gui.KeepInventoryMenu; +import com.rsscripting.serveradmin.gui.RSMenuHolder; +import com.rsscripting.serveradmin.gui.CreeperMenu; +import com.rsscripting.serveradmin.RSServerAdmin; +import com.rsscripting.serveradmin.settings.SettingKey; + +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; + +public class InventoryListener implements Listener { + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + + if (!(event.getInventory().getHolder() instanceof RSMenuHolder holder)) { + return; + } + + if (event.getClickedInventory() == null) { + return; + } + + if (event.getClickedInventory() != event.getView().getTopInventory()) { + return; + } + + event.setCancelled(true); + + switch (holder.getMenuId()) { + + case "main" -> { + + if (!(event.getWhoClicked() instanceof Player player)) { + return; + } + + switch (event.getSlot()) { + + case 11 -> player.openInventory( + CreeperMenu.create() + ); + + case 15 -> { + + try { + + player.openInventory( + KeepInventoryMenu.create( + 1 + ) + ); + + } catch (Exception ex) { + + ex.printStackTrace(); + + } + + } + + } + + } + + case "creeper" -> { + + if (!(event.getWhoClicked() instanceof Player player)) { + return; + } + + switch (event.getSlot()) { + + case 11 -> { + + try { + + RSServerAdmin.getInstance() + .getSettingsDAO() + .toggleDefault( + SettingKey.CREEPER_BLOCK_DAMAGE + ); + + } catch (Exception ex) { + + ex.printStackTrace(); + + } + + player.openInventory( + CreeperMenu.create() + ); + + } + + case 15 -> { + + try { + + RSServerAdmin.getInstance() + .getSettingsDAO() + .toggleDefault( + SettingKey.CREEPER_ENTITY_DAMAGE + ); + + } catch (Exception ex) { + + ex.printStackTrace(); + + } + + player.openInventory( + CreeperMenu.create() + ); + + } + + case 22 -> player.openInventory( + com.rsscripting.serveradmin.gui.MainMenu.create() + ); + + } + + } + + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/serveradmin/security/SecurityManager.java b/src/main/java/com/rsscripting/serveradmin/security/SecurityManager.java new file mode 100644 index 0000000..f0b42aa --- /dev/null +++ b/src/main/java/com/rsscripting/serveradmin/security/SecurityManager.java @@ -0,0 +1,51 @@ +package com.rsscripting.serveradmin.security; + +import com.rsscripting.serveradmin.RSServerAdmin; + +import java.util.List; +import java.util.UUID; + +public class SecurityManager { + + private final RSServerAdmin plugin; + + public SecurityManager(RSServerAdmin plugin) { + this.plugin = plugin; + } + + public UserRole getRole(UUID uuid) { + + String uuidString = uuid.toString(); + + List owners = + plugin.getConfig().getStringList("security.owners"); + + if (owners.contains(uuidString)) { + return UserRole.OWNER; + } + + List admins = + plugin.getConfig().getStringList("security.admins"); + + if (admins.contains(uuidString)) { + return UserRole.ADMIN; + } + + return UserRole.NONE; + } + + public boolean canAccess(UUID uuid) { + return getRole(uuid) != UserRole.NONE; + } + + public boolean isOwner(UUID uuid) { + return getRole(uuid) == UserRole.OWNER; + } + + public boolean isAdmin(UUID uuid) { + UserRole role = getRole(uuid); + + return role == UserRole.ADMIN + || role == UserRole.OWNER; + } +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/serveradmin/security/UserRole.java b/src/main/java/com/rsscripting/serveradmin/security/UserRole.java new file mode 100644 index 0000000..88ba434 --- /dev/null +++ b/src/main/java/com/rsscripting/serveradmin/security/UserRole.java @@ -0,0 +1,9 @@ +package com.rsscripting.serveradmin.security; + +public enum UserRole { + + OWNER, + ADMIN, + NONE + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/serveradmin/settings/SettingKey.java b/src/main/java/com/rsscripting/serveradmin/settings/SettingKey.java new file mode 100644 index 0000000..486a617 --- /dev/null +++ b/src/main/java/com/rsscripting/serveradmin/settings/SettingKey.java @@ -0,0 +1,10 @@ +package com.rsscripting.serveradmin.settings; + +public enum SettingKey { + + CREEPER_BLOCK_DAMAGE, + CREEPER_ENTITY_DAMAGE, + KEEP_INVENTORY_NEW_WORLD, + KEEP_INVENTORY + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/serveradmin/update/GitHubUpdateChecker.java b/src/main/java/com/rsscripting/serveradmin/update/GitHubUpdateChecker.java new file mode 100644 index 0000000..4e421a5 --- /dev/null +++ b/src/main/java/com/rsscripting/serveradmin/update/GitHubUpdateChecker.java @@ -0,0 +1,123 @@ +package com.rsscripting.serveradmin.update; + +import org.bukkit.plugin.java.JavaPlugin; + +import javax.xml.parsers.DocumentBuilderFactory; +import java.net.URL; + + + +public class GitHubUpdateChecker { + + private final JavaPlugin plugin; + private final String pomUrl; + + private static final String POM_URL = + "https://raw.githubusercontent.com/RS-Scripting/RS-ServerAdmin/main/pom.xml"; + + public GitHubUpdateChecker( + JavaPlugin plugin + ) { + + this.plugin = plugin; + this.pomUrl = POM_URL; + + } + + public void checkForUpdates() { + + plugin.getServer() + .getScheduler() + .runTaskAsynchronously( + plugin, + () -> { + + try { + + String currentVersion = + plugin.getDescription() + .getVersion(); + + String latestVersion = + getLatestVersion(); + + if (latestVersion == null) { + + plugin.getLogger().warning( + "Unable to determine latest version." + ); + + return; + + } + + if (currentVersion.equals( + latestVersion + )) { + + plugin.getLogger().info( + "Running latest version (" + + currentVersion + + ")." + ); + + } else { + + plugin.getLogger().warning( + "Update available! Current: " + + currentVersion + + " Latest: " + + latestVersion + ); + + } + + } catch (Exception ex) { + + plugin.getLogger().warning( + "Update check failed." + + ); + + } + + } + ); + + } + + private String getLatestVersion() + throws Exception { + + URL url = + new URL( + POM_URL + ); + + var document = + DocumentBuilderFactory + .newInstance() + .newDocumentBuilder() + .parse( + url.openStream() + ); + + var versions = + document.getElementsByTagName( + "version" + ); + + if (versions.getLength() == 0) { + + return null; + + } + + return versions + .item(0) + .getTextContent() + .trim(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/serveradmin/worlds/WorldsDAO.java b/src/main/java/com/rsscripting/serveradmin/worlds/WorldsDAO.java new file mode 100644 index 0000000..3800c78 --- /dev/null +++ b/src/main/java/com/rsscripting/serveradmin/worlds/WorldsDAO.java @@ -0,0 +1,93 @@ +package com.rsscripting.serveradmin.worlds; + +import com.rsscripting.serveradmin.database.DatabaseManager; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +public class WorldsDAO { + + private final DatabaseManager databaseManager; + + public WorldsDAO( + DatabaseManager databaseManager + ) { + + this.databaseManager = databaseManager; + + } + + public void ensureWorldExists( + String worldName + ) throws SQLException { + + Connection connection = + databaseManager.getConnection(); + + try (PreparedStatement statement = + connection.prepareStatement( + """ + INSERT OR IGNORE INTO worlds + ( + world_name + ) + VALUES + ( + ? + ) + """ + )) { + + statement.setString( + 1, + worldName + ); + + statement.executeUpdate(); + + } + + } + + public List getAllWorlds() + throws SQLException { + + List worlds = + new ArrayList<>(); + + Connection connection = + databaseManager.getConnection(); + + try (PreparedStatement statement = + connection.prepareStatement( + """ + SELECT world_name + FROM worlds + ORDER BY world_name + """ + ); + + ResultSet rs = + statement.executeQuery()) { + + while (rs.next()) { + + worlds.add( + rs.getString( + "world_name" + ) + ); + + } + + } + + return worlds; + + } + +} \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..48951ae --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,7 @@ +security: + + owners: + - [Owner UUID] + + admins: [] + diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..3f2eec8 --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,12 @@ +name: RS-ServerAdmin +version: ${project.version} +main: com.rsscripting.serveradmin.RSServerAdmin +api-version: '1.21' + +author: Big Pappa +contributors: + - Atlas + +commands: + rsadmin: + description: Open RS-ServerAdmin \ No newline at end of file