From d9be238ccd172e19a26db50ea0a08b3e70547d10 Mon Sep 17 00:00:00 2001 From: Garsooon Date: Wed, 10 Sep 2025 18:24:25 +0900 Subject: [PATCH 1/7] Limit bets to 2nd decimal --- .../org/garsooon/arenafighter/Commands/FightCommand.java | 7 ++++++- .../garsooon/arenafighter/Commands/SpectateBetCommand.java | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/garsooon/arenafighter/Commands/FightCommand.java b/src/main/java/org/garsooon/arenafighter/Commands/FightCommand.java index 0bc7267..dbc466f 100644 --- a/src/main/java/org/garsooon/arenafighter/Commands/FightCommand.java +++ b/src/main/java/org/garsooon/arenafighter/Commands/FightCommand.java @@ -141,8 +141,13 @@ private boolean handleChallenge(Player challenger, String[] args) { double wagerAmount = 0.0; if (args.length >= 3) { try { + String[] split = args[2].split("\\."); + if (split.length == 2 && split[1].length() > 2) { + challenger.sendMessage(ChatColor.RED + "Wagers can only have up to two decimals."); + return true; + } wagerAmount = Double.parseDouble(args[2]); - wagerAmount = Bet.roundDownTwoDecimals(wagerAmount); // <-- round down here + wagerAmount = Bet.roundDownTwoDecimals(wagerAmount); if (wagerAmount < 0) { challenger.sendMessage(ChatColor.RED + "Wager amount cannot be negative."); return true; diff --git a/src/main/java/org/garsooon/arenafighter/Commands/SpectateBetCommand.java b/src/main/java/org/garsooon/arenafighter/Commands/SpectateBetCommand.java index b867dc1..71ae509 100644 --- a/src/main/java/org/garsooon/arenafighter/Commands/SpectateBetCommand.java +++ b/src/main/java/org/garsooon/arenafighter/Commands/SpectateBetCommand.java @@ -40,6 +40,11 @@ public boolean onCommand(CommandSender sender, Command command, String label, St double amount; try { + String[] split = args[1].split("\\."); + if (split.length == 2 && split[1].length() > 2) { + player.sendMessage(ChatColor.RED + "Bets can only have up to two decimals."); + return true; + } amount = Double.parseDouble(args[1]); amount = Bet.roundDownTwoDecimals(amount); if (amount <= 0) { From 6b4a775ae66386d7c359189af038b688afa57b3b Mon Sep 17 00:00:00 2001 From: Garsooon Date: Sat, 27 Sep 2025 22:12:18 +0900 Subject: [PATCH 2/7] Public Getter & flag support --- .../arenafighter/Fight/FightManager.java | 57 ++++++++++++++++++- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/garsooon/arenafighter/Fight/FightManager.java b/src/main/java/org/garsooon/arenafighter/Fight/FightManager.java index 4e2fa1a..8285dc3 100644 --- a/src/main/java/org/garsooon/arenafighter/Fight/FightManager.java +++ b/src/main/java/org/garsooon/arenafighter/Fight/FightManager.java @@ -29,6 +29,8 @@ public class FightManager { private final ArenaFighter plugin; private final ArenaManager arenaManager; private final Map activeFights; + private final Set fightParticipants = new HashSet<>(); + private final Set recentlyDiedInArena = new HashSet<>(); private final Map originalLocations; private final Map originalInventories = new HashMap<>(); private final Map originalArmor = new HashMap<>(); @@ -210,6 +212,9 @@ public boolean startFight(Player player1, Player player2, double wager) { activeFights.put(player1.getUniqueId(), fight); activeFights.put(player2.getUniqueId(), fight); + fightParticipants.add(fight.getPlayer1().getUniqueId()); + fightParticipants.add(fight.getPlayer2().getUniqueId()); + arenaManager.occupyArena(arena); forceCloseInventory(player1); @@ -266,9 +271,15 @@ public void endFight(Player winner, Player loser) { Fight fight = activeFights.get(winner.getUniqueId()); if (fight == null) return; + markRecentlyDiedInArena(winner.getUniqueId()); + markRecentlyDiedInArena(loser.getUniqueId()); + activeFights.remove(winner.getUniqueId()); activeFights.remove(loser.getUniqueId()); + fightParticipants.remove(fight.getPlayer1().getUniqueId()); + fightParticipants.remove(fight.getPlayer2().getUniqueId()); + arenaManager.releaseArena(fight.getArena()); startPostFightCooldown(winner); @@ -367,7 +378,11 @@ public void run() { } if (savedArmor != null) { - player.getInventory().setArmorContents(savedArmor); + ItemStack[] armorCopy = new ItemStack[savedArmor.length]; + for (int i = 0; i < savedArmor.length; i++) { + armorCopy[i] = savedArmor[i] != null ? savedArmor[i].clone() : null; + } + player.getInventory().setArmorContents(armorCopy); } Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @@ -408,7 +423,11 @@ public void run() { } if (savedArmor != null) { - player.getInventory().setArmorContents(savedArmor); + ItemStack[] armorCopy = new ItemStack[savedArmor.length]; + for (int i = 0; i < savedArmor.length; i++) { + armorCopy[i] = savedArmor[i] != null ? savedArmor[i].clone() : null; + } + player.getInventory().setArmorContents(armorCopy); } player.updateInventory(); @@ -438,7 +457,6 @@ public void run() { } } - player.updateInventory(); } }, 2L); @@ -982,4 +1000,37 @@ public List getPlayerStatsByName(String name) { } // Stat and leaderboard functions end + // Public getters + public boolean getIsInFight(Player player) {return activeFights.containsKey(player.getUniqueId());} + + public boolean isFightParticipant(Player player) { + return fightParticipants.contains(player.getUniqueId()); + } + + public boolean isFightParticipant(UUID uuid) {return fightParticipants.contains(uuid);} + + //TODO debug config + public boolean isFightParticipantByName(String name) { +// System.out.println("DEBUG: Checking isFightParticipantByName for name=" + name); + for (UUID uuid : fightParticipants) { + Player p = plugin.getServer().getPlayer(uuid); + if (p != null) { +// System.out.println("DEBUG: Comparing with participant name=" + p.getName()); + if (p.getName().equalsIgnoreCase(name)) { +// System.out.println("DEBUG: MATCH! " + name + " is in fightParticipants"); + return true; + } + } else { +// System.out.println("DEBUG: Player for UUID " + uuid + " is null (not online?)"); + } + } +// System.out.println("DEBUG: NO MATCH for " + name + " in fightParticipants"); + return false; + } + + public void markRecentlyDiedInArena(UUID uuid) { recentlyDiedInArena.add(uuid);} + + public boolean didRecentlyDieInArena(UUID uuid) {return recentlyDiedInArena.contains(uuid);} + + public void clearRecentlyDiedInArena(UUID uuid) {recentlyDiedInArena.remove(uuid);} } From fb19da1b95ea68743504c8a476ced3900d3af9e6 Mon Sep 17 00:00:00 2001 From: Garsooon Date: Sat, 27 Sep 2025 22:48:42 +0900 Subject: [PATCH 3/7] Guarantee bet returns investment --- src/main/java/org/garsooon/arenafighter/Fight/Fight.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/org/garsooon/arenafighter/Fight/Fight.java b/src/main/java/org/garsooon/arenafighter/Fight/Fight.java index 70d0e77..f120a27 100644 --- a/src/main/java/org/garsooon/arenafighter/Fight/Fight.java +++ b/src/main/java/org/garsooon/arenafighter/Fight/Fight.java @@ -127,6 +127,10 @@ public void resolveBets(String winner) { double share = (bet.getAmount() / winnerPool) * loserPool; double payout = base + share; + payout = Math.max(payout, base); + + payout = Math.floor(payout * 100) / 100.0; + Methods.getMethod().depositPlayer(bet.getSpectator(), payout, p.getWorld()); p.sendMessage(ChatColor.GOLD + "You won your bet on " + winner + "! You receive " + payout); } else { From ccad67e83796b48c901c7ff0741ce324afb267fd Mon Sep 17 00:00:00 2001 From: Garsooon Date: Sat, 27 Sep 2025 22:52:41 +0900 Subject: [PATCH 4/7] Removes spectator O-location tracking map --- .../Commands/SpectateCommand.java | 13 +---- .../arenafighter/Fight/FightManager.java | 57 ++++++------------- 2 files changed, 19 insertions(+), 51 deletions(-) diff --git a/src/main/java/org/garsooon/arenafighter/Commands/SpectateCommand.java b/src/main/java/org/garsooon/arenafighter/Commands/SpectateCommand.java index e3a9586..b3f0c44 100644 --- a/src/main/java/org/garsooon/arenafighter/Commands/SpectateCommand.java +++ b/src/main/java/org/garsooon/arenafighter/Commands/SpectateCommand.java @@ -23,17 +23,6 @@ public boolean onCommand(CommandSender sender, Command command, String label, St } Player player = (Player) sender; - if (fightManager.isSpectating(player)) { - // If already spectating, stop and return - boolean stopped = fightManager.stopSpectating(player); - if (stopped) { - player.sendMessage(ChatColor.YELLOW + "You have stopped spectating and returned to your original location."); - } else { - player.sendMessage(ChatColor.RED + "An error occurred while stopping spectating."); - } - return true; - } - // Start spectating: requires arena name for multi-arena support if (args.length == 0) { player.sendMessage(ChatColor.RED + "Usage: /spectate "); @@ -48,4 +37,4 @@ public boolean onCommand(CommandSender sender, Command command, String label, St return true; } -} +} \ No newline at end of file diff --git a/src/main/java/org/garsooon/arenafighter/Fight/FightManager.java b/src/main/java/org/garsooon/arenafighter/Fight/FightManager.java index 8285dc3..dac2970 100644 --- a/src/main/java/org/garsooon/arenafighter/Fight/FightManager.java +++ b/src/main/java/org/garsooon/arenafighter/Fight/FightManager.java @@ -36,7 +36,7 @@ public class FightManager { private final Map originalArmor = new HashMap<>(); private final HashMap postFightCooldowns = new HashMap<>(); private final Map pendingChallenges; - private final Map spectatorOriginalLocations; +// private final Map spectatorOriginalLocations; private final Map punishments = new HashMap<>(); private final long punishmentDurationMillis; private final Method economy; @@ -51,7 +51,7 @@ public FightManager(ArenaFighter plugin, ArenaManager arenaManager, Method econo this.activeFights = new HashMap<>(); this.originalLocations = new HashMap<>(); this.pendingChallenges = new HashMap<>(); - this.spectatorOriginalLocations = new HashMap<>(); +// this.spectatorOriginalLocations = new HashMap<>(); this.punishmentDurationMillis = loadPunishmentDuration(plugin.getDataFolder()); this.statsFile = new File(plugin.getDataFolder(), "stats.yml"); loadStats(); @@ -320,7 +320,7 @@ public void endFight(Player winner, Player loser) { healAndFeedPlayer(loser); } - stopAllSpectators(); +// stopAllSpectators(); double wager = fight.getWager(); @@ -613,7 +613,7 @@ public void cancelFight(Player player) { healAndFeedPlayer(otherPlayer); } - stopAllSpectators(); +// stopAllSpectators(); String message = ChatColor.RED + "Fight cancelled!"; player.sendMessage(message); @@ -653,7 +653,7 @@ public void cleanup() { activeFights.clear(); originalLocations.clear(); - stopAllSpectators(); +// stopAllSpectators(); } public boolean hasPendingChallenge(Player player) { @@ -724,10 +724,6 @@ public void cancelChallenge(Player player) { public boolean startSpectating(Player player) { UUID uuid = player.getUniqueId(); - if (spectatorOriginalLocations.containsKey(uuid)) { - player.sendMessage(ChatColor.RED + "You are already spectating."); - return false; - } Fight fight = null; for (Fight f : activeFights.values()) { @@ -750,7 +746,6 @@ public boolean startSpectating(Player player) { return false; } - spectatorOriginalLocations.put(uuid, player.getLocation().clone()); player.teleport(specSpawn); player.sendMessage(ChatColor.YELLOW + "You are now spectating the fight between " + fight.getPlayer1().getName() + " and " + fight.getPlayer2().getName() + "."); @@ -760,11 +755,6 @@ public boolean startSpectating(Player player) { public boolean startSpectating(Player player, String arenaName) { UUID uuid = player.getUniqueId(); - if (spectatorOriginalLocations.containsKey(uuid)) { - player.sendMessage(ChatColor.RED + "You are already spectating."); - return false; - } - Arena arena = arenaManager.getArena(arenaName); if (arena == null) { player.sendMessage(ChatColor.RED + "Arena '" + arenaName + "' does not exist."); @@ -777,39 +767,28 @@ public boolean startSpectating(Player player, String arenaName) { return false; } - spectatorOriginalLocations.put(uuid, player.getLocation().clone()); player.teleport(specSpawn); player.sendMessage(ChatColor.YELLOW + "You are now spectating arena: " + ChatColor.AQUA + arenaName); - player.sendMessage(ChatColor.YELLOW + "Use /spectate to return to your original location."); return true; } public boolean stopSpectating(Player player) { - UUID uuid = player.getUniqueId(); - Location original = spectatorOriginalLocations.remove(uuid); - - if (original != null) { - player.teleport(original); - player.sendMessage(ChatColor.YELLOW + "Returned from spectating."); - return true; - } - - player.sendMessage(ChatColor.RED + "You are not spectating."); - return false; + player.sendMessage(ChatColor.YELLOW + "You have stopped spectating."); + return true; } - public void stopAllSpectators() { - for (UUID uuid : new HashMap<>(spectatorOriginalLocations).keySet()) { - Player player = plugin.getServer().getPlayer(uuid); - if (player != null && player.isOnline()) { - stopSpectating(player); - } - } - } +// public void stopAllSpectators() { +// for (UUID uuid : new HashMap<>(spectatorOriginalLocations).keySet()) { +// Player player = plugin.getServer().getPlayer(uuid); +// if (player != null && player.isOnline()) { +// stopSpectating(player); +// } +// } +// } - public boolean isSpectating(Player player) { - return spectatorOriginalLocations.containsKey(player.getUniqueId()); - } +// public boolean isSpectating(Player player) { +// return spectatorOriginalLocations.containsKey(player.getUniqueId()); +// } //ECO Wager per Challenge data start private static class FightChallenge { From 4d3ca08c2db131314072b32c9baa2bbc14207223 Mon Sep 17 00:00:00 2001 From: Garsooon Date: Sun, 28 Sep 2025 15:28:16 +0900 Subject: [PATCH 5/7] Adds better checks & catches --- pom.xml | 2 +- .../arenafighter/Fight/FightManager.java | 262 ++++++++++++------ src/main/resources/plugin.yml | 2 +- 3 files changed, 176 insertions(+), 90 deletions(-) diff --git a/pom.xml b/pom.xml index 1109d8f..d0e8b9b 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.garsooon arenafighter - 1.0.9 + 1.1.0 jar diff --git a/src/main/java/org/garsooon/arenafighter/Fight/FightManager.java b/src/main/java/org/garsooon/arenafighter/Fight/FightManager.java index dac2970..30fbf7c 100644 --- a/src/main/java/org/garsooon/arenafighter/Fight/FightManager.java +++ b/src/main/java/org/garsooon/arenafighter/Fight/FightManager.java @@ -289,66 +289,115 @@ public void endFight(Player winner, Player loser) { // forceCloseInventory(loser); UUID loserId = loser.getUniqueId(); - ItemStack[] inventory = loser.getInventory().getContents().clone(); - ItemStack[] armor = loser.getInventory().getArmorContents().clone(); + ItemStack[] inventory; + ItemStack[] armor; + try { + inventory = loser.getInventory().getContents().clone(); + armor = loser.getInventory().getArmorContents().clone(); + } catch (Exception e) { + return; + } ItemStack cursor = getItemOnCursor(loser); if (cursor != null && cursor.getTypeId() != 0) { - for (int i = 0; i < inventory.length; i++) { - if (inventory[i] == null || inventory[i].getTypeId() == 0) { - inventory[i] = cursor; - break; + boolean inserted = false; + try { + for (int i = 0; i < inventory.length; i++) { + if (inventory[i] == null || inventory[i].getTypeId() == 0) { + inventory[i] = cursor; + inserted = true; + break; + } } + } catch (IndexOutOfBoundsException e) { } setItemOnCursor(loser, new ItemStack(0)); } - originalInventories.put(loserId, inventory); - originalArmor.put(loserId, armor); + try { + originalInventories.put(loserId, inventory); + originalArmor.put(loserId, armor); + } catch (Exception e) { + } - Location winnerOriginal = originalLocations.remove(winner.getUniqueId()); - Location loserOriginal = originalLocations.remove(loser.getUniqueId()); + Location winnerOriginal; + Location loserOriginal; + try { + winnerOriginal = originalLocations.remove(winner.getUniqueId()); + loserOriginal = originalLocations.remove(loser.getUniqueId()); + } catch (Exception e) { + winnerOriginal = null; + loserOriginal = null; + } if (winnerOriginal != null) { - winner.teleport(winnerOriginal); - healAndFeedPlayer(winner); + try { + winner.teleport(winnerOriginal); + healAndFeedPlayer(winner); + } catch (Exception e) { + } } if (loserOriginal != null) { - loser.teleport(loserOriginal); - restoreOriginalInventoryAndArmor(loser); - healAndFeedPlayer(loser); + try { + loser.teleport(loserOriginal); + restoreOriginalInventoryAndArmor(loser); + healAndFeedPlayer(loser); + } catch (Exception e) { + } } // stopAllSpectators(); - double wager = fight.getWager(); + double wager; + try { + wager = fight.getWager(); + } catch (Exception e) { + wager = 0; + } if (wager > 0) { - double truncatedWager = Bet.roundDownTwoDecimals(wager); - deposit(winner, wager * 2); - winner.sendMessage(ChatColor.GREEN + "You have won " + (wager * 2) + " from the wager!"); + try { + double truncatedWager = Bet.roundDownTwoDecimals(wager); + deposit(winner, wager * 2); + winner.sendMessage(ChatColor.GREEN + "You have won " + (wager * 2) + " from the wager!"); + } catch (Exception e) { + } } - fight.resolveBets(winner.getName()); + try { + fight.resolveBets(winner.getName()); + } catch (Exception e) { + } - incrementStat(winner.getUniqueId(), "wins", winner.getName()); - incrementStat(loser.getUniqueId(), "losses", loser.getName()); + try { + incrementStat(winner.getUniqueId(), "wins", winner.getName()); + incrementStat(loser.getUniqueId(), "losses", loser.getName()); + } catch (Exception e) { + } - String message = ChatColor.GOLD + winner.getName() + - ChatColor.YELLOW + " has defeated " + - ChatColor.RED + loser.getName() + - ChatColor.YELLOW + " in arena " + - ChatColor.GREEN + fight.getArena().getName(); + String message; + try { + message = ChatColor.GOLD + winner.getName() + + ChatColor.YELLOW + " has defeated " + + ChatColor.RED + loser.getName() + + ChatColor.YELLOW + " in arena " + + ChatColor.GREEN + fight.getArena().getName(); - if (wager > 0) { - double truncatedWager = Bet.roundDownTwoDecimals(wager * 2); - message += ChatColor.YELLOW + " and won a wager of " + ChatColor.GOLD + truncatedWager; - } + if (wager > 0) { + double truncatedWager = Bet.roundDownTwoDecimals(wager * 2); + message += ChatColor.YELLOW + " and won a wager of " + ChatColor.GOLD + truncatedWager; + } - message += ChatColor.YELLOW + "!"; + message += ChatColor.YELLOW + "!"; + } catch (Exception e) { + message = ""; + } - plugin.getServer().broadcastMessage(message); + try { + plugin.getServer().broadcastMessage(message); + } catch (Exception e) { + } } // Boy I sure do love not having itemStackCursor in poseidon :clueless: @@ -368,46 +417,73 @@ public void run() { final ItemStack[] savedArmor = originalArmor.remove(uuid); if (savedInventory != null) { - player.getInventory().clear(); - - // Fill inventory backwards to reduce stacking dupes - for (int i = savedInventory.length - 1; i >= 0; i--) { - ItemStack item = savedInventory[i]; - player.getInventory().setItem(i, item != null ? item.clone() : null); + try { + player.getInventory().clear(); + // Fill inventory backwards to reduce stacking dupes + for (int i = savedInventory.length - 1; i >= 0; i--) { + if (i < player.getInventory().getSize()) { + ItemStack item = savedInventory[i]; + player.getInventory().setItem(i, item != null ? item.clone() : null); + } + } + } catch (Exception e) { + e.printStackTrace(); } } if (savedArmor != null) { - ItemStack[] armorCopy = new ItemStack[savedArmor.length]; - for (int i = 0; i < savedArmor.length; i++) { - armorCopy[i] = savedArmor[i] != null ? savedArmor[i].clone() : null; + try { + ItemStack[] armorCopy = new ItemStack[savedArmor.length]; + for (int i = 0; i < savedArmor.length; i++) { + armorCopy[i] = savedArmor[i] != null ? savedArmor[i].clone() : null; + } + player.getInventory().setArmorContents(armorCopy); + } catch (Exception e) { + e.printStackTrace(); } - player.getInventory().setArmorContents(armorCopy); } Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { - player.updateInventory(); + try { + player.updateInventory(); + } catch (Exception e) { + e.printStackTrace(); + } // Shouldn't run now that inventories are saved on fight end. Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { - boolean inventoryMismatch = !deepInventoryMatch(player.getInventory().getContents(), savedInventory); - boolean armorMismatch = !deepInventoryMatch(player.getInventory().getArmorContents(), savedArmor); + boolean inventoryMismatch = false; + boolean armorMismatch = false; + try { + inventoryMismatch = !deepInventoryMatch(player.getInventory().getContents(), savedInventory); + armorMismatch = !deepInventoryMatch(player.getInventory().getArmorContents(), savedArmor); + } catch (Exception e) { + e.printStackTrace(); + } if (inventoryMismatch || armorMismatch) { - player.sendMessage(ChatColor.RED + "Your inventory failed to restore properly. Retrying..."); + try { + player.sendMessage(ChatColor.RED + "Your inventory failed to restore properly. Retrying..."); + } catch (Exception e) { + e.printStackTrace(); + } //Debug if (savedInventory != null) { ItemStack[] current = player.getInventory().getContents(); for (int i = 0; i < savedInventory.length; i++) { - if (!deepItemEquals(savedInventory[i], current[i])) { - plugin.getServer().getLogger().warning("[ArenaFighter] Inventory slot mismatch at " + i + " for player " + player.getName()); - plugin.getServer().getLogger().warning("Expected: " + itemToString(savedInventory[i])); - plugin.getServer().getLogger().warning("Found: " + itemToString(current[i])); + try { + if (!deepItemEquals(savedInventory[i], current[i])) { + plugin.getServer().getLogger().warning("[ArenaFighter] Inventory slot mismatch at " + i + " for player " + player.getName()); + plugin.getServer().getLogger().warning("Expected: " + itemToString(savedInventory[i])); + plugin.getServer().getLogger().warning("Found: " + itemToString(current[i])); + } + } catch (Exception e) { + e.printStackTrace(); } } } @@ -416,48 +492,58 @@ public void run() { @SuppressWarnings("DataFlowIssue") @Override public void run() { - player.getInventory().clear(); - for (int i = savedInventory.length - 1; i >= 0; i--) { - ItemStack item = savedInventory[i]; - player.getInventory().setItem(i, item != null ? item.clone() : null); - } - - if (savedArmor != null) { - ItemStack[] armorCopy = new ItemStack[savedArmor.length]; - for (int i = 0; i < savedArmor.length; i++) { - armorCopy[i] = savedArmor[i] != null ? savedArmor[i].clone() : null; + try { + player.getInventory().clear(); + for (int i = savedInventory.length - 1; i >= 0; i--) { + if (i < player.getInventory().getSize()) { + ItemStack item = savedInventory[i]; + player.getInventory().setItem(i, item != null ? item.clone() : null); + } } - player.getInventory().setArmorContents(armorCopy); - } - - player.updateInventory(); - // Final check for total item quantity mismatch - Map expected = countItemQuantities(savedInventory); - Map actual = countItemQuantities(player.getInventory().getContents()); - - for (Map.Entry entry : expected.entrySet()) { - String key = entry.getKey(); - int expectedAmount = entry.getValue(); - int actualAmount = actual.getOrDefault(key, 0); - - if (actualAmount < expectedAmount) { - int missing = expectedAmount - actualAmount; - String[] split = key.split(":"); - int typeId = Integer.parseInt(split[0]); - short damage = Short.parseShort(split[1]); - - ItemStack stack = new ItemStack(typeId, missing, damage); - player.getInventory().addItem(stack); + if (savedArmor != null) { + ItemStack[] armorCopy = new ItemStack[savedArmor.length]; + for (int i = 0; i < savedArmor.length; i++) { + armorCopy[i] = savedArmor[i] != null ? savedArmor[i].clone() : null; + } + player.getInventory().setArmorContents(armorCopy); + } - // Debug log -defunct - plugin.getServer().getLogger().warning("[ArenaFighter] Mismatch recovery for " + player.getName() + - ": added back " + missing + " of ItemStack{typeId=" + typeId + ", damage=" + damage + "} " + - "(expected=" + expectedAmount + ", actual=" + actualAmount + ")"); + player.updateInventory(); + + // Final check for total item quantity mismatch + Map expected = countItemQuantities(savedInventory); + Map actual = countItemQuantities(player.getInventory().getContents()); + + for (Map.Entry entry : expected.entrySet()) { + try { + String key = entry.getKey(); + int expectedAmount = entry.getValue(); + int actualAmount = actual.getOrDefault(key, 0); + + if (actualAmount < expectedAmount) { + int missing = expectedAmount - actualAmount; + String[] split = key.split(":"); + int typeId = Integer.parseInt(split[0]); + short damage = Short.parseShort(split[1]); + + ItemStack stack = new ItemStack(typeId, missing, damage); + player.getInventory().addItem(stack); + + // Debug log -defunct + plugin.getServer().getLogger().warning("[ArenaFighter] Mismatch recovery for " + player.getName() + + ": added back " + missing + " of ItemStack{typeId=" + typeId + ", damage=" + damage + "} " + + "(expected=" + expectedAmount + ", actual=" + actualAmount + ")"); + } + } catch (Exception e) { + e.printStackTrace(); + } } - } - player.updateInventory(); + player.updateInventory(); + } catch (Exception e) { + e.printStackTrace(); + } } }, 2L); } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 511775a..0ea60be 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ name: ArenaFighter -version: 1.0.9 +version: 1.1.0 description: A plugin that allows players to fight in arenas and teleports them back after fights conclude author: Garsooon main: org.garsooon.arenafighter.Arena.ArenaFighter From 3bd4690f749698cc22e57b9a05944633cbc43f18 Mon Sep 17 00:00:00 2001 From: Garsooon Date: Sun, 28 Sep 2025 21:38:56 +0900 Subject: [PATCH 6/7] Add enable/disable command --- .../arenafighter/Arena/ArenaFighter.java | 86 ++++++++++++++++++- .../arenafighter/Commands/ArenaCommand.java | 40 ++++++++- .../arenafighter/Commands/FightCommand.java | 8 ++ src/main/resources/config.yml | 6 +- 4 files changed, 133 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/garsooon/arenafighter/Arena/ArenaFighter.java b/src/main/java/org/garsooon/arenafighter/Arena/ArenaFighter.java index eac55db..f574b26 100644 --- a/src/main/java/org/garsooon/arenafighter/Arena/ArenaFighter.java +++ b/src/main/java/org/garsooon/arenafighter/Arena/ArenaFighter.java @@ -18,11 +18,13 @@ import java.io.File; import java.io.FileInputStream; +import java.io.FileWriter; import java.io.InputStream; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.LinkedHashMap; import static org.bukkit.Bukkit.getLogger; @@ -36,8 +38,16 @@ public class ArenaFighter extends JavaPlugin { @SuppressWarnings("FieldMayBeFinal") private Set blockedCommands = new HashSet<>(); + private boolean arenaEnabled = true; + private Map configData; + @Override public void onEnable() { + // Create default config if missing + createDefaultConfig(); + + loadArenaEnabledFlag(); + // Initialize ArenaManager this.arenaManager = new ArenaManager(this); @@ -60,7 +70,7 @@ public void onEnable() { // Register commands getCommand("fight").setExecutor(fightCommand); - getCommand("arena").setExecutor(new ArenaCommand(arenaManager)); + getCommand("arena").setExecutor(new ArenaCommand(arenaManager, this)); getCommand("spectate").setExecutor(new SpectateCommand(fightManager)); getCommand("bet").setExecutor(new SpectateBetCommand(fightManager)); this.getCommand("fightabout").setExecutor(new FightAboutCommand(this)); @@ -72,9 +82,6 @@ public void onEnable() { pm.registerEvents(new PlayerDropListener(fightManager), this); pm.registerEvents(new PlayerCommandListener(this, fightManager), this); - // Create default config if missing - createDefaultConfig(); - // Load blocked commands list loadBlockedCommands(); @@ -105,6 +112,73 @@ public Set getBlockedCommands() { return blockedCommands; } + public boolean isArenaEnabled() { + return arenaEnabled; + } + + public void setArenaEnabled(boolean enabled) { + this.arenaEnabled = enabled; + if (configData == null) configData = new LinkedHashMap<>(); + Map arenaSection; + if (configData.containsKey("arena") && configData.get("arena") instanceof Map) { + arenaSection = (Map) configData.get("arena"); + } else { + arenaSection = new LinkedHashMap<>(); + configData.put("arena", arenaSection); + } + arenaSection.put("enabled", enabled); + saveConfigFile(); + } + + private void loadArenaEnabledFlag() { + File configFile = new File(getDataFolder(), "config.yml"); + Yaml yaml = new Yaml(); + configData = null; + + try (InputStream input = new FileInputStream(configFile)) { + configData = (Map) yaml.load(input); + } catch (Exception e) { + configData = new LinkedHashMap<>(); + } + + if (configData == null) configData = new LinkedHashMap<>(); + + boolean needSave = false; + + Map arenaSection; + if (configData.containsKey("arena") && configData.get("arena") instanceof Map) { + arenaSection = (Map) configData.get("arena"); + } else { + arenaSection = new LinkedHashMap<>(); + configData.put("arena", arenaSection); + needSave = true; + } + + if (!arenaSection.containsKey("enabled")) { + arenaSection.put("enabled", true); + this.arenaEnabled = true; + needSave = true; + } else { + Object value = arenaSection.get("enabled"); + this.arenaEnabled = (value instanceof Boolean) ? (Boolean) value : Boolean.parseBoolean(String.valueOf(value)); + } + + if (needSave) saveConfigFile(); + } + + //I should pr a config api that isnt for poseidons own config xd + private void saveConfigFile() { + File configFile = new File(getDataFolder(), "config.yml"); + org.yaml.snakeyaml.DumperOptions options = new org.yaml.snakeyaml.DumperOptions(); + options.setDefaultFlowStyle(org.yaml.snakeyaml.DumperOptions.FlowStyle.BLOCK); + Yaml yaml = new Yaml(options); + try (FileWriter writer = new FileWriter(configFile)) { + yaml.dump(configData, writer); + } catch (Exception e) { + getLogger().warning("Failed to save config.yml: " + e.getMessage()); + } + } + private void createDefaultConfig() { if (!getDataFolder().exists()) { getDataFolder().mkdirs(); @@ -121,6 +195,10 @@ private void createDefaultConfig() { writer.write("# To configure your arenas, run /arena create \n"); writer.write("# then you can modify it in arenas.properties in this folder\n"); writer.write("\n"); + writer.write("# Arena system enabled/disabled\n"); + writer.write("arena:\n"); + writer.write(" enabled: true\n"); + writer.write("\n"); writer.write("punishment:\n"); writer.write(" duration-minute: 5\n"); writer.write("\n"); diff --git a/src/main/java/org/garsooon/arenafighter/Commands/ArenaCommand.java b/src/main/java/org/garsooon/arenafighter/Commands/ArenaCommand.java index e0bf7e6..f3b146f 100644 --- a/src/main/java/org/garsooon/arenafighter/Commands/ArenaCommand.java +++ b/src/main/java/org/garsooon/arenafighter/Commands/ArenaCommand.java @@ -8,6 +8,7 @@ import org.bukkit.entity.Player; import org.garsooon.arenafighter.Arena.Arena; import org.garsooon.arenafighter.Arena.ArenaManager; +import org.garsooon.arenafighter.Arena.ArenaFighter; import java.util.List; @@ -15,9 +16,15 @@ public class ArenaCommand implements CommandExecutor { private final ArenaManager arenaManager; + private final ArenaFighter plugin; - public ArenaCommand(ArenaManager arenaManager) { + public ArenaCommand(ArenaManager arenaManager, ArenaFighter plugin) { this.arenaManager = arenaManager; + this.plugin = plugin; + } + + public ArenaCommand(ArenaManager arenaManager) { + this(arenaManager, null); } @SuppressWarnings("DuplicateBranchesInSwitch") @@ -36,6 +43,10 @@ public boolean onCommand(CommandSender sender, Command command, String label, St } switch (args[0].toLowerCase()) { + case "enable": + return handleEnable(player); + case "disable": + return handleDisable(player); case "create": return handleCreate(player, args); case "remove": @@ -55,6 +66,30 @@ public boolean onCommand(CommandSender sender, Command command, String label, St } } + private boolean handleEnable(Player player) { + if (!player.hasPermission("arenafighter.admin")) { + player.sendMessage(ChatColor.RED + "You don't have permission to enable ArenaFighter!"); + return true; + } + if (plugin != null) { + plugin.setArenaEnabled(true); + player.sendMessage(ChatColor.GREEN + "Arena Fighter enabled!"); + } + return true; + } + + private boolean handleDisable(Player player) { + if (!player.hasPermission("arenafighter.admin")) { + player.sendMessage(ChatColor.RED + "You don't have permission to disable ArenaFighter!"); + return true; + } + if (plugin != null) { + plugin.setArenaEnabled(false); + player.sendMessage(ChatColor.RED + "Arena Fighter disabled!"); + } + return true; + } + private boolean handleCreate(Player player, String[] args) { if (!player.hasPermission("arenafighter.admin")) { player.sendMessage(ChatColor.RED + "You don't have permission to create arenas!"); @@ -223,10 +258,11 @@ private boolean handleTeleport(Player player, String[] args) { private void sendHelpMessage(Player player) { player.sendMessage(ChatColor.GOLD + "=== Arena Fighter Commands ==="); + player.sendMessage(ChatColor.YELLOW + "/arena enable" + ChatColor.WHITE + " - Enable Arena Fighter"); + player.sendMessage(ChatColor.YELLOW + "/arena disable" + ChatColor.WHITE + " - Disable Arena Fighter"); player.sendMessage(ChatColor.YELLOW + "/arena create " + ChatColor.WHITE + " - Create a new arena"); player.sendMessage(ChatColor.YELLOW + "/arena remove " + ChatColor.WHITE + " - Remove an arena"); player.sendMessage(ChatColor.YELLOW + "/arena list" + ChatColor.WHITE + " - List all arenas"); - //Still don't know how to force a line break \n doesn't seem to work. New line as a work around. player.sendMessage(ChatColor.YELLOW + "/arena setspawn "); player.sendMessage(ChatColor.WHITE + " - Set spawn point"); player.sendMessage(ChatColor.YELLOW + "/arena tp [spawn1|spawn2]" + ChatColor.WHITE + " - Teleport to an arena"); diff --git a/src/main/java/org/garsooon/arenafighter/Commands/FightCommand.java b/src/main/java/org/garsooon/arenafighter/Commands/FightCommand.java index dbc466f..419d28c 100644 --- a/src/main/java/org/garsooon/arenafighter/Commands/FightCommand.java +++ b/src/main/java/org/garsooon/arenafighter/Commands/FightCommand.java @@ -91,6 +91,14 @@ public boolean onCommand(CommandSender sender, Command command, String label, St } private boolean handleChallenge(Player challenger, String[] args) { + if (plugin instanceof org.garsooon.arenafighter.Arena.ArenaFighter) { + org.garsooon.arenafighter.Arena.ArenaFighter afPlugin = (org.garsooon.arenafighter.Arena.ArenaFighter) plugin; + if (!afPlugin.isArenaEnabled()) { + challenger.sendMessage(ChatColor.RED + "Arena Fighter is currently disabled."); + return true; + } + } + if (args.length < 2) { challenger.sendMessage(ChatColor.RED + "Usage: /fight challenge [wagerAmount]"); return true; diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 3f798d1..2c38d01 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -2,6 +2,10 @@ # To configure your arenas, run /arena create in game # then you can modify it in arenas.properties in the ArenaFighter folder +# Arena system enabled/disabled +arena: + enabled: true + #Combat logging punishment punishment: duration-minutes: 5 @@ -18,4 +22,4 @@ blocked-commands: - "/tpa" - "/tpaccept" - "/tphere" - - "/heal" + - "/heal" \ No newline at end of file From dbdbd578483a8930a8784bbfaf29a697eec9e984 Mon Sep 17 00:00:00 2001 From: Garsooon Date: Sun, 28 Sep 2025 21:42:01 +0900 Subject: [PATCH 7/7] Update plugin.yml --- src/main/resources/plugin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 0ea60be..2b4c5b3 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -13,7 +13,7 @@ commands: usage: /fight [player] [wager] arena: description: Manage arena configurations - usage: /arena [args] + usage: /arena [args] permission: arenafighter.admin fightabout: description: Displays information about current ArenaFighter version