Skip to content

Commit 354d3b3

Browse files
authored
Merge pull request #286
Fix GUI Item Input Buttons deleting stacks on certain interactions
2 parents 47db9ff + d8c4aab commit 354d3b3

2 files changed

Lines changed: 35 additions & 2 deletions

File tree

src/main/java/me/wolfyscript/customcrafting/gui/InteractionUtils.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,23 @@
2424

2525
import java.util.Objects;
2626
import java.util.Set;
27+
import java.util.WeakHashMap;
2728
import java.util.function.Consumer;
2829
import java.util.function.Function;
2930
import me.wolfyscript.customcrafting.CustomCrafting;
3031
import me.wolfyscript.utilities.util.inventory.ItemUtils;
3132
import org.bukkit.Bukkit;
33+
import org.bukkit.event.inventory.InventoryAction;
3234
import org.bukkit.event.inventory.InventoryClickEvent;
3335
import org.bukkit.event.inventory.InventoryDragEvent;
36+
import org.bukkit.event.inventory.InventoryEvent;
3437
import org.bukkit.event.inventory.InventoryInteractEvent;
3538
import org.bukkit.inventory.ItemStack;
3639

3740
public class InteractionUtils {
3841

42+
private static final WeakHashMap<InventoryEvent, Integer> CACHE_COLLECT_TO_CURSOR = new WeakHashMap<>();
43+
3944
/**
4045
* Used to apply ItemStack changes from the InventoryInteractEvent.
4146
*
@@ -64,6 +69,14 @@ public static boolean applyItemFromInteractionEvent(int clickedSlot, InventoryIn
6469
// Cancel the event when trying to shift-click the items from the bottom to the top inventory.
6570
return true;
6671
}
72+
/*
73+
* # issue: WolfyUtils calls all the ItemInputButtons on Shift-interaction,
74+
* we need to only update the clicked slot when moving stack into bottom inventory,
75+
* but still update all when stacks are moved into the GUI (top inventory), due to non-deterministic stack placement!
76+
*/
77+
if (clickEvent.getAction().equals(InventoryAction.MOVE_TO_OTHER_INVENTORY) && Objects.equals(clickEvent.getClickedInventory(), event.getView().getTopInventory()) && clickedSlot != clickEvent.getSlot()) {
78+
return false; // The event should not be cancelled yet.
79+
}
6780
applyItemStack.accept(current);
6881
}
6982
// Other than the PICKUP_ALL, DROP_ALL is not called when there is only 1 item.
@@ -91,8 +104,28 @@ public static boolean applyItemFromInteractionEvent(int clickedSlot, InventoryIn
91104
}
92105
// All these actions will keep remaining items in the slot, so lets just use the current stack.
93106
// The stack will be updated, as it is a reference to the stack in the inventory.
94-
case PICKUP_ONE, PICKUP_SOME, COLLECT_TO_CURSOR, DROP_ALL_CURSOR ->
107+
case PICKUP_ONE, PICKUP_SOME, DROP_ALL_CURSOR -> applyItemStack.accept(clickEvent.getCurrentItem());
108+
case COLLECT_TO_CURSOR -> {
109+
/*
110+
* # issue: We need to determine which slots are cleared completely and which slots
111+
* are updated, because there are remaining items.
112+
* So we need to keep track of the collected amount to figure that out, since Spigot has no API for that.
113+
* This requires WolfyUtils v4.16.12 to properly function.
114+
*/
115+
if (clickedSlot == clickEvent.getSlot()) {
116+
CACHE_COLLECT_TO_CURSOR.put(event, clickEvent.getCursor().getAmount());
95117
applyItemStack.accept(clickEvent.getCurrentItem());
118+
break;
119+
}
120+
ItemStack item = clickEvent.getClickedInventory().getItem(clickedSlot);
121+
if (item == null) break;
122+
int total = CACHE_COLLECT_TO_CURSOR.compute(event, (inventoryEvent, count) -> count == null ? item.getAmount() : (count + item.getAmount()));
123+
if (total > clickEvent.getCursor().getMaxStackSize()) {
124+
applyItemStack.accept(clickEvent.getClickedInventory().getItem(clickedSlot));
125+
break;
126+
}
127+
applyItemStack.accept(null);
128+
}
96129
// Hotbar swaps work all the same, so lets take the hotbar stack.
97130
case HOTBAR_SWAP, HOTBAR_MOVE_AND_READD ->
98131
applyItemStack.accept(event.getWhoClicked().getInventory().getItem(clickEvent.getHotbarButton()));

src/main/java/me/wolfyscript/customcrafting/gui/elite_crafting/ButtonSlotResult.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class ButtonSlotResult extends ItemInputButton<CCCache> {
4444
super("result_slot", new ButtonState<>("", Material.AIR, (cache, guiHandler, player, inventory, slot, event) -> {
4545
CacheEliteCraftingTable cacheEliteCraftingTable = cache.getEliteWorkbench();
4646
if (event instanceof InventoryClickEvent clickEvent && inventory.getWindow() instanceof CraftingWindow) {
47-
if (!CraftingWindow.RESULT_SLOTS.contains(slot)) {
47+
if (!CraftingWindow.RESULT_SLOTS.contains(slot) || slot != clickEvent.getSlot()) { // # issue: We don't want to cause a recipe consumption when the result button wasn't actually clicked!
4848
return true;
4949
}
5050
if (clickEvent.getAction().equals(InventoryAction.MOVE_TO_OTHER_INVENTORY) && event.getView().getBottomInventory().equals(clickEvent.getClickedInventory())) {

0 commit comments

Comments
 (0)