diff --git a/src/main/java/de/studiocode/invui/gui/impl/IndexedGUI.java b/src/main/java/de/studiocode/invui/gui/impl/IndexedGUI.java index 3fdfe25..1f99b8b 100644 --- a/src/main/java/de/studiocode/invui/gui/impl/IndexedGUI.java +++ b/src/main/java/de/studiocode/invui/gui/impl/IndexedGUI.java @@ -13,6 +13,9 @@ import de.studiocode.invui.util.ArrayUtils; import de.studiocode.invui.virtualinventory.VirtualInventory; import de.studiocode.invui.virtualinventory.event.ItemUpdateEvent; import de.studiocode.invui.window.Window; +import de.studiocode.invui.window.WindowManager; +import de.studiocode.invui.window.impl.merged.combined.CombinedWindow; +import de.studiocode.invui.window.impl.merged.split.SplitWindow; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; @@ -107,6 +110,8 @@ abstract class IndexedGUI implements GUI { case MOVE_TO_OTHER_INVENTORY: event.setCancelled(true); + Window window = WindowManager.getInstance().findOpenWindow(player).orElse(null); + if (window instanceof CombinedWindow) break; // can't move if there is no other gui ItemStack invStack = virtualInventory.getItemStack(index); ItemUpdateEvent updateEvent = new ItemUpdateEvent(virtualInventory, player, invStack, @@ -114,12 +119,18 @@ abstract class IndexedGUI implements GUI { Bukkit.getPluginManager().callEvent(updateEvent); if (!updateEvent.isCancelled()) { - int leftOverAmount = 0; - HashMap leftover = - event.getWhoClicked().getInventory().addItem(virtualInventory.getItemStack(index)); - - if (!leftover.isEmpty()) leftOverAmount = leftover.get(0).getAmount(); - + int leftOverAmount; + if (window instanceof SplitWindow) { + SplitWindow splitWindow = (SplitWindow) window; + GUI[] guis = splitWindow.getGuis(); + GUI otherGui = guis[0] == this ? guis[1] : guis[0]; + + leftOverAmount = ((IndexedGUI) otherGui).putIntoVirtualInventories(player, invStack, virtualInventory); + } else { + leftOverAmount = 0; + HashMap leftover = event.getWhoClicked().getInventory().addItem(virtualInventory.getItemStack(index)); + if (!leftover.isEmpty()) leftOverAmount = leftover.get(0).getAmount(); + } virtualInventory.setAmountSilently(index, leftOverAmount); } @@ -144,29 +155,41 @@ abstract class IndexedGUI implements GUI { Player player = (Player) event.getWhoClicked(); ItemStack clicked = event.getCurrentItem(); - List virtualInventories = getAllVirtualInventories(); - if (virtualInventories.size() > 0) { - int amountLeft = clicked.getAmount(); - for (VirtualInventory virtualInventory : virtualInventories) { - ItemStack toAdd = clicked.clone(); - toAdd.setAmount(amountLeft); - amountLeft = virtualInventory.addItem(player, toAdd); - - if (amountLeft == 0) break; - } - + int amountLeft = putIntoVirtualInventories(player, clicked); + if (amountLeft != clicked.getAmount()) { if (amountLeft != 0) event.getCurrentItem().setAmount(amountLeft); else event.getClickedInventory().setItem(event.getSlot(), null); } } - private List getAllVirtualInventories() { + private int putIntoVirtualInventories(Player player, ItemStack itemStack, VirtualInventory... ignored) { + if (itemStack.getAmount() <= 0) throw new IllegalArgumentException("Illegal ItemStack amount"); + + List virtualInventories = getAllVirtualInventories(ignored); + if (virtualInventories.size() > 0) { + int amountLeft = itemStack.getAmount(); + for (VirtualInventory virtualInventory : virtualInventories) { + ItemStack toAdd = itemStack.clone(); + toAdd.setAmount(amountLeft); + amountLeft = virtualInventory.addItem(player, toAdd); + + if (amountLeft == 0) break; + } + + return amountLeft; + } + + return itemStack.getAmount(); + } + + private List getAllVirtualInventories(VirtualInventory... ignored) { List virtualInventories = new ArrayList<>(); Arrays.stream(slotElements) .filter(Objects::nonNull) .map(SlotElement::getItemStackHolder) .filter(holder -> holder instanceof VISlotElement) .map(holder -> ((VISlotElement) holder).getVirtualInventory()) + .filter(vi -> Arrays.stream(ignored).noneMatch(vi::equals)) .forEach(vi -> { if (!virtualInventories.contains(vi)) virtualInventories.add(vi); }); diff --git a/src/main/java/de/studiocode/invui/window/impl/merged/MergedWindow.java b/src/main/java/de/studiocode/invui/window/impl/merged/MergedWindow.java index d5795f1..1159fb3 100644 --- a/src/main/java/de/studiocode/invui/window/impl/merged/MergedWindow.java +++ b/src/main/java/de/studiocode/invui/window/impl/merged/MergedWindow.java @@ -1,7 +1,8 @@ package de.studiocode.invui.window.impl.merged; +import de.studiocode.invui.gui.GUI; import de.studiocode.invui.gui.SlotElement.ItemStackHolder; -import de.studiocode.invui.gui.SlotElement.VISlotElement; +import de.studiocode.invui.util.Pair; import de.studiocode.invui.util.SlotUtils; import de.studiocode.invui.window.Window; import de.studiocode.invui.window.impl.BaseWindow; @@ -62,9 +63,6 @@ public abstract class MergedWindow extends BaseWindow { @Override protected void redrawItem(int index, ItemStackHolder holder, boolean setItem) { - if (holder instanceof VISlotElement) - throw new IllegalArgumentException("VirtualInventories are not allowed in CombinedWindows"); - super.redrawItem(index, holder, setItem); if (getViewer() != null) getViewer().updateInventory(); // fixes a bug where some items wouldn't be displayed correctly @@ -114,9 +112,15 @@ public abstract class MergedWindow extends BaseWindow { restorePlayerInventory(); } + @Override + public void handleClick(InventoryClickEvent event) { + Pair clicked = getWhereClicked(event); + clicked.getFirst().handleClick(clicked.getSecond(), (Player) event.getWhoClicked(), event.getClick(), event); + } + @Override public void handleItemShift(InventoryClickEvent event) { - event.setCancelled(true); + // empty } @Override @@ -134,4 +138,6 @@ public abstract class MergedWindow extends BaseWindow { protected abstract ItemStackHolder getItemStackHolder(int index); + protected abstract Pair getWhereClicked(InventoryClickEvent event); + } diff --git a/src/main/java/de/studiocode/invui/window/impl/merged/combined/CombinedWindow.java b/src/main/java/de/studiocode/invui/window/impl/merged/combined/CombinedWindow.java index a844c87..11f07e0 100644 --- a/src/main/java/de/studiocode/invui/window/impl/merged/combined/CombinedWindow.java +++ b/src/main/java/de/studiocode/invui/window/impl/merged/combined/CombinedWindow.java @@ -2,6 +2,7 @@ package de.studiocode.invui.window.impl.merged.combined; import de.studiocode.invui.gui.GUI; import de.studiocode.invui.gui.SlotElement.ItemStackHolder; +import de.studiocode.invui.util.Pair; import de.studiocode.invui.util.SlotUtils; import de.studiocode.invui.window.Window; import de.studiocode.invui.window.impl.merged.MergedWindow; @@ -30,17 +31,17 @@ public abstract class CombinedWindow extends MergedWindow { } @Override - public void handleClick(InventoryClickEvent event) { - Inventory clicked = event.getClickedInventory(); - int guiSlot = clicked == getUpperInventory() ? event.getSlot() - : getUpperInventory().getSize() + SlotUtils.translatePlayerInvToGui(event.getSlot()); - - gui.handleClick(guiSlot, (Player) event.getWhoClicked(), event.getClick(), event); + protected ItemStackHolder getItemStackHolder(int index) { + return gui.getItemStackHolder(index); } @Override - protected ItemStackHolder getItemStackHolder(int index) { - return gui.getItemStackHolder(index); + protected Pair getWhereClicked(InventoryClickEvent event) { + Inventory clicked = event.getClickedInventory(); + int slot = event.getSlot(); + int clickedIndex = clicked == getUpperInventory() ? slot + : getUpperInventory().getSize() + SlotUtils.translatePlayerInvToGui(slot); + return new Pair<>(gui, clickedIndex); } @Override diff --git a/src/main/java/de/studiocode/invui/window/impl/merged/split/SplitWindow.java b/src/main/java/de/studiocode/invui/window/impl/merged/split/SplitWindow.java index c16d911..857df45 100644 --- a/src/main/java/de/studiocode/invui/window/impl/merged/split/SplitWindow.java +++ b/src/main/java/de/studiocode/invui/window/impl/merged/split/SplitWindow.java @@ -2,6 +2,7 @@ package de.studiocode.invui.window.impl.merged.split; import de.studiocode.invui.gui.GUI; import de.studiocode.invui.gui.SlotElement.ItemStackHolder; +import de.studiocode.invui.util.Pair; import de.studiocode.invui.util.SlotUtils; import de.studiocode.invui.window.Window; import de.studiocode.invui.window.impl.merged.MergedWindow; @@ -33,23 +34,23 @@ public abstract class SplitWindow extends MergedWindow { child.getItemStackHolder(slotIndex), true); } - @Override - public void handleClick(InventoryClickEvent event) { - Inventory clicked = event.getClickedInventory(); - if (clicked == getUpperInventory()) { - upperGui.handleClick(event.getSlot(), (Player) event.getWhoClicked(), event.getClick(), event); - } else { - int index = SlotUtils.translatePlayerInvToGui(event.getSlot()); - lowerGui.handleClick(index, (Player) event.getWhoClicked(), event.getClick(), event); - } - } - @Override public ItemStackHolder getItemStackHolder(int index) { if (index >= upperGui.getSize()) return lowerGui.getItemStackHolder(index - upperGui.getSize()); else return upperGui.getItemStackHolder(index); } + @Override + protected Pair getWhereClicked(InventoryClickEvent event) { + Inventory clicked = event.getClickedInventory(); + if (clicked == getUpperInventory()) { + return new Pair<>(upperGui, event.getSlot()); + } else { + int index = SlotUtils.translatePlayerInvToGui(event.getSlot()); + return new Pair<>(lowerGui, index); + } + } + @Override public GUI[] getGuis() { return new GUI[] {upperGui, lowerGui};