From da3a69c201d948df277ef6498cec160d136b559c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 13 Sep 2025 15:44:45 +0000 Subject: [PATCH 1/2] Initial plan From d4f53100cd155ec742852605ef18edf9e3a56172 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 13 Sep 2025 15:52:21 +0000 Subject: [PATCH 2/2] Implement ghost spawner validation in FilterConfigUI to prevent navigation exploit Co-authored-by: ptthanh02 <73684260+ptthanh02@users.noreply.github.com> --- .../nighter/smartspawner/SmartSpawner.java | 4 ++++ .../gui/storage/filter/FilterConfigUI.java | 24 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/core/src/main/java/github/nighter/smartspawner/SmartSpawner.java b/core/src/main/java/github/nighter/smartspawner/SmartSpawner.java index 571e223a..e54cac38 100644 --- a/core/src/main/java/github/nighter/smartspawner/SmartSpawner.java +++ b/core/src/main/java/github/nighter/smartspawner/SmartSpawner.java @@ -367,6 +367,10 @@ public SpawnerStorageUI getSpawnerStorageUI() { return spawnerStorageUI; } + public SpawnerManager getSpawnerManager() { + return spawnerManager; + } + public SpawnerRangeChecker getRangeChecker() { return rangeChecker; } diff --git a/core/src/main/java/github/nighter/smartspawner/spawner/gui/storage/filter/FilterConfigUI.java b/core/src/main/java/github/nighter/smartspawner/spawner/gui/storage/filter/FilterConfigUI.java index c328fe04..4133f71f 100644 --- a/core/src/main/java/github/nighter/smartspawner/spawner/gui/storage/filter/FilterConfigUI.java +++ b/core/src/main/java/github/nighter/smartspawner/spawner/gui/storage/filter/FilterConfigUI.java @@ -92,6 +92,13 @@ public void onPlayerQuit(PlayerQuitEvent event) { * Opens the filter configuration GUI for a player and spawner */ public void openFilterConfigGUI(Player player, SpawnerData spawner) { + // Validate that the spawner still exists before opening the GUI + if (plugin.getSpawnerManager().isGhostSpawner(spawner)) { + // Spawner no longer exists, do not open the GUI + player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_BASS, 0.8f, 0.5f); + return; + } + // Create a new inventory with title from language manager String title = languageManager.getGuiTitle("gui_title_filter_config"); Inventory filterInventory = Bukkit.createInventory( @@ -222,6 +229,15 @@ public void onFilterInventoryClick(InventoryClickEvent event) { } SpawnerData spawner = holder.getSpawnerData(); + + // Validate that the spawner still exists before processing any actions + if (plugin.getSpawnerManager().isGhostSpawner(spawner)) { + // Spawner no longer exists, close the inventory + player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_BASS, 0.8f, 0.5f); + player.closeInventory(); + return; + } + int slot = event.getRawSlot(); // Handle divider clicks (return to storage) @@ -248,6 +264,14 @@ public void onFilterInventoryClick(InventoryClickEvent event) { * Returns to the spawner storage UI */ private void returnToStorage(Player player, SpawnerData spawner) { + // Validate that the spawner still exists before allowing navigation + if (plugin.getSpawnerManager().isGhostSpawner(spawner)) { + // Spawner no longer exists, close the inventory and prevent navigation + player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_BASS, 0.8f, 0.5f); + player.closeInventory(); + return; + } + // Return to storage menu player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 0.8f, 1.0f); player.closeInventory();