From 30455aaacbb814d887259b3f3f985c29f7dc9fba Mon Sep 17 00:00:00 2001 From: APickledWalrus Date: Fri, 20 Aug 2021 21:17:14 -0400 Subject: [PATCH] Improve event handling This fixes some regressions that occurred, mainly issues with GUI items being able to be stolen through certain click types/actions. It also allows the user to perform certain actions that would normally be blocked if the GUI would allow such changes to it to be made. See the documentation within these changes for specific details. --- .../skriptgui/gui/events/GUIEvents.java | 52 +++++++++++++++++-- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/src/main/java/io/github/apickledwalrus/skriptgui/gui/events/GUIEvents.java b/src/main/java/io/github/apickledwalrus/skriptgui/gui/events/GUIEvents.java index 1dec8ed..2cf631c 100644 --- a/src/main/java/io/github/apickledwalrus/skriptgui/gui/events/GUIEvents.java +++ b/src/main/java/io/github/apickledwalrus/skriptgui/gui/events/GUIEvents.java @@ -3,15 +3,16 @@ import ch.njol.skript.SkriptEventHandler; import io.github.apickledwalrus.skriptgui.SkriptGUI; import io.github.apickledwalrus.skriptgui.gui.GUI; -import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; +import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.inventory.InventoryDragEvent; import org.bukkit.event.inventory.InventoryOpenEvent; import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; public class GUIEvents implements Listener { @@ -27,16 +28,15 @@ public GUIEvents() { public void onInventoryClick(InventoryClickEvent event) { // Don't handle this event if it's from an unsupported click type switch (event.getClick()) { - case UNKNOWN: case WINDOW_BORDER_RIGHT: case WINDOW_BORDER_LEFT: case CREATIVE: return; } - // Don't handle this event if the clicked inventory is the bottom inventory + // No inventory was clicked Inventory clickedInventory = event.getClickedInventory(); - if (clickedInventory == null || clickedInventory.equals(event.getView().getBottomInventory())) { + if (clickedInventory == null) { return; } @@ -46,6 +46,41 @@ public void onInventoryClick(InventoryClickEvent event) { return; } + // Don't process unknown clicks for safety reasons - cancel them to prevent unwanted GUI changes + if (event.getClick() == ClickType.UNKNOWN) { + event.setCancelled(true); + return; + } + + // Don't handle this event if the clicked inventory is the bottom inventory, as we want users to be able to interact with their inventory + // However, there are some cases where interaction with the bottom inventory may cause changes to the top inventory + // Because of this, we will cancel the event for some click types + if (clickedInventory.equals(event.getView().getBottomInventory())) { + switch (event.getClick()) { + case SHIFT_LEFT: + case SHIFT_RIGHT: + event.setCancelled(true); + return; + case DOUBLE_CLICK: + // Only cancel if this will cause a change to the GUI itself + // We are checking if our GUI contains an item that could be merged with the event item + // If that item is mergeable but it isn't stealable, we will cancel the event now + Inventory guiInventory = gui.getInventory(); + int size = guiInventory.getSize(); + ItemStack cursor = event.getWhoClicked().getItemOnCursor(); + for (int slot = 0; slot < size; slot++) { + ItemStack item = guiInventory.getItem(slot); + if (item != null && item.isSimilar(cursor) && !gui.isStealable(gui.convert(slot))) { + event.setCancelled(true); + break; + } + } + return; + default: + return; + } + } + gui.getEventHandler().onClick(event); } @@ -53,7 +88,14 @@ public void onInventoryClick(InventoryClickEvent event) { public void onInventoryDrag(InventoryDragEvent e) { GUI gui = SkriptGUI.getGUIManager().getGUI(e.getInventory()); if (gui != null) { - gui.getEventHandler().onDrag(e); + // Check if any slots in the actual GUI were changed. We don't care if only the player's inventory was changed. + int lastSlotIndex = gui.getInventory().getSize() - 1; + for (int slot : e.getRawSlots()) { + if (slot <= lastSlotIndex) { // A slot in the actual GUI was interacted with + gui.getEventHandler().onDrag(e); + break; + } + } } }