ItemUpdateEvent UpdateReason

This commit is contained in:
NichtStudioCode 2021-04-21 20:55:18 +02:00
parent ff56f8e017
commit edde43b1ae
7 changed files with 120 additions and 80 deletions

@ -7,6 +7,7 @@ import de.studiocode.invui.gui.structure.Structure;
import de.studiocode.invui.item.Item; import de.studiocode.invui.item.Item;
import de.studiocode.invui.item.ItemBuilder; import de.studiocode.invui.item.ItemBuilder;
import de.studiocode.invui.virtualinventory.VirtualInventory; import de.studiocode.invui.virtualinventory.VirtualInventory;
import de.studiocode.invui.virtualinventory.event.UpdateReason;
import de.studiocode.invui.window.Window; import de.studiocode.invui.window.Window;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.ClickType;
@ -167,6 +168,7 @@ public interface GUI extends GUIParent {
/** /**
* Sets the {@link ItemBuilder} that will be used if nothing else * Sets the {@link ItemBuilder} that will be used if nothing else
* is placed on a slot. * is placed on a slot.
*
* @param itemBuilder The {@link ItemBuilder} * @param itemBuilder The {@link ItemBuilder}
*/ */
void setBackground(@Nullable ItemBuilder itemBuilder); void setBackground(@Nullable ItemBuilder itemBuilder);
@ -174,7 +176,7 @@ public interface GUI extends GUIParent {
/** /**
* Gets the {@link ItemBuilder} that will used if nothing else * Gets the {@link ItemBuilder} that will used if nothing else
* is placed on a slot. * is placed on a slot.
* *
* @return The {@link ItemBuilder} * @return The {@link ItemBuilder}
*/ */
ItemBuilder getBackground(); ItemBuilder getBackground();
@ -222,13 +224,13 @@ public interface GUI extends GUIParent {
/** /**
* A method called when an {@link ItemStack} has been dragged over the {@link GUI}. * A method called when an {@link ItemStack} has been dragged over the {@link GUI}.
* *
* @param player The player that is responsible for this action * @param updateReason The reason for this item update.
* @param slot The slot index * @param slot The slot index
* @param oldStack The {@link ItemStack} that was previously on that slot * @param oldStack The {@link ItemStack} that was previously on that slot
* @param newStack The new {@link ItemStack} that would be there if the action isn't cancelled * @param newStack The new {@link ItemStack} that would be there if the action isn't cancelled
* @return If the action has been cancelled * @return If the action has been cancelled
*/ */
boolean handleItemDrag(Player player, int slot, ItemStack oldStack, ItemStack newStack); boolean handleItemDrag(UpdateReason updateReason, int slot, ItemStack oldStack, ItemStack newStack);
/** /**
* Adds a {@link GUIParent} to the set of {@link GUIParent}s. * Adds a {@link GUIParent} to the set of {@link GUIParent}s.

@ -13,6 +13,8 @@ import de.studiocode.invui.item.ItemBuilder;
import de.studiocode.invui.util.ArrayUtils; 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.virtualinventory.event.PlayerUpdateReason;
import de.studiocode.invui.virtualinventory.event.UpdateReason;
import de.studiocode.invui.window.Window; import de.studiocode.invui.window.Window;
import de.studiocode.invui.window.WindowManager; import de.studiocode.invui.window.WindowManager;
import de.studiocode.invui.window.impl.merged.MergedWindow; import de.studiocode.invui.window.impl.merged.MergedWindow;
@ -73,6 +75,8 @@ abstract class IndexedGUI implements GUI {
Player player = (Player) event.getWhoClicked(); Player player = (Player) event.getWhoClicked();
ItemStack cursor = event.getCursor(); ItemStack cursor = event.getCursor();
ItemStack clicked = event.getCurrentItem(); ItemStack clicked = event.getCurrentItem();
UpdateReason updateReason = new PlayerUpdateReason(player, event);
if (virtualInventory.isSynced(index, clicked)) { if (virtualInventory.isSynced(index, clicked)) {
boolean cancelled = false; boolean cancelled = false;
@ -87,38 +91,38 @@ abstract class IndexedGUI implements GUI {
case DROP_ONE_SLOT: case DROP_ONE_SLOT:
case PICKUP_ONE: case PICKUP_ONE:
cancelled = virtualInventory.removeOne(player, index); cancelled = virtualInventory.removeOne(updateReason, index);
break; break;
case DROP_ALL_SLOT: case DROP_ALL_SLOT:
case PICKUP_ALL: case PICKUP_ALL:
cancelled = virtualInventory.removeItem(player, index); cancelled = virtualInventory.removeItem(updateReason, index);
break; break;
case PICKUP_HALF: case PICKUP_HALF:
cancelled = virtualInventory.removeHalf(player, index); cancelled = virtualInventory.removeHalf(updateReason, index);
break; break;
case PLACE_ALL: case PLACE_ALL:
cancelled = virtualInventory.place(player, index, cursor); cancelled = virtualInventory.place(updateReason, index, cursor);
break; break;
case PLACE_ONE: case PLACE_ONE:
cancelled = virtualInventory.placeOne(player, index, cursor); cancelled = virtualInventory.placeOne(updateReason, index, cursor);
break; break;
case PLACE_SOME: case PLACE_SOME:
cancelled = virtualInventory.setToMaxAmount(player, index); cancelled = virtualInventory.setToMaxAmount(updateReason, index);
break; break;
case SWAP_WITH_CURSOR: case SWAP_WITH_CURSOR:
cancelled = virtualInventory.setItemStack(player, index, event.getCursor()); cancelled = virtualInventory.setItemStack(updateReason, index, event.getCursor());
break; break;
case COLLECT_TO_CURSOR: case COLLECT_TO_CURSOR:
cancelled = true; cancelled = true;
ItemStack newCursor = cursor.clone(); ItemStack newCursor = cursor.clone();
newCursor.setAmount(virtualInventory.collectToCursor(player, newCursor)); newCursor.setAmount(virtualInventory.collectToCursor(updateReason, newCursor));
player.setItemOnCursor(newCursor); player.setItemOnCursor(newCursor);
break; break;
@ -127,7 +131,7 @@ abstract class IndexedGUI implements GUI {
Window window = WindowManager.getInstance().findOpenWindow(player).orElse(null); Window window = WindowManager.getInstance().findOpenWindow(player).orElse(null);
ItemStack invStack = virtualInventory.getItemStack(index); ItemStack invStack = virtualInventory.getItemStack(index);
ItemUpdateEvent updateEvent = new ItemUpdateEvent(virtualInventory, index, player, invStack, null); ItemUpdateEvent updateEvent = new ItemUpdateEvent(virtualInventory, index, updateReason, invStack, null);
Bukkit.getPluginManager().callEvent(updateEvent); Bukkit.getPluginManager().callEvent(updateEvent);
if (!updateEvent.isCancelled()) { if (!updateEvent.isCancelled()) {
@ -142,7 +146,7 @@ abstract class IndexedGUI implements GUI {
otherGui = this; otherGui = this;
} }
leftOverAmount = ((IndexedGUI) otherGui).putIntoVirtualInventories(player, invStack, virtualInventory); leftOverAmount = ((IndexedGUI) otherGui).putIntoVirtualInventories(updateReason, invStack, virtualInventory);
} else { } else {
leftOverAmount = 0; leftOverAmount = 0;
HashMap<Integer, ItemStack> leftover = event.getWhoClicked().getInventory().addItem(virtualInventory.getItemStack(index)); HashMap<Integer, ItemStack> leftover = event.getWhoClicked().getInventory().addItem(virtualInventory.getItemStack(index));
@ -165,7 +169,7 @@ abstract class IndexedGUI implements GUI {
} }
@Override @Override
public boolean handleItemDrag(Player player, int slot, ItemStack oldStack, ItemStack newStack) { public boolean handleItemDrag(UpdateReason updateReason, int slot, ItemStack oldStack, ItemStack newStack) {
SlotElement element = getSlotElement(slot); SlotElement element = getSlotElement(slot);
if (element != null) element = element.getHoldingElement(); if (element != null) element = element.getHoldingElement();
if (element instanceof VISlotElement) { if (element instanceof VISlotElement) {
@ -173,7 +177,7 @@ abstract class IndexedGUI implements GUI {
VirtualInventory virtualInventory = viSlotElement.getVirtualInventory(); VirtualInventory virtualInventory = viSlotElement.getVirtualInventory();
int viIndex = viSlotElement.getIndex(); int viIndex = viSlotElement.getIndex();
if (virtualInventory.isSynced(viIndex, oldStack)) { if (virtualInventory.isSynced(viIndex, oldStack)) {
return virtualInventory.setItemStack(player, viIndex, newStack); return virtualInventory.setItemStack(updateReason, viIndex, newStack);
} }
} }
@ -189,14 +193,16 @@ abstract class IndexedGUI implements GUI {
Player player = (Player) event.getWhoClicked(); Player player = (Player) event.getWhoClicked();
ItemStack clicked = event.getCurrentItem(); ItemStack clicked = event.getCurrentItem();
int amountLeft = putIntoVirtualInventories(player, clicked); UpdateReason updateReason = new PlayerUpdateReason(player, event);
int amountLeft = putIntoVirtualInventories(updateReason, clicked);
if (amountLeft != clicked.getAmount()) { if (amountLeft != clicked.getAmount()) {
if (amountLeft != 0) event.getCurrentItem().setAmount(amountLeft); if (amountLeft != 0) event.getCurrentItem().setAmount(amountLeft);
else event.getClickedInventory().setItem(event.getSlot(), null); else event.getClickedInventory().setItem(event.getSlot(), null);
} }
} }
private int putIntoVirtualInventories(Player player, ItemStack itemStack, VirtualInventory... ignored) { private int putIntoVirtualInventories(UpdateReason updateReason, ItemStack itemStack, VirtualInventory... ignored) {
if (itemStack.getAmount() <= 0) throw new IllegalArgumentException("Illegal ItemStack amount"); if (itemStack.getAmount() <= 0) throw new IllegalArgumentException("Illegal ItemStack amount");
List<VirtualInventory> virtualInventories = getAllVirtualInventories(ignored); List<VirtualInventory> virtualInventories = getAllVirtualInventories(ignored);
@ -205,7 +211,7 @@ abstract class IndexedGUI implements GUI {
for (VirtualInventory virtualInventory : virtualInventories) { for (VirtualInventory virtualInventory : virtualInventories) {
ItemStack toAdd = itemStack.clone(); ItemStack toAdd = itemStack.clone();
toAdd.setAmount(amountLeft); toAdd.setAmount(amountLeft);
amountLeft = virtualInventory.addItem(player, toAdd); amountLeft = virtualInventory.addItem(updateReason, toAdd);
if (amountLeft == 0) break; if (amountLeft == 0) break;
} }

@ -3,10 +3,10 @@ package de.studiocode.invui.virtualinventory;
import de.studiocode.invui.InvUI; import de.studiocode.invui.InvUI;
import de.studiocode.invui.util.ArrayUtils; import de.studiocode.invui.util.ArrayUtils;
import de.studiocode.invui.virtualinventory.event.ItemUpdateEvent; import de.studiocode.invui.virtualinventory.event.ItemUpdateEvent;
import de.studiocode.invui.virtualinventory.event.UpdateReason;
import de.studiocode.invui.window.Window; import de.studiocode.invui.window.Window;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.configuration.serialization.ConfigurationSerializable; import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -76,7 +76,7 @@ public class VirtualInventory implements ConfigurationSerializable {
/** /**
* Gets a deep copy of the {@link ItemStack}s in this {@link VirtualInventory} * Gets a deep copy of the {@link ItemStack}s in this {@link VirtualInventory}
* *
* @return A copy of the {@link ItemStack}s in this {@link VirtualInventory} * @return A copy of the {@link ItemStack}s in this {@link VirtualInventory}
*/ */
public ItemStack[] getItems() { public ItemStack[] getItems() {
@ -111,14 +111,14 @@ public class VirtualInventory implements ConfigurationSerializable {
/** /**
* Sets an {@link ItemStack} on a specific slot. * Sets an {@link ItemStack} on a specific slot.
* *
* @param player The player that did this or <code>null</code> if it wasn't a player. * @param updateReason The reason for item update, can be null.
* @param index The slot index * @param index The slot index
* @param itemStack The {@link ItemStack} that should be put on that slot * @param itemStack The {@link ItemStack} that should be put on that slot
* @return If the action has been cancelled * @return If the action has been cancelled
*/ */
public boolean setItemStack(Player player, int index, ItemStack itemStack) { public boolean setItemStack(@Nullable UpdateReason updateReason, int index, ItemStack itemStack) {
ItemStack newStack = itemStack.clone(); ItemStack newStack = itemStack.clone();
ItemUpdateEvent event = createAndCallEvent(index, player, items[index], newStack); ItemUpdateEvent event = createAndCallEvent(index, updateReason, items[index], newStack);
if (!event.isCancelled()) { if (!event.isCancelled()) {
items[index] = newStack; items[index] = newStack;
notifyWindows(); notifyWindows();
@ -153,12 +153,12 @@ public class VirtualInventory implements ConfigurationSerializable {
* Sets an {@link ItemStack} on a specific slot or adds the amount * Sets an {@link ItemStack} on a specific slot or adds the amount
* if there already is an {@link ItemStack} on that slot. * if there already is an {@link ItemStack} on that slot.
* *
* @param player The player that did this or <code>null</code> if it wasn't a player. * @param updateReason The reason for item update, can be null.
* @param index The slot index * @param index The slot index
* @param itemStack The {@link ItemStack} to place * @param itemStack The {@link ItemStack} to place
* @return If the action has been cancelled * @return If the action has been cancelled
*/ */
public boolean place(Player player, int index, ItemStack itemStack) { public boolean place(@Nullable UpdateReason updateReason, int index, ItemStack itemStack) {
ItemStack currentStack = items[index]; ItemStack currentStack = items[index];
ItemStack newStack; ItemStack newStack;
@ -169,7 +169,7 @@ public class VirtualInventory implements ConfigurationSerializable {
newStack.setAmount(newStack.getAmount() + itemStack.getAmount()); newStack.setAmount(newStack.getAmount() + itemStack.getAmount());
} }
ItemUpdateEvent event = createAndCallEvent(index, player, currentStack, newStack); ItemUpdateEvent event = createAndCallEvent(index, updateReason, currentStack, newStack);
if (!event.isCancelled()) { if (!event.isCancelled()) {
items[index] = newStack; items[index] = newStack;
notifyWindows(); notifyWindows();
@ -184,12 +184,12 @@ public class VirtualInventory implements ConfigurationSerializable {
* Puts on of an {@link ItemStack} on a specific slots or adds one * Puts on of an {@link ItemStack} on a specific slots or adds one
* if there is already an {@link ItemStack} on that slot. * if there is already an {@link ItemStack} on that slot.
* *
* @param player The player that did this or <code>null</code> if it wasn't a player. * @param updateReason The reason for item update, can be null.
* @param index The slot index * @param index The slot index
* @param itemStack The {@link ItemStack} to place one of * @param itemStack The {@link ItemStack} to place one of
* @return If the action has been cancelled * @return If the action has been cancelled
*/ */
public boolean placeOne(Player player, int index, ItemStack itemStack) { public boolean placeOne(@Nullable UpdateReason updateReason, int index, ItemStack itemStack) {
ItemStack currentStack = items[index]; ItemStack currentStack = items[index];
ItemStack newStack; ItemStack newStack;
@ -201,7 +201,7 @@ public class VirtualInventory implements ConfigurationSerializable {
newStack.setAmount(newStack.getAmount() + 1); newStack.setAmount(newStack.getAmount() + 1);
} }
ItemUpdateEvent event = createAndCallEvent(index, player, currentStack, newStack); ItemUpdateEvent event = createAndCallEvent(index, updateReason, currentStack, newStack);
if (!event.isCancelled()) { if (!event.isCancelled()) {
items[index] = newStack; items[index] = newStack;
notifyWindows(); notifyWindows();
@ -231,17 +231,17 @@ public class VirtualInventory implements ConfigurationSerializable {
* Changes the amount of an {@link ItemStack} on a specific slot * Changes the amount of an {@link ItemStack} on a specific slot
* to the {@link ItemStack}'s {@link ItemStack#getMaxStackSize()}. * to the {@link ItemStack}'s {@link ItemStack#getMaxStackSize()}.
* *
* @param player The player that did this or <code>null</code> if it wasn't a player. * @param updateReason The reason for item update, can be null.
* @param index The slot index * @param index The slot index
* @return If the action has been cancelled * @return If the action has been cancelled
*/ */
public boolean setToMaxAmount(Player player, int index) { public boolean setToMaxAmount(@Nullable UpdateReason updateReason, int index) {
ItemStack currentStack = items[index]; ItemStack currentStack = items[index];
if (currentStack != null) { if (currentStack != null) {
ItemStack newStack = currentStack.clone(); ItemStack newStack = currentStack.clone();
newStack.setAmount(newStack.getMaxStackSize()); newStack.setAmount(newStack.getMaxStackSize());
ItemUpdateEvent event = createAndCallEvent(index, player, currentStack, newStack); ItemUpdateEvent event = createAndCallEvent(index, updateReason, currentStack, newStack);
if (!event.isCancelled()) { if (!event.isCancelled()) {
items[index] = newStack; items[index] = newStack;
notifyWindows(); notifyWindows();
@ -257,15 +257,15 @@ public class VirtualInventory implements ConfigurationSerializable {
* Removes an {@link ItemStack} on a specific slot from * Removes an {@link ItemStack} on a specific slot from
* the {@link VirtualInventory}. * the {@link VirtualInventory}.
* *
* @param player The player that did this or <code>null</code> if it wasn't a player. * @param updateReason The reason for item update, can be null.
* @param index The slot index * @param index The slot index
* @return If the action has been cancelled * @return If the action has been cancelled
*/ */
public boolean removeItem(Player player, int index) { public boolean removeItem(@Nullable UpdateReason updateReason, int index) {
ItemStack currentStack = items[index]; ItemStack currentStack = items[index];
if (currentStack != null) { if (currentStack != null) {
ItemUpdateEvent event = createAndCallEvent(index, player, currentStack, null); ItemUpdateEvent event = createAndCallEvent(index, updateReason, currentStack, null);
if (!event.isCancelled()) { if (!event.isCancelled()) {
items[index] = null; items[index] = null;
notifyWindows(); notifyWindows();
@ -280,11 +280,11 @@ public class VirtualInventory implements ConfigurationSerializable {
/** /**
* Removes one from an {@link ItemStack} on a specific slot. * Removes one from an {@link ItemStack} on a specific slot.
* *
* @param player The player that did this or <code>null</code> if it wasn't a player. * @param updateReason The reason for item update, can be null.
* @param index The slot index * @param index The slot index
* @return If the action has been cancelled * @return If the action has been cancelled
*/ */
public boolean removeOne(Player player, int index) { public boolean removeOne(@Nullable UpdateReason updateReason, int index) {
ItemStack currentStack = items[index]; ItemStack currentStack = items[index];
if (currentStack != null) { if (currentStack != null) {
int newAmount = currentStack.getAmount() - 1; int newAmount = currentStack.getAmount() - 1;
@ -293,14 +293,14 @@ public class VirtualInventory implements ConfigurationSerializable {
ItemStack newStack = currentStack.clone(); ItemStack newStack = currentStack.clone();
newStack.setAmount(newAmount); newStack.setAmount(newAmount);
ItemUpdateEvent event = createAndCallEvent(index, player, currentStack, newStack); ItemUpdateEvent event = createAndCallEvent(index, updateReason, currentStack, newStack);
if (!event.isCancelled()) { if (!event.isCancelled()) {
items[index] = newStack; items[index] = newStack;
notifyWindows(); notifyWindows();
return false; return false;
} }
} else return removeItem(player, index); } else return removeItem(updateReason, index);
} }
return true; return true;
@ -309,11 +309,11 @@ public class VirtualInventory implements ConfigurationSerializable {
/** /**
* Removes half of the {@link ItemStack} on a specific slot. * Removes half of the {@link ItemStack} on a specific slot.
* *
* @param player The player that did this or <code>null</code> if it wasn't a player. * @param updateReason The reason for item update, can be null.
* @param index The slot index * @param index The slot index
* @return If the action has been cancelled * @return If the action has been cancelled
*/ */
public boolean removeHalf(Player player, int index) { public boolean removeHalf(@Nullable UpdateReason updateReason, int index) {
ItemStack currentStack = items[index]; ItemStack currentStack = items[index];
if (currentStack != null) { if (currentStack != null) {
int newAmount = currentStack.getAmount() / 2; int newAmount = currentStack.getAmount() / 2;
@ -322,7 +322,7 @@ public class VirtualInventory implements ConfigurationSerializable {
ItemStack newStack = currentStack.clone(); ItemStack newStack = currentStack.clone();
newStack.setAmount(newAmount); newStack.setAmount(newAmount);
ItemUpdateEvent event = createAndCallEvent(index, player, currentStack, newStack); ItemUpdateEvent event = createAndCallEvent(index, updateReason, currentStack, newStack);
if (!event.isCancelled()) { if (!event.isCancelled()) {
items[index] = newStack; items[index] = newStack;
notifyWindows(); notifyWindows();
@ -330,7 +330,7 @@ public class VirtualInventory implements ConfigurationSerializable {
return false; return false;
} }
} else return removeItem(player, index); } else return removeItem(updateReason, index);
} }
return true; return true;
@ -339,17 +339,17 @@ public class VirtualInventory implements ConfigurationSerializable {
/** /**
* Adds an {@link ItemStack} to the {@link VirtualInventory}. * Adds an {@link ItemStack} to the {@link VirtualInventory}.
* *
* @param player The player that did this or <code>null</code> if it wasn't a player. * @param updateReason The reason for item update, can be null.
* @param itemStack The {@link ItemStack} to add * @param itemStack The {@link ItemStack} to add
* @return The amount of items that couldn't be added * @return The amount of items that couldn't be added
*/ */
public int addItem(Player player, ItemStack itemStack) { public int addItem(@Nullable UpdateReason updateReason, ItemStack itemStack) {
final int originalAmount = itemStack.getAmount(); final int originalAmount = itemStack.getAmount();
int amountLeft = originalAmount; int amountLeft = originalAmount;
// find all slots where the item partially fits and add it there // find all slots where the item partially fits and add it there
for (int partialSlot : findPartialSlots(itemStack)) { for (int partialSlot : findPartialSlots(itemStack)) {
amountLeft = addTo(player, partialSlot, amountLeft); amountLeft = addTo(updateReason, partialSlot, amountLeft);
if (amountLeft == 0) break; if (amountLeft == 0) break;
} }
@ -359,7 +359,7 @@ public class VirtualInventory implements ConfigurationSerializable {
if (emptyIndex != -1) { if (emptyIndex != -1) {
ItemStack leftover = itemStack.clone(); ItemStack leftover = itemStack.clone();
leftover.setAmount(amountLeft); leftover.setAmount(amountLeft);
if (!place(player, emptyIndex, leftover)) if (!place(updateReason, emptyIndex, leftover))
amountLeft = 0; amountLeft = 0;
} }
} }
@ -371,13 +371,13 @@ public class VirtualInventory implements ConfigurationSerializable {
return amountLeft; return amountLeft;
} }
public int collectToCursor(Player player, ItemStack itemStack) { public int collectToCursor(@Nullable UpdateReason updateReason, ItemStack itemStack) {
int amount = itemStack.getAmount(); int amount = itemStack.getAmount();
int maxStackSize = itemStack.getMaxStackSize(); int maxStackSize = itemStack.getMaxStackSize();
if (amount < itemStack.getMaxStackSize()) { if (amount < itemStack.getMaxStackSize()) {
// find partial slots and take items from there // find partial slots and take items from there
for (int partialSlot : findPartialSlots(itemStack)) { for (int partialSlot : findPartialSlots(itemStack)) {
amount += takeFrom(player, partialSlot, maxStackSize - amount); amount += takeFrom(updateReason, partialSlot, maxStackSize - amount);
if (amount == maxStackSize) break; if (amount == maxStackSize) break;
} }
@ -385,7 +385,7 @@ public class VirtualInventory implements ConfigurationSerializable {
if (amount < itemStack.getMaxStackSize()) { if (amount < itemStack.getMaxStackSize()) {
int fullSlot = findFullSlot(itemStack); int fullSlot = findFullSlot(itemStack);
if (fullSlot != -1) { if (fullSlot != -1) {
amount += takeFrom(player, fullSlot, maxStackSize - amount); amount += takeFrom(updateReason, fullSlot, maxStackSize - amount);
} }
} }
} }
@ -415,7 +415,7 @@ public class VirtualInventory implements ConfigurationSerializable {
return -1; return -1;
} }
private int addTo(Player player, int index, int amount) { private int addTo(@Nullable UpdateReason updateReason, int index, int amount) {
ItemStack itemStack = items[index]; ItemStack itemStack = items[index];
int maxAddable = Math.min(itemStack.getMaxStackSize() - itemStack.getAmount(), amount); int maxAddable = Math.min(itemStack.getMaxStackSize() - itemStack.getAmount(), amount);
@ -426,7 +426,7 @@ public class VirtualInventory implements ConfigurationSerializable {
ItemStack newStack = itemStack.clone(); ItemStack newStack = itemStack.clone();
newStack.setAmount(newAmount); newStack.setAmount(newAmount);
ItemUpdateEvent event = createAndCallEvent(index, player, itemStack, newStack); ItemUpdateEvent event = createAndCallEvent(index, updateReason, itemStack, newStack);
if (!event.isCancelled()) { if (!event.isCancelled()) {
items[index] = newStack; items[index] = newStack;
notifyWindows(); notifyWindows();
@ -434,7 +434,7 @@ public class VirtualInventory implements ConfigurationSerializable {
} else return amount; } else return amount;
} }
private int takeFrom(Player player, int index, int maxTake) { private int takeFrom(@Nullable UpdateReason updateReason, int index, int maxTake) {
ItemStack itemStack = items[index]; ItemStack itemStack = items[index];
int amount = itemStack.getAmount(); int amount = itemStack.getAmount();
int take = Math.min(amount, maxTake); int take = Math.min(amount, maxTake);
@ -445,7 +445,7 @@ public class VirtualInventory implements ConfigurationSerializable {
newStack.setAmount(amount - take); newStack.setAmount(amount - take);
} else newStack = null; } else newStack = null;
ItemUpdateEvent event = createAndCallEvent(index, player, itemStack, newStack); ItemUpdateEvent event = createAndCallEvent(index, updateReason, itemStack, newStack);
if (!event.isCancelled()) { if (!event.isCancelled()) {
items[index] = newStack; items[index] = newStack;
notifyWindows(); notifyWindows();
@ -480,8 +480,8 @@ public class VirtualInventory implements ConfigurationSerializable {
windows.forEach(window -> window.handleVirtualInventoryUpdate(this))); windows.forEach(window -> window.handleVirtualInventoryUpdate(this)));
} }
private ItemUpdateEvent createAndCallEvent(int index, Player player, ItemStack previousItemStack, ItemStack newItemStack) { private ItemUpdateEvent createAndCallEvent(int index, UpdateReason updateReason, ItemStack previousItemStack, ItemStack newItemStack) {
ItemUpdateEvent event = new ItemUpdateEvent(this, index, player, previousItemStack, newItemStack); ItemUpdateEvent event = new ItemUpdateEvent(this, index, updateReason, previousItemStack, newItemStack);
if (itemUpdateHandler != null) itemUpdateHandler.accept(event); if (itemUpdateHandler != null) itemUpdateHandler.accept(event);
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
return event; return event;

@ -19,7 +19,7 @@ public class ItemUpdateEvent extends Event implements Cancellable {
private final VirtualInventory virtualInventory; private final VirtualInventory virtualInventory;
private final ItemStack previousItemStack; private final ItemStack previousItemStack;
private final ItemStack newItemStack; private final ItemStack newItemStack;
private final Player player; private final UpdateReason updateReason;
private final int slot; private final int slot;
private boolean cancelled; private boolean cancelled;
@ -28,17 +28,19 @@ public class ItemUpdateEvent extends Event implements Cancellable {
* Creates a new {@link ItemUpdateEvent}. * Creates a new {@link ItemUpdateEvent}.
* *
* @param virtualInventory The {@link VirtualInventory} where this action takes place. * @param virtualInventory The {@link VirtualInventory} where this action takes place.
* @param player The {@link Player} who changed the {@link ItemStack} or <code>null</code> * @param updateReason The {@link UpdateReason} for the calling of this event.
* This will probably be a {@link PlayerUpdateReason} in most cases but can be a custom one
* if you called the methods in the {@link VirtualInventory} yourself.
* if it wasn't a {@link Player} * if it wasn't a {@link Player}
* @param slot The slot that is affected * @param slot The slot that is affected
* @param previousItemStack The {@link ItemStack} that was there previously * @param previousItemStack The {@link ItemStack} that was there previously
* @param newItemStack The {@link ItemStack} that will be there if the event isn't cancelled * @param newItemStack The {@link ItemStack} that will be there if the event isn't cancelled
*/ */
public ItemUpdateEvent(@NotNull VirtualInventory virtualInventory, int slot, @Nullable Player player, public ItemUpdateEvent(@NotNull VirtualInventory virtualInventory, int slot, @Nullable UpdateReason updateReason,
@Nullable ItemStack previousItemStack, @Nullable ItemStack newItemStack) { @Nullable ItemStack previousItemStack, @Nullable ItemStack newItemStack) {
this.virtualInventory = virtualInventory; this.virtualInventory = virtualInventory;
this.slot = slot; this.slot = slot;
this.player = player; this.updateReason = updateReason;
this.previousItemStack = previousItemStack; this.previousItemStack = previousItemStack;
this.newItemStack = newItemStack; this.newItemStack = newItemStack;
} }
@ -62,13 +64,12 @@ public class ItemUpdateEvent extends Event implements Cancellable {
} }
/** /**
* Gets the {@link Player} who changed the {@link ItemStack} or <code>null</code> * Gets the {@link UpdateReason} for the calling of this event.
* if it wasn't a {@link Player}.
* *
* @return The {@link Player} * @return The reason why this event was called. Probably a {@link PlayerUpdateReason} in most cases.
*/ */
public Player getPlayer() { public UpdateReason getUpdateReason() {
return player; return updateReason;
} }
/** /**

@ -0,0 +1,24 @@
package de.studiocode.invui.virtualinventory.event;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryEvent;
public class PlayerUpdateReason implements UpdateReason {
private final Player player;
private final InventoryEvent event;
public PlayerUpdateReason(Player player, InventoryEvent event) {
this.player = player;
this.event = event;
}
public Player getPlayer() {
return player;
}
public InventoryEvent getEvent() {
return event;
}
}

@ -0,0 +1,4 @@
package de.studiocode.invui.virtualinventory.event;
public interface UpdateReason {
}

@ -11,6 +11,8 @@ import de.studiocode.invui.item.ItemBuilder;
import de.studiocode.invui.util.ArrayUtils; import de.studiocode.invui.util.ArrayUtils;
import de.studiocode.invui.util.Pair; import de.studiocode.invui.util.Pair;
import de.studiocode.invui.virtualinventory.VirtualInventory; import de.studiocode.invui.virtualinventory.VirtualInventory;
import de.studiocode.invui.virtualinventory.event.PlayerUpdateReason;
import de.studiocode.invui.virtualinventory.event.UpdateReason;
import de.studiocode.invui.window.Window; import de.studiocode.invui.window.Window;
import de.studiocode.invui.window.WindowManager; import de.studiocode.invui.window.WindowManager;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -89,6 +91,7 @@ public abstract class BaseWindow implements Window {
@Override @Override
public void handleDrag(InventoryDragEvent event) { public void handleDrag(InventoryDragEvent event) {
Player player = ((Player) event.getWhoClicked()).getPlayer(); Player player = ((Player) event.getWhoClicked()).getPlayer();
UpdateReason updateReason = new PlayerUpdateReason(player, event);
Map<Integer, ItemStack> newItems = event.getNewItems(); Map<Integer, ItemStack> newItems = event.getNewItems();
int itemsLeft = event.getCursor() == null ? 0 : event.getCursor().getAmount(); int itemsLeft = event.getCursor() == null ? 0 : event.getCursor().getAmount();
@ -98,7 +101,7 @@ public abstract class BaseWindow implements Window {
// get the GUI at that index and ask for permission to drag an Item there // get the GUI at that index and ask for permission to drag an Item there
Pair<GUI, Integer> pair = getGuiAt(rawSlot); Pair<GUI, Integer> pair = getGuiAt(rawSlot);
if (pair != null && pair.getFirst().handleItemDrag(player, pair.getSecond(), currentStack, newItems.get(rawSlot))) { if (pair != null && pair.getFirst().handleItemDrag(updateReason, pair.getSecond(), currentStack, newItems.get(rawSlot))) {
// the drag was cancelled // the drag was cancelled
int currentAmount = currentStack == null ? 0 : currentStack.getAmount(); int currentAmount = currentStack == null ? 0 : currentStack.getAmount();
int newAmount = newItems.get(rawSlot).getAmount(); int newAmount = newItems.get(rawSlot).getAmount();