From efe9a141bf0a748fe6902b80641583368cceeae9 Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Fri, 29 Nov 2024 02:48:43 +0200 Subject: [PATCH 1/6] prevent taking items from chest while POS GUI is open --- .../pro/cloudnode/smp/bankaccounts/POS.java | 14 +++++++++ .../smp/bankaccounts/events/GUI.java | 29 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/main/java/pro/cloudnode/smp/bankaccounts/POS.java b/src/main/java/pro/cloudnode/smp/bankaccounts/POS.java index b7f6c6f..4b1cae3 100644 --- a/src/main/java/pro/cloudnode/smp/bankaccounts/POS.java +++ b/src/main/java/pro/cloudnode/smp/bankaccounts/POS.java @@ -26,6 +26,7 @@ import java.util.Arrays; import java.util.Comparator; import java.util.Date; +import java.util.HashMap; import java.util.Objects; import java.util.Optional; import java.util.UUID; @@ -66,6 +67,8 @@ public final class POS { */ public final @NotNull Date created; + public final static @NotNull HashMap<@NotNull Inventory, @NotNull POS> activePosChestGuis = new HashMap<>(); + /** * Create new POS instance * @@ -118,6 +121,15 @@ public POS(final @NotNull ResultSet rs) throws @NotNull SQLException, @NotNull I return getLocation().getBlock(); } + /** + * Get POS chest + */ + public @Nullable Chest getChest() { + if (getBlock().getState() instanceof final @NotNull Chest chest) return chest; + delete(); + return null; + } + /** * Create POS id */ @@ -263,6 +275,7 @@ public static void openOwnerGui(final @NotNull Player player, final @NotNull Che final int extraRows = 1; final int size = extraRows * 9 + items.length + 9 - items.length % 9; final @NotNull Inventory gui = BankAccounts.getInstance().getServer().createInventory(null, size, BankAccounts.getInstance().config().posTitle(pos)); + POS.activePosChestGuis.put(gui, pos); gui.addItem(items); final @NotNull ItemStack overview = new ItemStack(BankAccounts.getInstance().config().posInfoMaterial(), 1); @@ -308,6 +321,7 @@ public static void openBuyGui(final @NotNull Player player, final @NotNull Chest final int extraRows = 1; final int size = extraRows * 9 + items.length + 9 - items.length % 9; final @NotNull Inventory gui = BankAccounts.getInstance().getServer().createInventory(null, size, BankAccounts.getInstance().config().posTitle(pos)); + POS.activePosChestGuis.put(gui, pos); gui.addItem(items); final @NotNull ItemStack overview = new ItemStack(BankAccounts.getInstance().config().posInfoMaterial(), 1); diff --git a/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java b/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java index de2636a..6231f69 100644 --- a/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java +++ b/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java @@ -5,10 +5,13 @@ import org.bukkit.block.Chest; import org.bukkit.entity.Player; 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.InventoryMoveItemEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.persistence.PersistentDataContainer; @@ -152,6 +155,32 @@ public void onInventoryClick(final @NotNull InventoryDragEvent event) { event.setCancelled(true); } + /** + * Detect changes in items of POS chest while a POS GUI is opened and prevent the item change. + * POS items can still be modified if no POS GUI is opened for that POS. + */ + @EventHandler(priority = EventPriority.HIGHEST) + public void posItemsChangeWhileOpened(final @NotNull InventoryMoveItemEvent event) { + final @NotNull Inventory inventory = event.getSource(); + for (final @NotNull POS pos : POS.activePosChestGuis.values()) { + final @Nullable Chest chest = pos.getChest(); + if (chest == null) continue; + if (inventory.equals(chest.getInventory())) { + event.setCancelled(true); + return; + } + } + } + + /** + * POS GUI closed + */ + @EventHandler + public void posGuiClosed(final @NotNull InventoryCloseEvent event) { + if (!POS.activePosChestGuis.containsKey(event.getInventory())) return; + POS.activePosChestGuis.remove(event.getInventory()); + } + public final static @NotNull HashMap<@NotNull String, @NotNull NamespacedKey[]> keys = new HashMap<>() {{ put("pos-owner", new NamespacedKey[]{BankAccounts.Key.POS_OWNER_GUI}); put("pos-buyer", new NamespacedKey[]{BankAccounts.Key.POS_BUYER_GUI_CONFIRM, BankAccounts.Key.POS_BUYER_GUI, BankAccounts.Key.POS_BUYER_GUI_CANCEL}); From ab897d9f120e2a66c66c583b739c41948bff649d Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Fri, 29 Nov 2024 03:28:15 +0200 Subject: [PATCH 2/6] also prevent adding items to opened POS --- .../java/pro/cloudnode/smp/bankaccounts/events/GUI.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java b/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java index 6231f69..3e91974 100644 --- a/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java +++ b/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java @@ -161,11 +161,13 @@ public void onInventoryClick(final @NotNull InventoryDragEvent event) { */ @EventHandler(priority = EventPriority.HIGHEST) public void posItemsChangeWhileOpened(final @NotNull InventoryMoveItemEvent event) { - final @NotNull Inventory inventory = event.getSource(); + final @NotNull Inventory source = event.getSource(); + final @NotNull Inventory destination = event.getDestination(); for (final @NotNull POS pos : POS.activePosChestGuis.values()) { final @Nullable Chest chest = pos.getChest(); if (chest == null) continue; - if (inventory.equals(chest.getInventory())) { + final @NotNull Inventory chestInventory = chest.getInventory(); + if (source.equals(chestInventory) || destination.equals(chestInventory)) { event.setCancelled(true); return; } From bf68327fba3859591863b65c6da7b253cb88ca34 Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Fri, 29 Nov 2024 03:28:29 +0200 Subject: [PATCH 3/6] POS item move event: ignore handler if cancelled --- src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java b/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java index 3e91974..87753f8 100644 --- a/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java +++ b/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java @@ -159,7 +159,7 @@ public void onInventoryClick(final @NotNull InventoryDragEvent event) { * Detect changes in items of POS chest while a POS GUI is opened and prevent the item change. * POS items can still be modified if no POS GUI is opened for that POS. */ - @EventHandler(priority = EventPriority.HIGHEST) + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void posItemsChangeWhileOpened(final @NotNull InventoryMoveItemEvent event) { final @NotNull Inventory source = event.getSource(); final @NotNull Inventory destination = event.getDestination(); From 4a0a63e77243f62d978eed1e4f98f2fe2d5afff5 Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Sat, 30 Nov 2024 14:11:34 +0200 Subject: [PATCH 4/6] wait 2s before removing closed POS GUI from the active GUIs cache --- src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java b/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java index 87753f8..f2db9eb 100644 --- a/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java +++ b/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java @@ -180,7 +180,9 @@ public void posItemsChangeWhileOpened(final @NotNull InventoryMoveItemEvent even @EventHandler public void posGuiClosed(final @NotNull InventoryCloseEvent event) { if (!POS.activePosChestGuis.containsKey(event.getInventory())) return; - POS.activePosChestGuis.remove(event.getInventory()); + BankAccounts.getInstance().getServer().getScheduler().runTaskLater(BankAccounts.getInstance(), () -> { + POS.activePosChestGuis.remove(event.getInventory()); + }, 40L); } public final static @NotNull HashMap<@NotNull String, @NotNull NamespacedKey[]> keys = new HashMap<>() {{ From 824a8dfa02f8607504f80427bdb6b7cfa1d98580 Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Sat, 30 Nov 2024 14:24:44 +0200 Subject: [PATCH 5/6] Revert "wait 2s before removing closed POS GUI from the active GUIs cache" This reverts commit 4a0a63e77243f62d978eed1e4f98f2fe2d5afff5. --- src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java b/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java index f2db9eb..87753f8 100644 --- a/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java +++ b/src/main/java/pro/cloudnode/smp/bankaccounts/events/GUI.java @@ -180,9 +180,7 @@ public void posItemsChangeWhileOpened(final @NotNull InventoryMoveItemEvent even @EventHandler public void posGuiClosed(final @NotNull InventoryCloseEvent event) { if (!POS.activePosChestGuis.containsKey(event.getInventory())) return; - BankAccounts.getInstance().getServer().getScheduler().runTaskLater(BankAccounts.getInstance(), () -> { - POS.activePosChestGuis.remove(event.getInventory()); - }, 40L); + POS.activePosChestGuis.remove(event.getInventory()); } public final static @NotNull HashMap<@NotNull String, @NotNull NamespacedKey[]> keys = new HashMap<>() {{ From 3e43e2e8385388319b4502700ef7a18dbea1c45b Mon Sep 17 00:00:00 2001 From: Zefir Kirilov Date: Sat, 30 Nov 2024 14:26:02 +0200 Subject: [PATCH 6/6] clone item stacks before adding to preview GUI --- src/main/java/pro/cloudnode/smp/bankaccounts/POS.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/pro/cloudnode/smp/bankaccounts/POS.java b/src/main/java/pro/cloudnode/smp/bankaccounts/POS.java index 4b1cae3..ac68717 100644 --- a/src/main/java/pro/cloudnode/smp/bankaccounts/POS.java +++ b/src/main/java/pro/cloudnode/smp/bankaccounts/POS.java @@ -271,7 +271,7 @@ public void delete() { * @param pos The POS */ public static void openOwnerGui(final @NotNull Player player, final @NotNull Chest chest, final @NotNull POS pos) { - final @NotNull ItemStack @NotNull [] items = Arrays.stream(chest.getInventory().getStorageContents()).filter(Objects::nonNull).toArray(ItemStack[]::new); + final @NotNull ItemStack @NotNull [] items = Arrays.stream(chest.getInventory().getStorageContents()).filter(Objects::nonNull).map(ItemStack::clone).toArray(ItemStack[]::new); final int extraRows = 1; final int size = extraRows * 9 + items.length + 9 - items.length % 9; final @NotNull Inventory gui = BankAccounts.getInstance().getServer().createInventory(null, size, BankAccounts.getInstance().config().posTitle(pos)); @@ -317,7 +317,7 @@ public static void openOwnerGui(final @NotNull Player player, final @NotNull Che * @param pos The POS */ public static void openBuyGui(final @NotNull Player player, final @NotNull Chest chest, final @NotNull POS pos, final @NotNull Account account) { - final @NotNull ItemStack @NotNull [] items = Arrays.stream(chest.getInventory().getStorageContents()).filter(Objects::nonNull).toArray(ItemStack[]::new); + final @NotNull ItemStack @NotNull [] items = Arrays.stream(chest.getInventory().getStorageContents()).filter(Objects::nonNull).map(ItemStack::clone).toArray(ItemStack[]::new); final int extraRows = 1; final int size = extraRows * 9 + items.length + 9 - items.length % 9; final @NotNull Inventory gui = BankAccounts.getInstance().getServer().createInventory(null, size, BankAccounts.getInstance().config().posTitle(pos));