VirtualInventories in MergedWindow

This commit is contained in:
NichtStudioCode 2021-02-08 20:26:38 +01:00
parent 951178f161
commit 7335ae86de
4 changed files with 73 additions and 42 deletions

@ -13,6 +13,9 @@ import de.studiocode.invui.util.ArrayUtils;
import de.studiocode.invui.virtualinventory.VirtualInventory; import de.studiocode.invui.virtualinventory.VirtualInventory;
import de.studiocode.invui.virtualinventory.event.ItemUpdateEvent; import de.studiocode.invui.virtualinventory.event.ItemUpdateEvent;
import de.studiocode.invui.window.Window; 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.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.ClickType;
@ -107,6 +110,8 @@ abstract class IndexedGUI implements GUI {
case MOVE_TO_OTHER_INVENTORY: case MOVE_TO_OTHER_INVENTORY:
event.setCancelled(true); 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); ItemStack invStack = virtualInventory.getItemStack(index);
ItemUpdateEvent updateEvent = new ItemUpdateEvent(virtualInventory, player, invStack, ItemUpdateEvent updateEvent = new ItemUpdateEvent(virtualInventory, player, invStack,
@ -114,12 +119,18 @@ abstract class IndexedGUI implements GUI {
Bukkit.getPluginManager().callEvent(updateEvent); Bukkit.getPluginManager().callEvent(updateEvent);
if (!updateEvent.isCancelled()) { if (!updateEvent.isCancelled()) {
int leftOverAmount = 0; int leftOverAmount;
HashMap<Integer, ItemStack> leftover = if (window instanceof SplitWindow) {
event.getWhoClicked().getInventory().addItem(virtualInventory.getItemStack(index)); SplitWindow splitWindow = (SplitWindow) window;
GUI[] guis = splitWindow.getGuis();
if (!leftover.isEmpty()) leftOverAmount = leftover.get(0).getAmount(); GUI otherGui = guis[0] == this ? guis[1] : guis[0];
leftOverAmount = ((IndexedGUI) otherGui).putIntoVirtualInventories(player, invStack, virtualInventory);
} else {
leftOverAmount = 0;
HashMap<Integer, ItemStack> leftover = event.getWhoClicked().getInventory().addItem(virtualInventory.getItemStack(index));
if (!leftover.isEmpty()) leftOverAmount = leftover.get(0).getAmount();
}
virtualInventory.setAmountSilently(index, leftOverAmount); virtualInventory.setAmountSilently(index, leftOverAmount);
} }
@ -144,29 +155,41 @@ abstract class IndexedGUI implements GUI {
Player player = (Player) event.getWhoClicked(); Player player = (Player) event.getWhoClicked();
ItemStack clicked = event.getCurrentItem(); ItemStack clicked = event.getCurrentItem();
List<VirtualInventory> virtualInventories = getAllVirtualInventories(); int amountLeft = putIntoVirtualInventories(player, clicked);
if (amountLeft != clicked.getAmount()) {
if (amountLeft != 0) event.getCurrentItem().setAmount(amountLeft);
else event.getClickedInventory().setItem(event.getSlot(), null);
}
}
private int putIntoVirtualInventories(Player player, ItemStack itemStack, VirtualInventory... ignored) {
if (itemStack.getAmount() <= 0) throw new IllegalArgumentException("Illegal ItemStack amount");
List<VirtualInventory> virtualInventories = getAllVirtualInventories(ignored);
if (virtualInventories.size() > 0) { if (virtualInventories.size() > 0) {
int amountLeft = clicked.getAmount(); int amountLeft = itemStack.getAmount();
for (VirtualInventory virtualInventory : virtualInventories) { for (VirtualInventory virtualInventory : virtualInventories) {
ItemStack toAdd = clicked.clone(); ItemStack toAdd = itemStack.clone();
toAdd.setAmount(amountLeft); toAdd.setAmount(amountLeft);
amountLeft = virtualInventory.addItem(player, toAdd); amountLeft = virtualInventory.addItem(player, toAdd);
if (amountLeft == 0) break; if (amountLeft == 0) break;
} }
if (amountLeft != 0) event.getCurrentItem().setAmount(amountLeft); return amountLeft;
else event.getClickedInventory().setItem(event.getSlot(), null);
} }
return itemStack.getAmount();
} }
private List<VirtualInventory> getAllVirtualInventories() { private List<VirtualInventory> getAllVirtualInventories(VirtualInventory... ignored) {
List<VirtualInventory> virtualInventories = new ArrayList<>(); List<VirtualInventory> virtualInventories = new ArrayList<>();
Arrays.stream(slotElements) Arrays.stream(slotElements)
.filter(Objects::nonNull) .filter(Objects::nonNull)
.map(SlotElement::getItemStackHolder) .map(SlotElement::getItemStackHolder)
.filter(holder -> holder instanceof VISlotElement) .filter(holder -> holder instanceof VISlotElement)
.map(holder -> ((VISlotElement) holder).getVirtualInventory()) .map(holder -> ((VISlotElement) holder).getVirtualInventory())
.filter(vi -> Arrays.stream(ignored).noneMatch(vi::equals))
.forEach(vi -> { .forEach(vi -> {
if (!virtualInventories.contains(vi)) virtualInventories.add(vi); if (!virtualInventories.contains(vi)) virtualInventories.add(vi);
}); });

@ -1,7 +1,8 @@
package de.studiocode.invui.window.impl.merged; 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.ItemStackHolder;
import de.studiocode.invui.gui.SlotElement.VISlotElement; import de.studiocode.invui.util.Pair;
import de.studiocode.invui.util.SlotUtils; import de.studiocode.invui.util.SlotUtils;
import de.studiocode.invui.window.Window; import de.studiocode.invui.window.Window;
import de.studiocode.invui.window.impl.BaseWindow; import de.studiocode.invui.window.impl.BaseWindow;
@ -62,9 +63,6 @@ public abstract class MergedWindow extends BaseWindow {
@Override @Override
protected void redrawItem(int index, ItemStackHolder holder, boolean setItem) { 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); super.redrawItem(index, holder, setItem);
if (getViewer() != null) if (getViewer() != null)
getViewer().updateInventory(); // fixes a bug where some items wouldn't be displayed correctly getViewer().updateInventory(); // fixes a bug where some items wouldn't be displayed correctly
@ -114,9 +112,15 @@ public abstract class MergedWindow extends BaseWindow {
restorePlayerInventory(); restorePlayerInventory();
} }
@Override
public void handleClick(InventoryClickEvent event) {
Pair<GUI, Integer> clicked = getWhereClicked(event);
clicked.getFirst().handleClick(clicked.getSecond(), (Player) event.getWhoClicked(), event.getClick(), event);
}
@Override @Override
public void handleItemShift(InventoryClickEvent event) { public void handleItemShift(InventoryClickEvent event) {
event.setCancelled(true); // empty
} }
@Override @Override
@ -134,4 +138,6 @@ public abstract class MergedWindow extends BaseWindow {
protected abstract ItemStackHolder getItemStackHolder(int index); protected abstract ItemStackHolder getItemStackHolder(int index);
protected abstract Pair<GUI, Integer> getWhereClicked(InventoryClickEvent event);
} }

@ -2,6 +2,7 @@ package de.studiocode.invui.window.impl.merged.combined;
import de.studiocode.invui.gui.GUI; import de.studiocode.invui.gui.GUI;
import de.studiocode.invui.gui.SlotElement.ItemStackHolder; import de.studiocode.invui.gui.SlotElement.ItemStackHolder;
import de.studiocode.invui.util.Pair;
import de.studiocode.invui.util.SlotUtils; import de.studiocode.invui.util.SlotUtils;
import de.studiocode.invui.window.Window; import de.studiocode.invui.window.Window;
import de.studiocode.invui.window.impl.merged.MergedWindow; import de.studiocode.invui.window.impl.merged.MergedWindow;
@ -30,17 +31,17 @@ public abstract class CombinedWindow extends MergedWindow {
} }
@Override @Override
public void handleClick(InventoryClickEvent event) { protected ItemStackHolder getItemStackHolder(int index) {
Inventory clicked = event.getClickedInventory(); return gui.getItemStackHolder(index);
int guiSlot = clicked == getUpperInventory() ? event.getSlot()
: getUpperInventory().getSize() + SlotUtils.translatePlayerInvToGui(event.getSlot());
gui.handleClick(guiSlot, (Player) event.getWhoClicked(), event.getClick(), event);
} }
@Override @Override
protected ItemStackHolder getItemStackHolder(int index) { protected Pair<GUI, Integer> getWhereClicked(InventoryClickEvent event) {
return gui.getItemStackHolder(index); Inventory clicked = event.getClickedInventory();
int slot = event.getSlot();
int clickedIndex = clicked == getUpperInventory() ? slot
: getUpperInventory().getSize() + SlotUtils.translatePlayerInvToGui(slot);
return new Pair<>(gui, clickedIndex);
} }
@Override @Override

@ -2,6 +2,7 @@ package de.studiocode.invui.window.impl.merged.split;
import de.studiocode.invui.gui.GUI; import de.studiocode.invui.gui.GUI;
import de.studiocode.invui.gui.SlotElement.ItemStackHolder; import de.studiocode.invui.gui.SlotElement.ItemStackHolder;
import de.studiocode.invui.util.Pair;
import de.studiocode.invui.util.SlotUtils; import de.studiocode.invui.util.SlotUtils;
import de.studiocode.invui.window.Window; import de.studiocode.invui.window.Window;
import de.studiocode.invui.window.impl.merged.MergedWindow; import de.studiocode.invui.window.impl.merged.MergedWindow;
@ -33,23 +34,23 @@ public abstract class SplitWindow extends MergedWindow {
child.getItemStackHolder(slotIndex), true); 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 @Override
public ItemStackHolder getItemStackHolder(int index) { public ItemStackHolder getItemStackHolder(int index) {
if (index >= upperGui.getSize()) return lowerGui.getItemStackHolder(index - upperGui.getSize()); if (index >= upperGui.getSize()) return lowerGui.getItemStackHolder(index - upperGui.getSize());
else return upperGui.getItemStackHolder(index); else return upperGui.getItemStackHolder(index);
} }
@Override
protected Pair<GUI, Integer> 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 @Override
public GUI[] getGuis() { public GUI[] getGuis() {
return new GUI[] {upperGui, lowerGui}; return new GUI[] {upperGui, lowerGui};