From e4cacd5e4e87b2e9db597cc7ef106eb59ef7d79a Mon Sep 17 00:00:00 2001 From: rockyhawk64 Date: Mon, 6 Oct 2025 16:46:04 +1100 Subject: [PATCH] bug fixes and cooldown added --- .../commandpanels/commands/TabComplete.java | 2 +- .../commands/subcommands/OpenCommand.java | 2 +- .../formatter/language/Message.java | 1 + .../openpanel/PanelOpenCommand.java | 2 +- .../commandpanels/session/Panel.java | 24 ++++++++- .../session/dialog/DialogPanel.java | 5 +- .../session/floodgate/FloodgatePanel.java | 5 +- .../session/inventory/InventoryPanel.java | 10 +--- .../inventory/InventoryPanelUpdater.java | 51 ++++++++++++++----- 9 files changed, 74 insertions(+), 28 deletions(-) diff --git a/src/me/rockyhawk/commandpanels/commands/TabComplete.java b/src/me/rockyhawk/commandpanels/commands/TabComplete.java index 16991b5..dc97eb4 100644 --- a/src/me/rockyhawk/commandpanels/commands/TabComplete.java +++ b/src/me/rockyhawk/commandpanels/commands/TabComplete.java @@ -48,7 +48,7 @@ public class TabComplete { if (sender instanceof Player player) { for (String panelName : ctx.plugin.panels.keySet()) { Panel panel = ctx.plugin.panels.get(panelName); - if (panel.canOpen(player, ctx)) { + if (panel.passesConditions(player, ctx)) { output.add(panelName); } } diff --git a/src/me/rockyhawk/commandpanels/commands/subcommands/OpenCommand.java b/src/me/rockyhawk/commandpanels/commands/subcommands/OpenCommand.java index b6184b0..2d4bfba 100644 --- a/src/me/rockyhawk/commandpanels/commands/subcommands/OpenCommand.java +++ b/src/me/rockyhawk/commandpanels/commands/subcommands/OpenCommand.java @@ -51,7 +51,7 @@ public class OpenCommand implements SubCommand { } } - if(sender instanceof Player && !panel.canOpen((Player) sender, ctx)){ + if(sender instanceof Player && !panel.passesConditions((Player) sender, ctx)){ ctx.text.sendError(sender, Message.COMMAND_NO_PERMISSION); return true; } diff --git a/src/me/rockyhawk/commandpanels/formatter/language/Message.java b/src/me/rockyhawk/commandpanels/formatter/language/Message.java index 4211964..93a9578 100644 --- a/src/me/rockyhawk/commandpanels/formatter/language/Message.java +++ b/src/me/rockyhawk/commandpanels/formatter/language/Message.java @@ -111,6 +111,7 @@ public enum Message { // Misc DIALOG_NO_BUTTONS("Dialog needs at least one button"), + COOLDOWN_ERROR("You're opening panels too quickly"), TELEPORT_ERROR("Error with teleport tag"), REQUIRE_HEADDATABASE("Download the HeadDatabase plugin to use this feature!"); diff --git a/src/me/rockyhawk/commandpanels/interaction/openpanel/PanelOpenCommand.java b/src/me/rockyhawk/commandpanels/interaction/openpanel/PanelOpenCommand.java index 55ae1e2..e22aab1 100644 --- a/src/me/rockyhawk/commandpanels/interaction/openpanel/PanelOpenCommand.java +++ b/src/me/rockyhawk/commandpanels/interaction/openpanel/PanelOpenCommand.java @@ -59,7 +59,7 @@ public class PanelOpenCommand implements Listener { } // Stop and do not open panel if conditions are false - if (!panel.canOpen(e.getPlayer(), ctx)) { + if (!panel.passesConditions(e.getPlayer(), ctx)) { continue; } diff --git a/src/me/rockyhawk/commandpanels/session/Panel.java b/src/me/rockyhawk/commandpanels/session/Panel.java index 0e92212..dc982ad 100644 --- a/src/me/rockyhawk/commandpanels/session/Panel.java +++ b/src/me/rockyhawk/commandpanels/session/Panel.java @@ -3,6 +3,8 @@ package me.rockyhawk.commandpanels.session; import me.rockyhawk.commandpanels.Context; import me.rockyhawk.commandpanels.builder.logic.ConditionNode; import me.rockyhawk.commandpanels.builder.logic.ConditionParser; +import me.rockyhawk.commandpanels.formatter.language.Message; +import me.rockyhawk.commandpanels.session.inventory.InventoryPanel; import org.bukkit.NamespacedKey; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; @@ -30,7 +32,8 @@ public abstract class Panel { this.type = config.getString("type", "inventory"); } - public boolean canOpen(Player player, Context ctx) { + // Check run for permission checks with commands + public boolean passesConditions(Player player, Context ctx) { // Check the panel condition if (this.conditions.trim().isEmpty()) return true; try { @@ -41,11 +44,30 @@ public abstract class Panel { } } + // Checks for opening fresh panels + public boolean canOpen(Player p, Context ctx) { + // Do not open if user is in cooldown period + NamespacedKey keyTime = new NamespacedKey(ctx.plugin, "last_open_time"); + Long lastOpen = p.getPersistentDataContainer().get(keyTime, PersistentDataType.LONG); + if (lastOpen != null && System.currentTimeMillis() - lastOpen < 250) { // 5 ticks + ctx.text.sendError(p, Message.COOLDOWN_ERROR); + return false; + } + + // Do not allow the same panel to be opened again if already open + return !(p.getOpenInventory().getTopInventory().getHolder() instanceof InventoryPanel panel) + || !panel.getName().equals(getName()); + } + // Updates data to set the current panel and previous panel. public void updatePanelData(Context ctx, Player p) { NamespacedKey keyCurrent = new NamespacedKey(ctx.plugin, "current"); NamespacedKey keyPrevious = new NamespacedKey(ctx.plugin, "previous"); + NamespacedKey keyTime = new NamespacedKey(ctx.plugin, "last_open_time"); PersistentDataContainer container = p.getPersistentDataContainer(); + + // Time the player last opened any panel + container.set(keyTime, PersistentDataType.LONG, System.currentTimeMillis()); // Move current → previous String current = container.get(keyCurrent, PersistentDataType.STRING); diff --git a/src/me/rockyhawk/commandpanels/session/dialog/DialogPanel.java b/src/me/rockyhawk/commandpanels/session/dialog/DialogPanel.java index ffa960a..af585a9 100644 --- a/src/me/rockyhawk/commandpanels/session/dialog/DialogPanel.java +++ b/src/me/rockyhawk/commandpanels/session/dialog/DialogPanel.java @@ -64,7 +64,10 @@ public class DialogPanel extends Panel { } if(isNewPanelSession) { - // Update panel data values + // Don't open same panel if its already open + if(!canOpen(player, ctx)){ + return; + } updatePanelData(ctx, player); // Run panel commands diff --git a/src/me/rockyhawk/commandpanels/session/floodgate/FloodgatePanel.java b/src/me/rockyhawk/commandpanels/session/floodgate/FloodgatePanel.java index 3da60eb..4d87175 100644 --- a/src/me/rockyhawk/commandpanels/session/floodgate/FloodgatePanel.java +++ b/src/me/rockyhawk/commandpanels/session/floodgate/FloodgatePanel.java @@ -54,7 +54,10 @@ public class FloodgatePanel extends Panel { } if(isNewPanelSession) { - // Update panel data values + // Don't open same panel if its already open + if(!canOpen(player, ctx)){ + return; + } updatePanelData(ctx, player); // Run panel commands diff --git a/src/me/rockyhawk/commandpanels/session/inventory/InventoryPanel.java b/src/me/rockyhawk/commandpanels/session/inventory/InventoryPanel.java index ae454ee..bbf4c52 100644 --- a/src/me/rockyhawk/commandpanels/session/inventory/InventoryPanel.java +++ b/src/me/rockyhawk/commandpanels/session/inventory/InventoryPanel.java @@ -67,7 +67,7 @@ public class InventoryPanel extends Panel implements InventoryHolder { if(isNewPanelSession) { // Don't open same panel if its already open - if(checkCurrentPanel(player)){ + if(!canOpen(player, ctx)){ return; } updatePanelData(ctx, player); @@ -88,14 +88,6 @@ public class InventoryPanel extends Panel implements InventoryHolder { } } - // Do not open the same panel again if its already open - private boolean checkCurrentPanel(Player p) { - if(p.getOpenInventory().getTopInventory().getHolder() instanceof InventoryPanel panel){ - return panel.getName().equals(getName()); - } - return false; - } - public String getRows() { return rows; } diff --git a/src/me/rockyhawk/commandpanels/session/inventory/InventoryPanelUpdater.java b/src/me/rockyhawk/commandpanels/session/inventory/InventoryPanelUpdater.java index 1202c9f..15ced9d 100644 --- a/src/me/rockyhawk/commandpanels/session/inventory/InventoryPanelUpdater.java +++ b/src/me/rockyhawk/commandpanels/session/inventory/InventoryPanelUpdater.java @@ -15,34 +15,39 @@ import org.bukkit.persistence.PersistentDataType; public class InventoryPanelUpdater { - private ScheduledTask task; + private ScheduledTask checkTask; + private ScheduledTask updateTask; + + /** + * Panel updater will maintain itself with a checkTask that will end the updater + * If it finds the panel has been closed it will end the updater tasks + */ public void start(Context ctx, Player p, InventoryPanel panel) { - // If restarted, stop current event + // Stop existing tasks if any stop(); - InventoryPanelBuilder panelBuilder = new InventoryPanelBuilder(ctx, p); - ItemBuilder builder = new ItemBuilder(ctx, panelBuilder); - + // Determine update delay (same as your original logic) int updateDelay = 20; if (panel.getUpdateDelay().matches("\\d+")) { - // Update delay value is a number updateDelay = Integer.parseInt(panel.getUpdateDelay()); } // If update delay is 0 then do not run the updater if (updateDelay == 0) { - this.task = null; + this.updateTask = null; return; } - // Schedule repeating GUI update task on the player's region - this.task = Bukkit.getRegionScheduler().runAtFixedRate( + InventoryPanelBuilder panelBuilder = new InventoryPanelBuilder(ctx, p); + ItemBuilder builder = new ItemBuilder(ctx, panelBuilder); + + // Main update task + this.updateTask = Bukkit.getRegionScheduler().runAtFixedRate( ctx.plugin, p.getLocation(), (scheduledTask) -> { Inventory inv = p.getOpenInventory().getTopInventory(); - InventoryHolder holder = inv.getHolder(); if (!(holder instanceof InventoryPanel) || holder != panel) { stop(); @@ -88,12 +93,32 @@ public class InventoryPanelUpdater { updateDelay, updateDelay ); + + // Fast check task + this.checkTask = Bukkit.getRegionScheduler().runAtFixedRate( + ctx.plugin, + p.getLocation(), + (scheduledTask) -> { + Inventory inv = p.getOpenInventory().getTopInventory(); + InventoryHolder holder = inv.getHolder(); + + if (!(holder instanceof InventoryPanel) || holder != panel) { + stop(); + } + }, + 5, + 5 + ); } public void stop() { - if (task != null) { - task.cancel(); - task = null; + if (checkTask != null) { + checkTask.cancel(); + checkTask = null; + } + if (updateTask != null) { + updateTask.cancel(); + updateTask = null; } } }