From d9d556229a8d58107769f479252e48bc85ade9e7 Mon Sep 17 00:00:00 2001 From: GeminiAntigravityCLI Date: Wed, 19 Aug 2026 21:25:01 +0200 Subject: [PATCH] refactor: reset plugin and integrate WorldGuard/WorldEdit dependencies --- build.gradle.kts | 7 +- docs/mining_model.puml | 150 -------- .../java/fr/luc/gamingcore/GamingCore.java | 55 +-- .../mining/command/MiningCommand.java | 242 ------------- .../mining/database/DatabaseManager.java | 328 ------------------ .../mining/listener/BlockBreakListener.java | 46 --- .../listener/BlockProtectionListener.java | 50 --- .../gamingcore/mining/manager/OreManager.java | 210 ----------- .../mining/manager/RespawnScheduler.java | 83 ----- .../mining/model/BlockLocation.java | 82 ----- .../gamingcore/mining/model/CustomOre.java | 97 ------ .../luc/gamingcore/mining/model/OreDrop.java | 104 ------ .../gamingcore/mining/model/OreRarity.java | 41 --- .../mining/model/PlacedOreBlock.java | 100 ------ src/main/resources/plugin.yml | 20 +- .../luc/gamingcore/mining/OreModelTest.java | 58 ---- 16 files changed, 24 insertions(+), 1649 deletions(-) delete mode 100644 docs/mining_model.puml delete mode 100644 src/main/java/fr/luc/gamingcore/mining/command/MiningCommand.java delete mode 100644 src/main/java/fr/luc/gamingcore/mining/database/DatabaseManager.java delete mode 100644 src/main/java/fr/luc/gamingcore/mining/listener/BlockBreakListener.java delete mode 100644 src/main/java/fr/luc/gamingcore/mining/listener/BlockProtectionListener.java delete mode 100644 src/main/java/fr/luc/gamingcore/mining/manager/OreManager.java delete mode 100644 src/main/java/fr/luc/gamingcore/mining/manager/RespawnScheduler.java delete mode 100644 src/main/java/fr/luc/gamingcore/mining/model/BlockLocation.java delete mode 100644 src/main/java/fr/luc/gamingcore/mining/model/CustomOre.java delete mode 100644 src/main/java/fr/luc/gamingcore/mining/model/OreDrop.java delete mode 100644 src/main/java/fr/luc/gamingcore/mining/model/OreRarity.java delete mode 100644 src/main/java/fr/luc/gamingcore/mining/model/PlacedOreBlock.java delete mode 100644 src/test/java/fr/luc/gamingcore/mining/OreModelTest.java diff --git a/build.gradle.kts b/build.gradle.kts index 80b9f1f..f8ae3b8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,13 +11,18 @@ repositories { maven("https://repo.papermc.io/repository/maven-public/") maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") maven("https://oss.sonatype.org/content/groups/public/") + maven("https://maven.enginehub.org/repo/") maven("https://jitpack.io") } dependencies { - // Paper API (1.20.4 gives access to modern Paper API while remaining cross-compatible) + // Paper API (1.20.4) compileOnly("io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT") + // WorldGuard & WorldEdit APIs + compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.9") + compileOnly("com.sk89q.worldedit:worldedit-bukkit:7.3.0") + // Adventure platform for Bukkit (cross-version RGB, MiniMessage, Titles, ActionBars) implementation("net.kyori:adventure-platform-bukkit:4.3.4") implementation("net.kyori:adventure-text-minimessage:4.17.0") diff --git a/docs/mining_model.puml b/docs/mining_model.puml deleted file mode 100644 index a1c4846..0000000 --- a/docs/mining_model.puml +++ /dev/null @@ -1,150 +0,0 @@ -@startuml mining_model -skinparam roundcorner 8 -skinparam shadowing false -skinparam classAttributeIconSize 0 - -title Système de Minage Personnalisé (GamingCore) - Modèle & Architecture - -package "Database Schema (SQLite / MySQL)" <> { - class "ores" as OresTable << (T,#5DADE2) >> { - + id : VARCHAR(64) [PK] - -- - + block_material : VARCHAR(64) - + hardness : DOUBLE - + rarity : VARCHAR(32) - + stock : INTEGER - + respawnable : BOOLEAN - + respawn_time : INTEGER - + temp_block : VARCHAR(64) - + created_at : TIMESTAMP - } - - class "ore_drops" as OreDropsTable << (T,#5DADE2) >> { - + id : INTEGER [PK AUTO] - -- - + ore_id : VARCHAR(64) [FK] - + item_material : VARCHAR(64) - + default_amount : INTEGER - + default_chance : DOUBLE - + fortunable : BOOLEAN - + fortune_multiplier : DOUBLE - + smeltable : BOOLEAN - + smelted_material : VARCHAR(64) - } - - class "placed_ores" as PlacedOresTable << (T,#5DADE2) >> { - + id : INTEGER [PK AUTO] - -- - + ore_id : VARCHAR(64) [FK] - + world : VARCHAR(64) - + x : INTEGER - + y : INTEGER - + z : INTEGER - + current_stock : INTEGER - + is_depleted : BOOLEAN - + next_respawn_at : BIGINT - } - - OresTable "1" *-- "0..*" OreDropsTable : "drops configurés" - OresTable "1" *-- "0..*" PlacedOresTable : "blocs actifs" -} - -package "fr.luc.gamingcore.mining.model" { - class CustomOre { - - id: String - - blockMaterial: XMaterial - - hardness: double - - rarity: OreRarity - - stock: int - - respawnable: boolean - - respawnTimeSeconds: int - - tempBlockMaterial: XMaterial - - drops: List - + isDepleted(currentStock: int): boolean - } - - class OreDrop { - - id: int - - itemMaterial: XMaterial - - defaultAmount: int - - defaultChance: double - - fortunable: boolean - - fortuneMultiplier: double - - smeltable: boolean - - smeltedMaterial: XMaterial - + calculateDrop(fortuneLevel: int, hasSmeltEnchant: boolean): ItemStack - } - - class PlacedOreBlock { - - id: int - - oreType: CustomOre - - worldName: String - - x: int - - y: int - - z: int - - currentStock: int - - depleted: boolean - - nextRespawnTimestamp: long - + mine(player: Player): List - + triggerRespawn(): void - } - - enum OreRarity { - COMMON - UNCOMMON - RARE - EPIC - LEGENDARY - MYTHIC - } -} - -package "fr.luc.gamingcore.mining.manager" { - class OreManager { - - ores: Map - - placedBlocks: Map - + registerOre(ore: CustomOre): void - + getOre(id: String): CustomOre - + getPlacedBlock(location: Location): PlacedOreBlock - + placeOreBlock(oreId: String, location: Location): PlacedOreBlock - + removeOreBlock(location: Location): void - } - - class RespawnScheduler { - + startTask(): void - + checkRespawnQueue(): void - } - - class DatabaseManager { - - connectionSource: Connection - + initTables(): void - + loadAllOres(): List - + loadPlacedBlocks(): List - + savePlacedBlock(block: PlacedOreBlock): void - + updatePlacedBlockState(block: PlacedOreBlock): void - + deletePlacedBlock(id: int): void - } -} - -package "fr.luc.gamingcore.mining.listener" { - class BlockBreakListener { - + onBlockBreak(event: BlockBreakEvent): void - } - class BlockPlaceListener { - + onBlockPlace(event: BlockPlaceEvent): void - } -} - -CustomOre "1" *-- "0..*" OreDrop -CustomOre "1" -- "0..*" PlacedOreBlock -CustomOre --> OreRarity - -OreManager o-- CustomOre -OreManager o-- PlacedOreBlock -OreManager --> DatabaseManager -OreManager --> RespawnScheduler - -BlockBreakListener --> OreManager -BlockPlaceListener --> OreManager - -@enduml diff --git a/src/main/java/fr/luc/gamingcore/GamingCore.java b/src/main/java/fr/luc/gamingcore/GamingCore.java index d3507f5..965dfc5 100644 --- a/src/main/java/fr/luc/gamingcore/GamingCore.java +++ b/src/main/java/fr/luc/gamingcore/GamingCore.java @@ -1,21 +1,14 @@ package fr.luc.gamingcore; -import fr.luc.gamingcore.mining.command.MiningCommand; -import fr.luc.gamingcore.mining.database.DatabaseManager; -import fr.luc.gamingcore.mining.listener.BlockBreakListener; -import fr.luc.gamingcore.mining.listener.BlockProtectionListener; -import fr.luc.gamingcore.mining.manager.OreManager; +import com.sk89q.worldguard.WorldGuard; +import com.sk89q.worldguard.protection.regions.RegionContainer; import fr.luc.gamingcore.util.TextUtil; -import org.bukkit.command.PluginCommand; -import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; public final class GamingCore extends JavaPlugin { private static GamingCore instance; - - private DatabaseManager databaseManager; - private OreManager oreManager; + private RegionContainer regionContainer; @Override public void onEnable() { @@ -23,38 +16,21 @@ public final class GamingCore extends JavaPlugin { saveDefaultConfig(); // Initialize Text Util prefix from config - TextUtil.setPrefix(getConfig().getString("prefix")); + TextUtil.setPrefix(getConfig().getString("prefix", "[GamingCore] » ")); - // Initialize SQLite Database - this.databaseManager = new DatabaseManager(this); - this.databaseManager.initialize(); - - // Initialize Ore Manager & Load Data - this.oreManager = new OreManager(this, databaseManager); - this.oreManager.loadData(); - - // Register Listeners - PluginManager pm = getServer().getPluginManager(); - pm.registerEvents(new BlockBreakListener(this, oreManager), this); - pm.registerEvents(new BlockProtectionListener(oreManager), this); - - // Register Commands - MiningCommand miningCommand = new MiningCommand(this, oreManager); - PluginCommand gcCmd = getCommand("gamingcore"); - if (gcCmd != null) { - gcCmd.setExecutor(miningCommand); - gcCmd.setTabCompleter(miningCommand); + // Hook into WorldGuard + try { + this.regionContainer = WorldGuard.getInstance().getPlatform().getRegionContainer(); + getLogger().info("Connexion avec WorldGuard 7 etablie avec succes !"); + } catch (Throwable t) { + getLogger().severe("Impossible de se connecter a WorldGuard : " + t.getMessage()); } - getLogger().info("GamingCore (Custom Mining Module) a ete active avec succes !"); + getLogger().info("GamingCore a ete active avec succes !"); } @Override public void onDisable() { - if (oreManager != null) { - oreManager.shutdown(); - } - getLogger().info("GamingCore a ete desactive !"); } @@ -62,12 +38,7 @@ public final class GamingCore extends JavaPlugin { return instance; } - public DatabaseManager getDatabaseManager() { - return databaseManager; - } - - public OreManager getOreManager() { - return oreManager; + public RegionContainer getRegionContainer() { + return regionContainer; } } - diff --git a/src/main/java/fr/luc/gamingcore/mining/command/MiningCommand.java b/src/main/java/fr/luc/gamingcore/mining/command/MiningCommand.java deleted file mode 100644 index a9adb30..0000000 --- a/src/main/java/fr/luc/gamingcore/mining/command/MiningCommand.java +++ /dev/null @@ -1,242 +0,0 @@ -package fr.luc.gamingcore.mining.command; - -import fr.luc.gamingcore.GamingCore; -import fr.luc.gamingcore.mining.manager.OreManager; -import fr.luc.gamingcore.mining.model.CustomOre; -import fr.luc.gamingcore.mining.model.OreDrop; -import fr.luc.gamingcore.mining.model.PlacedOreBlock; -import fr.luc.gamingcore.util.TextUtil; -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; -import org.bukkit.entity.Player; - -import java.util.*; -import java.util.stream.Collectors; - -public class MiningCommand implements CommandExecutor, TabCompleter { - - private final GamingCore plugin; - private final OreManager oreManager; - - public MiningCommand(GamingCore plugin, OreManager oreManager) { - this.plugin = plugin; - this.oreManager = oreManager; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (args.length == 0 || args[0].equalsIgnoreCase("help")) { - sendHelp(sender, label); - return true; - } - - String sub = args[0].toLowerCase(); - - if (sub.equals("reload")) { - if (!sender.hasPermission("gamingcore.admin")) { - TextUtil.sendMessage(sender, "Tu n'as pas la permission d'exécuter cette commande."); - return true; - } - plugin.reloadConfig(); - TextUtil.setPrefix(plugin.getConfig().getString("prefix")); - oreManager.loadData(); - TextUtil.sendMessage(sender, "Configuration et minerais rechargés avec succès !"); - return true; - } - - if (sub.equals("ore")) { - if (args.length < 2) { - sendHelp(sender, label); - return true; - } - - String action = args[1].toLowerCase(); - - switch (action) { - case "list": - handleList(sender); - return true; - - case "set": - case "place": - if (!sender.hasPermission("gamingcore.admin")) { - TextUtil.sendMessage(sender, "Tu n'as pas la permission d'exécuter cette commande."); - return true; - } - if (!(sender instanceof Player)) { - sender.sendMessage("Cette commande doit être exécutée par un joueur."); - return true; - } - if (args.length < 3) { - TextUtil.sendMessage(sender, "Utilisation: /" + label + " ore set "); - return true; - } - handleSetOre((Player) sender, args[2]); - return true; - - case "remove": - case "delete": - if (!sender.hasPermission("gamingcore.admin")) { - TextUtil.sendMessage(sender, "Tu n'as pas la permission d'exécuter cette commande."); - return true; - } - if (!(sender instanceof Player)) { - sender.sendMessage("Cette commande doit être exécutée par un joueur."); - return true; - } - handleRemoveOre((Player) sender); - return true; - - case "info": - if (!(sender instanceof Player)) { - sender.sendMessage("Cette commande doit être exécutée par un joueur."); - return true; - } - handleInfoOre((Player) sender); - return true; - - default: - sendHelp(sender, label); - return true; - } - } - - sendHelp(sender, label); - return true; - } - - private void handleList(CommandSender sender) { - Collection ores = oreManager.getAllOres(); - if (ores.isEmpty()) { - TextUtil.sendMessage(sender, "Aucun minerai personnalisé n'est actuellement configuré."); - return; - } - - TextUtil.sendRawMessage(sender, "═══════════ [ Minerais Personnalisés ] ═══════════"); - for (CustomOre ore : ores) { - TextUtil.sendRawMessage(sender, " " + ore.getId() + " - " + ore.getDisplayName() + - " " + ore.getRarity().getTag() + " (Stock: " + ore.getStock() + ", Respawn: " + ore.getRespawnTimeSeconds() + "s)"); - for (OreDrop drop : ore.getDrops()) { - TextUtil.sendRawMessage(sender, " └─ Drop: " + drop.getItemMaterial().name() + " x" + drop.getDefaultAmount() + - " (" + (int)(drop.getDefaultChance() * 100) + "%)"); - } - } - TextUtil.sendRawMessage(sender, "══════════════════════════════════════════════════"); - } - - private void handleSetOre(Player player, String oreId) { - CustomOre ore = oreManager.getOre(oreId); - if (ore == null) { - TextUtil.sendMessage(player, "Minerai introuvable : " + oreId + ". Tape /gc ore list pour voir la liste."); - return; - } - - Block targetBlock = player.getTargetBlockExact(5); - if (targetBlock == null || targetBlock.isEmpty()) { - TextUtil.sendMessage(player, "Tu dois regarder un bloc valide à moins de 5 blocs de distance."); - return; - } - - Location loc = targetBlock.getLocation(); - PlacedOreBlock placed = oreManager.placeOreBlock(ore.getId(), loc); - if (placed != null) { - TextUtil.sendMessage(player, "Bloc défini avec succès en tant que minerai " + ore.getId() + " (" + ore.getDisplayName() + ") !"); - } else { - TextUtil.sendMessage(player, "Une erreur est survenue lors de la pose du minerai."); - } - } - - private void handleRemoveOre(Player player) { - Block targetBlock = player.getTargetBlockExact(5); - if (targetBlock == null || targetBlock.isEmpty()) { - TextUtil.sendMessage(player, "Tu dois regarder un bloc valide à moins de 5 blocs de distance."); - return; - } - - boolean removed = oreManager.removeOreBlock(targetBlock.getLocation()); - if (removed) { - TextUtil.sendMessage(player, "Minerai personnalisé retiré avec succès de ce bloc."); - } else { - TextUtil.sendMessage(player, "Ce bloc n'est pas un minerai personnalisé actif."); - } - } - - private void handleInfoOre(Player player) { - Block targetBlock = player.getTargetBlockExact(5); - if (targetBlock == null || targetBlock.isEmpty()) { - TextUtil.sendMessage(player, "Tu dois regarder un bloc valide à moins de 5 blocs de distance."); - return; - } - - PlacedOreBlock placed = oreManager.getPlacedBlock(targetBlock.getLocation()); - if (placed == null) { - TextUtil.sendMessage(player, "Ce bloc n'est pas un minerai personnalisé."); - return; - } - - CustomOre ore = placed.getOreType(); - TextUtil.sendRawMessage(player, "═══════════ [ Info Minerai ] ═══════════"); - TextUtil.sendRawMessage(player, " ID : " + placed.getOreId() + ""); - TextUtil.sendRawMessage(player, " Nom : " + ore.getDisplayName() + ""); - TextUtil.sendRawMessage(player, " Rareté : " + ore.getRarity().getTag() + ""); - TextUtil.sendRawMessage(player, " Stock : " + placed.getCurrentStock() + "/" + ore.getStock() + ""); - TextUtil.sendRawMessage(player, " Épuisé : " + (placed.isDepleted() ? "Oui" : "Non") + ""); - if (placed.isDepleted()) { - long remaining = Math.max(0, (placed.getNextRespawnTimestamp() - System.currentTimeMillis()) / 1000); - TextUtil.sendRawMessage(player, " Respawn dans : " + remaining + "s"); - } - TextUtil.sendRawMessage(player, "════════════════════════════════════════"); - } - - private void sendHelp(CommandSender sender, String label) { - TextUtil.sendRawMessage(sender, "═══════════ [ GamingCore Mining ] ═══════════"); - TextUtil.sendRawMessage(sender, " /" + label + " ore list - Liste des minerais disponibles"); - TextUtil.sendRawMessage(sender, " /" + label + " ore info - Voir les infos du bloc ciblé"); - if (sender.hasPermission("gamingcore.admin")) { - TextUtil.sendRawMessage(sender, " /" + label + " ore set - Transformer le bloc ciblé en minerai"); - TextUtil.sendRawMessage(sender, " /" + label + " ore remove - Retirer le minerai ciblé"); - TextUtil.sendRawMessage(sender, " /" + label + " reload - Recharger la configuration et la BDD"); - } - TextUtil.sendRawMessage(sender, "════════════════════════════════════════════"); - } - - @Override - public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { - List completions = new ArrayList<>(); - - if (args.length == 1) { - List subcommands = new ArrayList<>(Arrays.asList("help", "ore")); - if (sender.hasPermission("gamingcore.admin")) { - subcommands.add("reload"); - } - return subcommands.stream() - .filter(s -> s.toLowerCase().startsWith(args[0].toLowerCase())) - .collect(Collectors.toList()); - } - - if (args.length == 2 && args[0].equalsIgnoreCase("ore")) { - List oreSubcommands = new ArrayList<>(Arrays.asList("list", "info")); - if (sender.hasPermission("gamingcore.admin")) { - oreSubcommands.addAll(Arrays.asList("set", "remove")); - } - return oreSubcommands.stream() - .filter(s -> s.toLowerCase().startsWith(args[1].toLowerCase())) - .collect(Collectors.toList()); - } - - if (args.length == 3 && args[0].equalsIgnoreCase("ore") && args[1].equalsIgnoreCase("set")) { - if (sender.hasPermission("gamingcore.admin")) { - return oreManager.getAllOres().stream() - .map(CustomOre::getId) - .filter(id -> id.toLowerCase().startsWith(args[2].toLowerCase())) - .collect(Collectors.toList()); - } - } - - return completions; - } -} diff --git a/src/main/java/fr/luc/gamingcore/mining/database/DatabaseManager.java b/src/main/java/fr/luc/gamingcore/mining/database/DatabaseManager.java deleted file mode 100644 index d744f26..0000000 --- a/src/main/java/fr/luc/gamingcore/mining/database/DatabaseManager.java +++ /dev/null @@ -1,328 +0,0 @@ -package fr.luc.gamingcore.mining.database; - -import com.cryptomorin.xseries.XMaterial; -import fr.luc.gamingcore.GamingCore; -import fr.luc.gamingcore.mining.model.*; -import org.bukkit.Bukkit; - -import java.io.File; -import java.sql.*; -import java.util.*; -import java.util.logging.Level; - -public class DatabaseManager { - - private final GamingCore plugin; - private final File dbFile; - private Connection connection; - - public DatabaseManager(GamingCore plugin) { - this.plugin = plugin; - this.dbFile = new File(plugin.getDataFolder(), "database.db"); - } - - public synchronized void initialize() { - if (!plugin.getDataFolder().exists()) { - plugin.getDataFolder().mkdirs(); - } - - try { - connect(); - createTables(); - seedDefaultOresIfEmpty(); - } catch (SQLException e) { - plugin.getLogger().log(Level.SEVERE, "Impossible d'initialiser la base de donnees SQLite !", e); - } - } - - private synchronized void connect() throws SQLException { - if (connection != null && !connection.isClosed()) { - return; - } - try { - Class.forName("org.sqlite.JDBC"); - } catch (ClassNotFoundException e) { - // Paper runtime includes SQLite JDBC by default - } - String url = "jdbc:sqlite:" + dbFile.getAbsolutePath(); - connection = DriverManager.getConnection(url); - } - - private synchronized Connection getConnection() throws SQLException { - if (connection == null || connection.isClosed()) { - connect(); - } - return connection; - } - - private void createTables() throws SQLException { - try (Statement stmt = getConnection().createStatement()) { - // Ores Table - stmt.executeUpdate("CREATE TABLE IF NOT EXISTS ores (" + - "id VARCHAR(64) PRIMARY KEY, " + - "display_name VARCHAR(64) NOT NULL, " + - "block_material VARCHAR(64) NOT NULL, " + - "hardness DOUBLE NOT NULL DEFAULT 1.0, " + - "rarity VARCHAR(32) NOT NULL DEFAULT 'COMMON', " + - "stock INTEGER NOT NULL DEFAULT 1, " + - "respawnable INTEGER NOT NULL DEFAULT 1, " + - "respawn_time INTEGER NOT NULL DEFAULT 10, " + - "temp_block VARCHAR(64) NOT NULL DEFAULT 'BEDROCK', " + - "created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP" + - ");"); - - // Ore Drops Table - stmt.executeUpdate("CREATE TABLE IF NOT EXISTS ore_drops (" + - "id INTEGER PRIMARY KEY AUTOINCREMENT, " + - "ore_id VARCHAR(64) NOT NULL, " + - "item_material VARCHAR(64) NOT NULL, " + - "default_amount INTEGER NOT NULL DEFAULT 1, " + - "default_chance DOUBLE NOT NULL DEFAULT 1.0, " + - "fortunable INTEGER NOT NULL DEFAULT 1, " + - "fortune_multiplier DOUBLE NOT NULL DEFAULT 1.0, " + - "smeltable INTEGER NOT NULL DEFAULT 0, " + - "smelted_material VARCHAR(64), " + - "FOREIGN KEY (ore_id) REFERENCES ores(id) ON DELETE CASCADE" + - ");"); - - // Placed Ores Table - stmt.executeUpdate("CREATE TABLE IF NOT EXISTS placed_ores (" + - "id INTEGER PRIMARY KEY AUTOINCREMENT, " + - "ore_id VARCHAR(64) NOT NULL, " + - "world VARCHAR(64) NOT NULL, " + - "x INTEGER NOT NULL, " + - "y INTEGER NOT NULL, " + - "z INTEGER NOT NULL, " + - "current_stock INTEGER NOT NULL, " + - "is_depleted INTEGER NOT NULL DEFAULT 0, " + - "next_respawn_at BIGINT NOT NULL DEFAULT 0, " + - "FOREIGN KEY (ore_id) REFERENCES ores(id) ON DELETE CASCADE" + - ");"); - } - } - - private void seedDefaultOresIfEmpty() throws SQLException { - try (Statement stmt = getConnection().createStatement(); - ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM ores")) { - if (rs.next() && rs.getInt(1) == 0) { - plugin.getLogger().info("Insertion des minerais par defaut dans la base SQLite..."); - - // 1. Custom Iron - CustomOre iron = new CustomOre("custom_iron", "Fer Renforcé", XMaterial.IRON_ORE, 3.0, - OreRarity.COMMON, 3, true, 15, XMaterial.BEDROCK, new ArrayList<>()); - iron.addDrop(new OreDrop(0, "custom_iron", XMaterial.RAW_IRON, 1, 1.0, true, 1.0, true, XMaterial.IRON_INGOT)); - saveOre(iron); - - // 2. Custom Gold - CustomOre gold = new CustomOre("custom_gold", "Or Pur", XMaterial.GOLD_ORE, 3.5, - OreRarity.UNCOMMON, 4, true, 20, XMaterial.BEDROCK, new ArrayList<>()); - gold.addDrop(new OreDrop(0, "custom_gold", XMaterial.RAW_GOLD, 1, 1.0, true, 1.0, true, XMaterial.GOLD_INGOT)); - saveOre(gold); - - // 3. Custom Diamond - CustomOre diamond = new CustomOre("custom_diamond", "Diamant Cristallin", XMaterial.DIAMOND_ORE, 5.0, - OreRarity.RARE, 5, true, 45, XMaterial.BEDROCK, new ArrayList<>()); - diamond.addDrop(new OreDrop(0, "custom_diamond", XMaterial.DIAMOND, 1, 1.0, true, 1.2, false, null)); - saveOre(diamond); - - // 4. Custom Ancient Debris / Netherite - CustomOre netherite = new CustomOre("custom_netherite", "Débris Ancien Sacré", XMaterial.ANCIENT_DEBRIS, 8.0, - OreRarity.LEGENDARY, 8, true, 120, XMaterial.BEDROCK, new ArrayList<>()); - netherite.addDrop(new OreDrop(0, "custom_netherite", XMaterial.NETHERITE_SCRAP, 1, 0.9, true, 1.3, false, null)); - saveOre(netherite); - } - } - } - - public synchronized void saveOre(CustomOre ore) throws SQLException { - String sql = "INSERT OR REPLACE INTO ores (id, display_name, block_material, hardness, rarity, stock, respawnable, respawn_time, temp_block) " + - "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; - try (PreparedStatement ps = getConnection().prepareStatement(sql)) { - ps.setString(1, ore.getId()); - ps.setString(2, ore.getDisplayName()); - ps.setString(3, ore.getBlockMaterial().name()); - ps.setDouble(4, ore.getHardness()); - ps.setString(5, ore.getRarity().name()); - ps.setInt(6, ore.getStock()); - ps.setInt(7, ore.isRespawnable() ? 1 : 0); - ps.setInt(8, ore.getRespawnTimeSeconds()); - ps.setString(9, ore.getTempBlockMaterial().name()); - ps.executeUpdate(); - } - - // Drops - for (OreDrop drop : ore.getDrops()) { - saveOreDrop(drop); - } - } - - public synchronized void saveOreDrop(OreDrop drop) throws SQLException { - String sql = "INSERT INTO ore_drops (ore_id, item_material, default_amount, default_chance, fortunable, fortune_multiplier, smeltable, smelted_material) " + - "VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; - try (PreparedStatement ps = getConnection().prepareStatement(sql)) { - ps.setString(1, drop.getOreId()); - ps.setString(2, drop.getItemMaterial().name()); - ps.setInt(3, drop.getDefaultAmount()); - ps.setDouble(4, drop.getDefaultChance()); - ps.setInt(5, drop.isFortunable() ? 1 : 0); - ps.setDouble(6, drop.getFortuneMultiplier()); - ps.setInt(7, drop.isSmeltable() ? 1 : 0); - ps.setString(8, drop.getSmeltedMaterial() != null ? drop.getSmeltedMaterial().name() : null); - ps.executeUpdate(); - } - } - - public synchronized Map loadAllOres() { - Map ores = new HashMap<>(); - String sql = "SELECT * FROM ores"; - - try (Statement stmt = getConnection().createStatement(); - ResultSet rs = stmt.executeQuery(sql)) { - - while (rs.next()) { - String id = rs.getString("id"); - String displayName = rs.getString("display_name"); - XMaterial blockMat = XMaterial.matchXMaterial(rs.getString("block_material")).orElse(XMaterial.STONE); - double hardness = rs.getDouble("hardness"); - OreRarity rarity = OreRarity.fromString(rs.getString("rarity")); - int stock = rs.getInt("stock"); - boolean respawnable = rs.getInt("respawnable") == 1; - int respawnTime = rs.getInt("respawn_time"); - XMaterial tempBlock = XMaterial.matchXMaterial(rs.getString("temp_block")).orElse(XMaterial.BEDROCK); - - CustomOre ore = new CustomOre(id, displayName, blockMat, hardness, rarity, stock, respawnable, respawnTime, tempBlock, new ArrayList<>()); - ores.put(id, ore); - } - } catch (SQLException e) { - plugin.getLogger().log(Level.SEVERE, "Erreur lors du chargement des minerais !", e); - } - - // Load drops for all ores - String dropsSql = "SELECT * FROM ore_drops"; - try (Statement stmt = getConnection().createStatement(); - ResultSet rs = stmt.executeQuery(dropsSql)) { - - while (rs.next()) { - int dropId = rs.getInt("id"); - String oreId = rs.getString("ore_id"); - XMaterial itemMat = XMaterial.matchXMaterial(rs.getString("item_material")).orElse(XMaterial.COBBLESTONE); - int amount = rs.getInt("default_amount"); - double chance = rs.getDouble("default_chance"); - boolean fortunable = rs.getInt("fortunable") == 1; - double fortuneMult = rs.getDouble("fortune_multiplier"); - boolean smeltable = rs.getInt("smeltable") == 1; - String smeltedMatStr = rs.getString("smelted_material"); - XMaterial smeltedMat = smeltedMatStr != null ? XMaterial.matchXMaterial(smeltedMatStr).orElse(null) : null; - - CustomOre ore = ores.get(oreId); - if (ore != null) { - OreDrop drop = new OreDrop(dropId, oreId, itemMat, amount, chance, fortunable, fortuneMult, smeltable, smeltedMat); - ore.addDrop(drop); - } - } - } catch (SQLException e) { - plugin.getLogger().log(Level.SEVERE, "Erreur lors du chargement des drops de minerais !", e); - } - - return ores; - } - - public synchronized Map loadPlacedBlocks(Map ores) { - Map map = new HashMap<>(); - String sql = "SELECT * FROM placed_ores"; - - try (Statement stmt = getConnection().createStatement(); - ResultSet rs = stmt.executeQuery(sql)) { - - while (rs.next()) { - int id = rs.getInt("id"); - String oreId = rs.getString("ore_id"); - String world = rs.getString("world"); - int x = rs.getInt("x"); - int y = rs.getInt("y"); - int z = rs.getInt("z"); - int stock = rs.getInt("current_stock"); - boolean depleted = rs.getInt("is_depleted") == 1; - long nextRespawnAt = rs.getLong("next_respawn_at"); - - CustomOre ore = ores.get(oreId); - if (ore != null) { - BlockLocation loc = new BlockLocation(world, x, y, z); - PlacedOreBlock placed = new PlacedOreBlock(id, oreId, ore, loc, stock, depleted, nextRespawnAt); - map.put(loc, placed); - } - } - } catch (SQLException e) { - plugin.getLogger().log(Level.SEVERE, "Erreur lors du chargement des blocs places !", e); - } - - return map; - } - - public synchronized int insertPlacedBlock(PlacedOreBlock block) { - String sql = "INSERT INTO placed_ores (ore_id, world, x, y, z, current_stock, is_depleted, next_respawn_at) " + - "VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; - try (PreparedStatement ps = getConnection().prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { - ps.setString(1, block.getOreId()); - ps.setString(2, block.getLocation().getWorldName()); - ps.setInt(3, block.getLocation().getX()); - ps.setInt(4, block.getLocation().getY()); - ps.setInt(5, block.getLocation().getZ()); - ps.setInt(6, block.getCurrentStock()); - ps.setInt(7, block.isDepleted() ? 1 : 0); - ps.setLong(8, block.getNextRespawnTimestamp()); - ps.executeUpdate(); - - try (ResultSet rs = ps.getGeneratedKeys()) { - if (rs.next()) { - int generatedId = rs.getInt(1); - block.setId(generatedId); - return generatedId; - } - } - } catch (SQLException e) { - plugin.getLogger().log(Level.SEVERE, "Erreur lors de l'enregistrement d'un minerai pose !", e); - } - return -1; - } - - public void updatePlacedBlockAsync(PlacedOreBlock block) { - Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { - String sql = "UPDATE placed_ores SET current_stock = ?, is_depleted = ?, next_respawn_at = ? WHERE id = ?"; - try (PreparedStatement ps = getConnection().prepareStatement(sql)) { - ps.setInt(1, block.getCurrentStock()); - ps.setInt(2, block.isDepleted() ? 1 : 0); - ps.setLong(3, block.getNextRespawnTimestamp()); - ps.setInt(4, block.getId()); - ps.executeUpdate(); - } catch (SQLException e) { - plugin.getLogger().log(Level.SEVERE, "Erreur lors de la mise a jour de l'etat du minerai pose !", e); - } - }); - } - - public void deletePlacedBlockAsync(BlockLocation loc) { - Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { - String sql = "DELETE FROM placed_ores WHERE world = ? AND x = ? AND y = ? AND z = ?"; - try (PreparedStatement ps = getConnection().prepareStatement(sql)) { - ps.setString(1, loc.getWorldName()); - ps.setInt(2, loc.getX()); - ps.setInt(3, loc.getY()); - ps.setInt(4, loc.getZ()); - ps.executeUpdate(); - } catch (SQLException e) { - plugin.getLogger().log(Level.SEVERE, "Erreur lors de la suppression d'un minerai pose !", e); - } - }); - } - - public synchronized void close() { - try { - if (connection != null && !connection.isClosed()) { - connection.close(); - } - } catch (SQLException e) { - plugin.getLogger().log(Level.WARNING, "Erreur lors de la fermeture de la connexion SQLite", e); - } - } -} diff --git a/src/main/java/fr/luc/gamingcore/mining/listener/BlockBreakListener.java b/src/main/java/fr/luc/gamingcore/mining/listener/BlockBreakListener.java deleted file mode 100644 index 08e282b..0000000 --- a/src/main/java/fr/luc/gamingcore/mining/listener/BlockBreakListener.java +++ /dev/null @@ -1,46 +0,0 @@ -package fr.luc.gamingcore.mining.listener; - -import fr.luc.gamingcore.GamingCore; -import fr.luc.gamingcore.mining.manager.OreManager; -import fr.luc.gamingcore.mining.model.PlacedOreBlock; -import fr.luc.gamingcore.util.TextUtil; -import org.bukkit.GameMode; -import org.bukkit.block.Block; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockBreakEvent; - -public class BlockBreakListener implements Listener { - - private final GamingCore plugin; - private final OreManager oreManager; - - public BlockBreakListener(GamingCore plugin, OreManager oreManager) { - this.plugin = plugin; - this.oreManager = oreManager; - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onBlockBreak(BlockBreakEvent event) { - Block block = event.getBlock(); - PlacedOreBlock placed = oreManager.getPlacedBlock(block.getLocation()); - if (placed == null) { - return; - } - - Player player = event.getPlayer(); - - // If admin in creative mode sneaking breaks the block, remove it permanently - if (player.getGameMode() == GameMode.CREATIVE && player.isSneaking() && player.hasPermission("gamingcore.admin")) { - oreManager.removeOreBlock(block.getLocation()); - TextUtil.sendMessage(player, "Minerai personnalisé retiré avec succès !"); - event.setCancelled(false); - return; - } - - // Delegate to OreManager for custom mining mechanics - oreManager.handleMine(player, event); - } -} diff --git a/src/main/java/fr/luc/gamingcore/mining/listener/BlockProtectionListener.java b/src/main/java/fr/luc/gamingcore/mining/listener/BlockProtectionListener.java deleted file mode 100644 index bb10445..0000000 --- a/src/main/java/fr/luc/gamingcore/mining/listener/BlockProtectionListener.java +++ /dev/null @@ -1,50 +0,0 @@ -package fr.luc.gamingcore.mining.listener; - -import fr.luc.gamingcore.mining.manager.OreManager; -import org.bukkit.block.Block; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockExplodeEvent; -import org.bukkit.event.block.BlockPistonExtendEvent; -import org.bukkit.event.block.BlockPistonRetractEvent; -import org.bukkit.event.entity.EntityExplodeEvent; - -public class BlockProtectionListener implements Listener { - - private final OreManager oreManager; - - public BlockProtectionListener(OreManager oreManager) { - this.oreManager = oreManager; - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onEntityExplode(EntityExplodeEvent event) { - event.blockList().removeIf(block -> oreManager.isPlacedOre(block.getLocation())); - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onBlockExplode(BlockExplodeEvent event) { - event.blockList().removeIf(block -> oreManager.isPlacedOre(block.getLocation())); - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onPistonExtend(BlockPistonExtendEvent event) { - for (Block block : event.getBlocks()) { - if (oreManager.isPlacedOre(block.getLocation())) { - event.setCancelled(true); - return; - } - } - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onPistonRetract(BlockPistonRetractEvent event) { - for (Block block : event.getBlocks()) { - if (oreManager.isPlacedOre(block.getLocation())) { - event.setCancelled(true); - return; - } - } - } -} diff --git a/src/main/java/fr/luc/gamingcore/mining/manager/OreManager.java b/src/main/java/fr/luc/gamingcore/mining/manager/OreManager.java deleted file mode 100644 index 183a9a4..0000000 --- a/src/main/java/fr/luc/gamingcore/mining/manager/OreManager.java +++ /dev/null @@ -1,210 +0,0 @@ -package fr.luc.gamingcore.mining.manager; - -import com.cryptomorin.xseries.XMaterial; -import com.cryptomorin.xseries.XSound; -import fr.luc.gamingcore.GamingCore; -import fr.luc.gamingcore.mining.database.DatabaseManager; -import fr.luc.gamingcore.mining.model.*; -import fr.luc.gamingcore.util.TextUtil; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Particle; -import org.bukkit.block.Block; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.Player; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.inventory.ItemStack; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -public class OreManager { - - private final GamingCore plugin; - private final DatabaseManager databaseManager; - private final RespawnScheduler respawnScheduler; - - private final Map registeredOres = new ConcurrentHashMap<>(); - private final Map placedBlocks = new ConcurrentHashMap<>(); - - public OreManager(GamingCore plugin, DatabaseManager databaseManager) { - this.plugin = plugin; - this.databaseManager = databaseManager; - this.respawnScheduler = new RespawnScheduler(plugin, this); - } - - public void loadData() { - registeredOres.clear(); - placedBlocks.clear(); - - // 1. Load Custom Ores from DB - Map ores = databaseManager.loadAllOres(); - registeredOres.putAll(ores); - plugin.getLogger().info("Charges " + registeredOres.size() + " minerais personnalises."); - - // 2. Load Placed Blocks from DB - Map placed = databaseManager.loadPlacedBlocks(registeredOres); - placedBlocks.putAll(placed); - plugin.getLogger().info("Charges " + placedBlocks.size() + " blocs de minerais actifs."); - - // 3. Start Respawn Scheduler - respawnScheduler.start(); - } - - public void shutdown() { - respawnScheduler.stop(); - databaseManager.close(); - } - - public DatabaseManager getDatabaseManager() { - return databaseManager; - } - - public RespawnScheduler getRespawnScheduler() { - return respawnScheduler; - } - - public CustomOre getOre(String id) { - if (id == null) return null; - return registeredOres.get(id.toLowerCase()); - } - - public Collection getAllOres() { - return Collections.unmodifiableCollection(registeredOres.values()); - } - - public void registerOre(CustomOre ore) { - if (ore != null) { - registeredOres.put(ore.getId().toLowerCase(), ore); - try { - databaseManager.saveOre(ore); - } catch (Exception e) { - plugin.getLogger().warning("Erreur lors de la sauvegarde du minerai : " + ore.getId()); - } - } - } - - public PlacedOreBlock getPlacedBlock(Location loc) { - if (loc == null || loc.getWorld() == null) return null; - return placedBlocks.get(BlockLocation.fromLocation(loc)); - } - - public PlacedOreBlock getPlacedBlock(BlockLocation loc) { - if (loc == null) return null; - return placedBlocks.get(loc); - } - - public Collection getAllPlacedBlocks() { - return Collections.unmodifiableCollection(placedBlocks.values()); - } - - public boolean isPlacedOre(Location loc) { - return getPlacedBlock(loc) != null; - } - - public PlacedOreBlock placeOreBlock(String oreId, Location loc) { - CustomOre ore = getOre(oreId); - if (ore == null || loc == null || loc.getWorld() == null) { - return null; - } - - BlockLocation blockLoc = BlockLocation.fromLocation(loc); - PlacedOreBlock placed = new PlacedOreBlock(-1, ore.getId(), ore, blockLoc, ore.getStock(), false, 0); - - // Update block in world - Block block = loc.getBlock(); - block.setType(ore.parseBlockMaterial()); - - // Save in DB and cache - int generatedId = databaseManager.insertPlacedBlock(placed); - placed.setId(generatedId); - placedBlocks.put(blockLoc, placed); - - return placed; - } - - public boolean removeOreBlock(Location loc) { - if (loc == null || loc.getWorld() == null) return false; - BlockLocation blockLoc = BlockLocation.fromLocation(loc); - PlacedOreBlock removed = placedBlocks.remove(blockLoc); - if (removed != null) { - databaseManager.deletePlacedBlockAsync(blockLoc); - loc.getBlock().setType(Material.AIR); - return true; - } - return false; - } - - /** - * Handles custom mining interaction when a player breaks a placed ore block. - */ - public void handleMine(Player player, BlockBreakEvent event) { - Block block = event.getBlock(); - PlacedOreBlock placed = getPlacedBlock(block.getLocation()); - if (placed == null) { - return; - } - - // Cancel the standard vanilla break event - event.setCancelled(true); - - // If block is already depleted and waiting to respawn, do nothing or notify player - if (placed.isDepleted()) { - long remainingSeconds = Math.max(1, (placed.getNextRespawnTimestamp() - System.currentTimeMillis()) / 1000); - TextUtil.sendActionBar(player, "Ce minerai est épuisé ! Réapparition dans " + remainingSeconds + "s."); - XSound.BLOCK_STONE_HIT.play(player, 0.7f, 0.5f); - return; - } - - CustomOre ore = placed.getOreType(); - if (ore == null) return; - - // Tool & Enchantment checks - ItemStack handItem = player.getInventory().getItemInMainHand(); - int fortuneLevel = 0; - if (handItem.hasItemMeta() && handItem.getItemMeta().hasEnchant(Enchantment.LOOT_BONUS_BLOCKS)) { - fortuneLevel = handItem.getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS); - } - - // Calculate and drop items - Location dropLoc = block.getLocation().clone().add(0.5, 0.5, 0.5); - for (OreDrop drop : ore.getDrops()) { - ItemStack dropItem = drop.calculateDrop(fortuneLevel, false); - if (dropItem != null && dropItem.getType() != Material.AIR) { - block.getWorld().dropItemNaturally(dropLoc, dropItem); - } - } - - // Visual & audio feedback for hit - try { - block.getWorld().spawnParticle(Particle.CRIT, dropLoc, 8, 0.2, 0.2, 0.2, 0.05); - } catch (Throwable ignored) {} - XSound.BLOCK_STONE_BREAK.play(player.getLocation(), 0.8f, 1.2f); - XSound.ENTITY_EXPERIENCE_ORB_PICKUP.play(player.getLocation(), 0.5f, 1.5f); - - // Decrement stock - boolean justDepleted = placed.decrementStock(); - - if (justDepleted) { - // Transform block to tempBlock (e.g. Bedrock) - block.setType(ore.parseTempBlockMaterial()); - - // Visual effects for depletion - try { - block.getWorld().spawnParticle(Particle.SMOKE_LARGE, dropLoc, 10, 0.2, 0.2, 0.2, 0.02); - } catch (Throwable ignored) {} - XSound.BLOCK_ANVIL_LAND.play(player.getLocation(), 0.6f, 0.8f); - - TextUtil.sendActionBar(player, "⛏ " + ore.getDisplayName() + " | Épuisé ! (" + ore.getRespawnTimeSeconds() + "s)"); - } else { - // Stock remaining feedback - int current = placed.getCurrentStock(); - int total = ore.getStock(); - String stockColor = current > (total / 2) ? "" : ""; - TextUtil.sendActionBar(player, "⛏ " + ore.getDisplayName() + " | Stock: " + stockColor + current + "/" + total + ""); - } - - // Update database state asynchronously - databaseManager.updatePlacedBlockAsync(placed); - } -} diff --git a/src/main/java/fr/luc/gamingcore/mining/manager/RespawnScheduler.java b/src/main/java/fr/luc/gamingcore/mining/manager/RespawnScheduler.java deleted file mode 100644 index c3b1dc6..0000000 --- a/src/main/java/fr/luc/gamingcore/mining/manager/RespawnScheduler.java +++ /dev/null @@ -1,83 +0,0 @@ -package fr.luc.gamingcore.mining.manager; - -import com.cryptomorin.xseries.XSound; -import fr.luc.gamingcore.GamingCore; -import fr.luc.gamingcore.mining.model.BlockLocation; -import fr.luc.gamingcore.mining.model.PlacedOreBlock; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Particle; -import org.bukkit.block.Block; -import org.bukkit.scheduler.BukkitRunnable; -import org.bukkit.scheduler.BukkitTask; - -public class RespawnScheduler { - - private final GamingCore plugin; - private final OreManager oreManager; - private BukkitTask task; - - public RespawnScheduler(GamingCore plugin, OreManager oreManager) { - this.plugin = plugin; - this.oreManager = oreManager; - } - - public void start() { - stop(); - // Check every second (20 ticks) - this.task = new BukkitRunnable() { - @Override - public void run() { - checkRespawnQueue(); - } - }.runTaskTimer(plugin, 20L, 20L); - } - - public void stop() { - if (task != null && !task.isCancelled()) { - task.cancel(); - task = null; - } - } - - public void checkRespawnQueue() { - long now = System.currentTimeMillis(); - - for (PlacedOreBlock placed : oreManager.getAllPlacedBlocks()) { - if (!placed.isDepleted() || placed.getNextRespawnTimestamp() <= 0) { - continue; - } - - if (now >= placed.getNextRespawnTimestamp()) { - respawnBlock(placed); - } - } - } - - private void respawnBlock(PlacedOreBlock placed) { - BlockLocation blockLoc = placed.getLocation(); - Location loc = blockLoc.toLocation(); - if (loc == null || loc.getWorld() == null || !loc.getWorld().isChunkLoaded(loc.getBlockX() >> 4, loc.getBlockZ() >> 4)) { - // World not loaded or chunk not loaded: reset state anyway so it appears correct when chunk loads - placed.respawn(); - oreManager.getDatabaseManager().updatePlacedBlockAsync(placed); - return; - } - - Block block = loc.getBlock(); - Material oreMat = placed.getOreType().parseBlockMaterial(); - block.setType(oreMat); - - // Respawn state in memory & database - placed.respawn(); - oreManager.getDatabaseManager().updatePlacedBlockAsync(placed); - - // Visual & audio effects - try { - loc.getWorld().spawnParticle(Particle.VILLAGER_HAPPY, loc.clone().add(0.5, 0.5, 0.5), 15, 0.3, 0.3, 0.3, 0.1); - } catch (Throwable ignored) {} - - XSound.BLOCK_STONE_PLACE.play(loc, 1.0f, 1.2f); - } -} diff --git a/src/main/java/fr/luc/gamingcore/mining/model/BlockLocation.java b/src/main/java/fr/luc/gamingcore/mining/model/BlockLocation.java deleted file mode 100644 index a84acff..0000000 --- a/src/main/java/fr/luc/gamingcore/mining/model/BlockLocation.java +++ /dev/null @@ -1,82 +0,0 @@ -package fr.luc.gamingcore.mining.model; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.block.Block; - -import java.util.Objects; - -public final class BlockLocation { - - private final String worldName; - private final int x; - private final int y; - private final int z; - - public BlockLocation(String worldName, int x, int y, int z) { - this.worldName = worldName != null ? worldName : "world"; - this.x = x; - this.y = y; - this.z = z; - } - - public static BlockLocation fromLocation(Location loc) { - if (loc == null || loc.getWorld() == null) { - throw new IllegalArgumentException("Location and World cannot be null"); - } - return new BlockLocation(loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); - } - - public static BlockLocation fromBlock(Block block) { - if (block == null) { - throw new IllegalArgumentException("Block cannot be null"); - } - return fromLocation(block.getLocation()); - } - - public Location toLocation() { - World world = Bukkit.getWorld(worldName); - if (world == null) return null; - return new Location(world, x, y, z); - } - - public Block getBlock() { - Location loc = toLocation(); - return loc != null ? loc.getBlock() : null; - } - - public String getWorldName() { - return worldName; - } - - public int getX() { - return x; - } - - public int getY() { - return y; - } - - public int getZ() { - return z; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - BlockLocation that = (BlockLocation) o; - return x == that.x && y == that.y && z == that.z && Objects.equals(worldName, that.worldName); - } - - @Override - public int hashCode() { - return Objects.hash(worldName, x, y, z); - } - - @Override - public String toString() { - return worldName + ":" + x + "," + y + "," + z; - } -} diff --git a/src/main/java/fr/luc/gamingcore/mining/model/CustomOre.java b/src/main/java/fr/luc/gamingcore/mining/model/CustomOre.java deleted file mode 100644 index 4705162..0000000 --- a/src/main/java/fr/luc/gamingcore/mining/model/CustomOre.java +++ /dev/null @@ -1,97 +0,0 @@ -package fr.luc.gamingcore.mining.model; - -import com.cryptomorin.xseries.XMaterial; -import org.bukkit.Material; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class CustomOre { - - private final String id; - private final String displayName; - private final XMaterial blockMaterial; - private final double hardness; - private final OreRarity rarity; - private final int stock; - private final boolean respawnable; - private final int respawnTimeSeconds; - private final XMaterial tempBlockMaterial; - private final List drops; - - public CustomOre(String id, String displayName, XMaterial blockMaterial, double hardness, - OreRarity rarity, int stock, boolean respawnable, int respawnTimeSeconds, - XMaterial tempBlockMaterial, List drops) { - this.id = id; - this.displayName = displayName != null ? displayName : id; - this.blockMaterial = blockMaterial != null ? blockMaterial : XMaterial.STONE; - this.hardness = Math.max(0.1, hardness); - this.rarity = rarity != null ? rarity : OreRarity.COMMON; - this.stock = Math.max(1, stock); - this.respawnable = respawnable; - this.respawnTimeSeconds = Math.max(1, respawnTimeSeconds); - this.tempBlockMaterial = tempBlockMaterial != null ? tempBlockMaterial : XMaterial.BEDROCK; - this.drops = drops != null ? new ArrayList<>(drops) : new ArrayList<>(); - } - - public String getId() { - return id; - } - - public String getDisplayName() { - return displayName; - } - - public XMaterial getBlockMaterial() { - return blockMaterial; - } - - public Material parseBlockMaterial() { - Material mat = blockMaterial.parseMaterial(); - return mat != null ? mat : Material.STONE; - } - - public double getHardness() { - return hardness; - } - - public OreRarity getRarity() { - return rarity; - } - - public int getStock() { - return stock; - } - - public boolean isRespawnable() { - return respawnable; - } - - public int getRespawnTimeSeconds() { - return respawnTimeSeconds; - } - - public XMaterial getTempBlockMaterial() { - return tempBlockMaterial; - } - - public Material parseTempBlockMaterial() { - Material mat = tempBlockMaterial.parseMaterial(); - return mat != null ? mat : Material.BEDROCK; - } - - public List getDrops() { - return Collections.unmodifiableList(drops); - } - - public void addDrop(OreDrop drop) { - if (drop != null) { - this.drops.add(drop); - } - } - - public void clearDrops() { - this.drops.clear(); - } -} diff --git a/src/main/java/fr/luc/gamingcore/mining/model/OreDrop.java b/src/main/java/fr/luc/gamingcore/mining/model/OreDrop.java deleted file mode 100644 index b376044..0000000 --- a/src/main/java/fr/luc/gamingcore/mining/model/OreDrop.java +++ /dev/null @@ -1,104 +0,0 @@ -package fr.luc.gamingcore.mining.model; - -import com.cryptomorin.xseries.XMaterial; -import org.bukkit.inventory.ItemStack; - -import java.util.concurrent.ThreadLocalRandom; - -public class OreDrop { - - private final int id; - private final String oreId; - private final XMaterial itemMaterial; - private final int defaultAmount; - private final double defaultChance; - private final boolean fortunable; - private final double fortuneMultiplier; - private final boolean smeltable; - private final XMaterial smeltedMaterial; - - public OreDrop(int id, String oreId, XMaterial itemMaterial, int defaultAmount, double defaultChance, - boolean fortunable, double fortuneMultiplier, boolean smeltable, XMaterial smeltedMaterial) { - this.id = id; - this.oreId = oreId; - this.itemMaterial = itemMaterial != null ? itemMaterial : XMaterial.COBBLESTONE; - this.defaultAmount = Math.max(1, defaultAmount); - this.defaultChance = Math.min(1.0, Math.max(0.0, defaultChance)); - this.fortunable = fortunable; - this.fortuneMultiplier = fortuneMultiplier; - this.smeltable = smeltable; - this.smeltedMaterial = smeltedMaterial; - } - - public int getId() { - return id; - } - - public String getOreId() { - return oreId; - } - - public XMaterial getItemMaterial() { - return itemMaterial; - } - - public int getDefaultAmount() { - return defaultAmount; - } - - public double getDefaultChance() { - return defaultChance; - } - - public boolean isFortunable() { - return fortunable; - } - - public double getFortuneMultiplier() { - return fortuneMultiplier; - } - - public boolean isSmeltable() { - return smeltable; - } - - public XMaterial getSmeltedMaterial() { - return smeltedMaterial; - } - - /** - * Calculates the drop based on chance, fortune level, and auto-smelt status. - * - * @param fortuneLevel Level of Fortune enchantment on tool (0 if none) - * @param autoSmelt Whether auto-smelt is active - * @return ItemStack if drop was successful, or null if chance roll failed - */ - public ItemStack calculateDrop(int fortuneLevel, boolean autoSmelt) { - double roll = ThreadLocalRandom.current().nextDouble(); - if (roll > defaultChance) { - return null; // Failed drop chance roll - } - - int amount = defaultAmount; - if (fortunable && fortuneLevel > 0) { - // Vanilla-like fortune bonus calculation with customizable multiplier - int bonus = ThreadLocalRandom.current().nextInt(fortuneLevel + 2) - 1; - if (bonus > 0) { - amount += (int) Math.round(bonus * Math.max(1.0, fortuneMultiplier)); - } - } - - XMaterial targetMaterial = itemMaterial; - if (smeltable && autoSmelt && smeltedMaterial != null && smeltedMaterial.isSupported()) { - targetMaterial = smeltedMaterial; - } - - ItemStack item = targetMaterial.parseItem(); - if (item == null) { - return null; - } - - item.setAmount(Math.max(1, amount)); - return item; - } -} diff --git a/src/main/java/fr/luc/gamingcore/mining/model/OreRarity.java b/src/main/java/fr/luc/gamingcore/mining/model/OreRarity.java deleted file mode 100644 index a06a2fc..0000000 --- a/src/main/java/fr/luc/gamingcore/mining/model/OreRarity.java +++ /dev/null @@ -1,41 +0,0 @@ -package fr.luc.gamingcore.mining.model; - -public enum OreRarity { - COMMON("Commun", "Commun", "[Commun]"), - UNCOMMON("Peu Commun", "Peu Commun", "[Peu Commun]"), - RARE("Rare", "Rare", "[Rare]"), - EPIC("Épique", "Épique", "[Épique]"), - LEGENDARY("Légendaire", "Légendaire", "[Légendaire]"), - MYTHIC("Mythique", "Mythique", "[Mythique]"); - - private final String displayName; - private final String formattedName; - private final String tag; - - OreRarity(String displayName, String formattedName, String tag) { - this.displayName = displayName; - this.formattedName = formattedName; - this.tag = tag; - } - - public String getDisplayName() { - return displayName; - } - - public String getFormattedName() { - return formattedName; - } - - public String getTag() { - return tag; - } - - public static OreRarity fromString(String name) { - if (name == null) return COMMON; - try { - return OreRarity.valueOf(name.toUpperCase()); - } catch (IllegalArgumentException e) { - return COMMON; - } - } -} diff --git a/src/main/java/fr/luc/gamingcore/mining/model/PlacedOreBlock.java b/src/main/java/fr/luc/gamingcore/mining/model/PlacedOreBlock.java deleted file mode 100644 index b6ca039..0000000 --- a/src/main/java/fr/luc/gamingcore/mining/model/PlacedOreBlock.java +++ /dev/null @@ -1,100 +0,0 @@ -package fr.luc.gamingcore.mining.model; - -public class PlacedOreBlock { - - private int id; - private final String oreId; - private CustomOre oreType; - private final BlockLocation location; - private int currentStock; - private boolean depleted; - private long nextRespawnTimestamp; - - public PlacedOreBlock(int id, String oreId, CustomOre oreType, BlockLocation location, - int currentStock, boolean depleted, long nextRespawnTimestamp) { - this.id = id; - this.oreId = oreId; - this.oreType = oreType; - this.location = location; - this.currentStock = currentStock; - this.depleted = depleted; - this.nextRespawnTimestamp = nextRespawnTimestamp; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getOreId() { - return oreId; - } - - public CustomOre getOreType() { - return oreType; - } - - public void setOreType(CustomOre oreType) { - this.oreType = oreType; - } - - public BlockLocation getLocation() { - return location; - } - - public int getCurrentStock() { - return currentStock; - } - - public void setCurrentStock(int currentStock) { - this.currentStock = currentStock; - } - - public boolean isDepleted() { - return depleted; - } - - public void setDepleted(boolean depleted) { - this.depleted = depleted; - } - - public long getNextRespawnTimestamp() { - return nextRespawnTimestamp; - } - - public void setNextRespawnTimestamp(long nextRespawnTimestamp) { - this.nextRespawnTimestamp = nextRespawnTimestamp; - } - - /** - * Decrements the stock by 1 and checks if it reached 0. - * - * @return true if the ore has just been depleted - */ - public boolean decrementStock() { - this.currentStock--; - if (this.currentStock <= 0) { - this.currentStock = 0; - this.depleted = true; - if (this.oreType != null && this.oreType.isRespawnable()) { - this.nextRespawnTimestamp = System.currentTimeMillis() + (this.oreType.getRespawnTimeSeconds() * 1000L); - } - return true; - } - return false; - } - - /** - * Resets the stock and removes depleted flag on respawn. - */ - public void respawn() { - this.depleted = false; - this.nextRespawnTimestamp = 0L; - if (this.oreType != null) { - this.currentStock = this.oreType.getStock(); - } - } -} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 39bc477..ddb6670 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -3,20 +3,10 @@ version: 1.0.0 main: fr.luc.gamingcore.GamingCore api-version: '1.16' author: Luc -description: GamingCore Plugin - Système de Minage Personnalisé +description: GamingCore Plugin +depend: + - WorldGuard +softdepend: + - WorldEdit -commands: - gamingcore: - description: Commande principale de GamingCore - aliases: [gc, mining] - permission: gamingcore.use - usage: / [help|ore|reload] - -permissions: - gamingcore.use: - description: Permet d'utiliser les commandes de base de GamingCore - default: true - gamingcore.admin: - description: Permet d'administrer les minerais et recharger le plugin - default: op diff --git a/src/test/java/fr/luc/gamingcore/mining/OreModelTest.java b/src/test/java/fr/luc/gamingcore/mining/OreModelTest.java deleted file mode 100644 index 0460c0d..0000000 --- a/src/test/java/fr/luc/gamingcore/mining/OreModelTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package fr.luc.gamingcore.mining; - -import com.cryptomorin.xseries.XMaterial; -import fr.luc.gamingcore.mining.model.*; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; - -import static org.junit.jupiter.api.Assertions.*; - -public class OreModelTest { - - @Test - public void testOreStockAndDepletion() { - CustomOre ore = new CustomOre("test_iron", "Test Iron", XMaterial.IRON_ORE, 3.0, - OreRarity.COMMON, 3, true, 10, XMaterial.BEDROCK, new ArrayList<>()); - - BlockLocation loc = new BlockLocation("world", 100, 64, -200); - PlacedOreBlock placed = new PlacedOreBlock(1, ore.getId(), ore, loc, ore.getStock(), false, 0); - - assertEquals(3, placed.getCurrentStock()); - assertFalse(placed.isDepleted()); - - // First hit - boolean depleted1 = placed.decrementStock(); - assertFalse(depleted1); - assertEquals(2, placed.getCurrentStock()); - - // Second hit - boolean depleted2 = placed.decrementStock(); - assertFalse(depleted2); - assertEquals(1, placed.getCurrentStock()); - - // Third hit -> Depleted - boolean depleted3 = placed.decrementStock(); - assertTrue(depleted3); - assertEquals(0, placed.getCurrentStock()); - assertTrue(placed.isDepleted()); - assertTrue(placed.getNextRespawnTimestamp() > System.currentTimeMillis()); - - // Respawn - placed.respawn(); - assertFalse(placed.isDepleted()); - assertEquals(3, placed.getCurrentStock()); - assertEquals(0L, placed.getNextRespawnTimestamp()); - } - - @Test - public void testBlockLocationEquality() { - BlockLocation loc1 = new BlockLocation("world", 10, 20, 30); - BlockLocation loc2 = new BlockLocation("world", 10, 20, 30); - BlockLocation loc3 = new BlockLocation("nether", 10, 20, 30); - - assertEquals(loc1, loc2); - assertEquals(loc1.hashCode(), loc2.hashCode()); - assertNotEquals(loc1, loc3); - } -}