summaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
authorriking <rikingcoding@gmail.com>2013-04-13 18:17:27 -0700
committerNate Mortensen <nate.richard.mortensen@gmail.com>2013-06-03 17:57:14 -0600
commitc1cd6ec06de7b7d9285cecc39d39d311dc92ffa5 (patch)
treeb392ffcca09c1a1234d3b69efe4914904c176844 /src/main
parenta0b31825391355b962497a80c8790029feecd63d (diff)
downloadbukkit-c1cd6ec06de7b7d9285cecc39d39d311dc92ffa5.tar
bukkit-c1cd6ec06de7b7d9285cecc39d39d311dc92ffa5.tar.gz
bukkit-c1cd6ec06de7b7d9285cecc39d39d311dc92ffa5.tar.lz
bukkit-c1cd6ec06de7b7d9285cecc39d39d311dc92ffa5.tar.xz
bukkit-c1cd6ec06de7b7d9285cecc39d39d311dc92ffa5.zip
Improve events for new inventory features. Adds BUKKIT-3859
This commit brings the InventoryClickEvent up to date with the new Minecraft changes in 1.5. InventoryDragEvent (thanks to @YLivay for his PR) is added to represent the new "dragging" or "painting" functionality, where if you hold an itemstack and click-drag over several slots, the items will be split evenly (left click) or 1 each (right click). The ClickType enum is used to represent what the client did to trigger the event. The InventoryAction enum is reserved for future expansion, but will be used to indicate the approximate result of the action. Additionally, handling of creative inventory editing is improved with the new InventoryCreativeEvent, and handling of numberkey presses is also improved within InventoryClickEvent and CraftItemEvent. Also, cancelling a creative click now displays properly on the client. Adresses BUKKIT-3692, BUKKIT-4035, BUKKIT-3859 (new 1.5 events), BUKKIT-2659, BUKKIT-3043, BUKKIT-2659, and BUKKIT-2897 (creative click events).
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/org/bukkit/event/inventory/ClickType.java115
-rw-r--r--src/main/java/org/bukkit/event/inventory/CraftItemEvent.java12
-rw-r--r--src/main/java/org/bukkit/event/inventory/DragType.java18
-rw-r--r--src/main/java/org/bukkit/event/inventory/InventoryAction.java90
-rw-r--r--src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java204
-rw-r--r--src/main/java/org/bukkit/event/inventory/InventoryCreativeEvent.java27
-rw-r--r--src/main/java/org/bukkit/event/inventory/InventoryDragEvent.java164
-rw-r--r--src/main/java/org/bukkit/event/inventory/InventoryInteractEvent.java78
8 files changed, 648 insertions, 60 deletions
diff --git a/src/main/java/org/bukkit/event/inventory/ClickType.java b/src/main/java/org/bukkit/event/inventory/ClickType.java
new file mode 100644
index 00000000..dc2928cc
--- /dev/null
+++ b/src/main/java/org/bukkit/event/inventory/ClickType.java
@@ -0,0 +1,115 @@
+package org.bukkit.event.inventory;
+
+/**
+ * What the client did to trigger this action (not the result).
+ */
+public enum ClickType {
+ /**
+ * The left (or primary) mouse button.
+ */
+ LEFT,
+ /**
+ * Holding shift while pressing the left mouse button.
+ */
+ SHIFT_LEFT,
+ /**
+ * The right mouse button.
+ */
+ RIGHT,
+ /**
+ * Holding shift while pressing the right mouse button.
+ */
+ SHIFT_RIGHT,
+ /**
+ * Clicking the left mouse button on the grey area around the
+ * inventory.
+ */
+ WINDOW_BORDER_LEFT,
+ /**
+ * Clicking the right mouse button on the grey area around the
+ * inventory.
+ */
+ WINDOW_BORDER_RIGHT,
+ /**
+ * The middle mouse button, or a "scrollwheel click".
+ */
+ MIDDLE,
+ /**
+ * One of the number keys 1-9, correspond to slots on the hotbar.
+ */
+ NUMBER_KEY,
+ /**
+ * Pressing the left mouse button twice in quick succession.
+ */
+ DOUBLE_CLICK,
+ /**
+ * The "Drop" key (defaults to Q).
+ */
+ DROP,
+ /**
+ * Holding Ctrl while pressing the "Drop" key (defaults to Q).
+ */
+ CONTROL_DROP,
+ /**
+ * Any action done with the Creative inventory open.
+ */
+ CREATIVE,
+ /**
+ * A type of inventory manipulation not yet recognized by Bukkit.
+ * This is only for transitional purposes on a new Minecraft update,
+ * and should never be relied upon.
+ * <p>
+ * Any ClickType.UNKNOWN is called on a best-effort basis.
+ */
+ UNKNOWN,
+ ;
+
+ /**
+ * Gets whether this ClickType represents the pressing of a key on a
+ * keyboard.
+ *
+ * @return true if this ClickType represents the pressing of a key
+ */
+ public boolean isKeyboardClick() {
+ return (this == ClickType.NUMBER_KEY) || (this == ClickType.DROP) || (this == ClickType.CONTROL_DROP);
+ }
+
+ /**
+ * Gets whether this ClickType represents an action that can only be
+ * performed by a Player in creative mode.
+ *
+ * @return true if this action requires Creative mode
+ */
+ public boolean isCreativeAction() {
+ // Why use middle click?
+ return (this == ClickType.MIDDLE) || (this == ClickType.CREATIVE);
+ }
+
+ /**
+ * Gets whether this ClickType represents a right click.
+ *
+ * @return true if this ClickType represents a right click
+ */
+ public boolean isRightClick() {
+ return (this == ClickType.RIGHT) || (this == ClickType.SHIFT_RIGHT);
+ }
+
+ /**
+ * Gets whether this ClickType represents a left click.
+ *
+ * @return true if this ClickType represents a left click
+ */
+ public boolean isLeftClick() {
+ return (this == ClickType.LEFT) || (this == ClickType.SHIFT_LEFT) || (this == ClickType.DOUBLE_CLICK) || (this == ClickType.CREATIVE);
+ }
+
+ /**
+ * Gets whether this ClickType indicates that the shift key was pressed
+ * down when the click was made.
+ *
+ * @return true if the action uses Shift.
+ */
+ public boolean isShiftClick() {
+ return (this == ClickType.SHIFT_LEFT) || (this == ClickType.SHIFT_RIGHT) || (this == ClickType.CONTROL_DROP);
+ }
+}
diff --git a/src/main/java/org/bukkit/event/inventory/CraftItemEvent.java b/src/main/java/org/bukkit/event/inventory/CraftItemEvent.java
index 264ab0a9..4ebc36bd 100644
--- a/src/main/java/org/bukkit/event/inventory/CraftItemEvent.java
+++ b/src/main/java/org/bukkit/event/inventory/CraftItemEvent.java
@@ -8,8 +8,18 @@ import org.bukkit.inventory.Recipe;
public class CraftItemEvent extends InventoryClickEvent {
private Recipe recipe;
+ @Deprecated
public CraftItemEvent(Recipe recipe, InventoryView what, SlotType type, int slot, boolean right, boolean shift) {
- super(what, type, slot, right, shift);
+ this(recipe, what, type, slot, right ? (shift ? ClickType.SHIFT_RIGHT : ClickType.RIGHT) : (shift ? ClickType.SHIFT_LEFT : ClickType.LEFT), InventoryAction.PICKUP_ALL);
+ }
+
+ public CraftItemEvent(Recipe recipe, InventoryView what, SlotType type, int slot, ClickType click, InventoryAction action) {
+ super(what, type, slot, click, action);
+ this.recipe = recipe;
+ }
+
+ public CraftItemEvent(Recipe recipe, InventoryView what, SlotType type, int slot, ClickType click, InventoryAction action, int key) {
+ super(what, type, slot, click, action, key);
this.recipe = recipe;
}
diff --git a/src/main/java/org/bukkit/event/inventory/DragType.java b/src/main/java/org/bukkit/event/inventory/DragType.java
new file mode 100644
index 00000000..9000faf1
--- /dev/null
+++ b/src/main/java/org/bukkit/event/inventory/DragType.java
@@ -0,0 +1,18 @@
+package org.bukkit.event.inventory;
+
+/**
+ * Represents the effect of a drag that will be applied to an Inventory in an
+ * InventoryDragEvent.
+ */
+public enum DragType {
+ /**
+ * One item from the cursor is placed in each selected slot.
+ */
+ SINGLE,
+ /**
+ * The cursor is split evenly across all selected slots, not to
+ * exceed the Material's max stack size, with the remainder going to
+ * the cursor.
+ */
+ EVEN,
+}
diff --git a/src/main/java/org/bukkit/event/inventory/InventoryAction.java b/src/main/java/org/bukkit/event/inventory/InventoryAction.java
new file mode 100644
index 00000000..c9da0222
--- /dev/null
+++ b/src/main/java/org/bukkit/event/inventory/InventoryAction.java
@@ -0,0 +1,90 @@
+package org.bukkit.event.inventory;
+
+/**
+ * An estimation of what the result will be.
+ */
+public enum InventoryAction {
+ /**
+ * Nothing will happen from the click.
+ * There may be cases where nothing will happen and this is value is
+ * not provided, but it is guaranteed that this value is accurate
+ * when given.
+ */
+ NOTHING,
+ /**
+ * All of the items on the clicked slot are moved to the cursor.
+ */
+ PICKUP_ALL,
+ /**
+ * Some of the items on the clicked slot are moved to the cursor.
+ */
+ PICKUP_SOME,
+ /**
+ * Half of the items on the clicked slot are moved to the cursor.
+ */
+ PICKUP_HALF,
+ /**
+ * One of the items on the clicked slot are moved to the cursor.
+ */
+ PICKUP_ONE,
+ /**
+ * All of the items on the cursor are moved to the clicked slot.
+ */
+ PLACE_ALL,
+ /**
+ * Some of the items from the cursor are moved to the clicked slot
+ * (usually up to the max stack size).
+ */
+ PLACE_SOME,
+ /**
+ * A single item from the cursor is moved to the clicked slot.
+ */
+ PLACE_ONE,
+ /**
+ * The clicked item and the cursor are exchanged.
+ */
+ SWAP_WITH_CURSOR,
+ /**
+ * The entire cursor item is dropped.
+ */
+ DROP_ALL_CURSOR,
+ /**
+ * One item is dropped from the cursor.
+ */
+ DROP_ONE_CURSOR,
+ /**
+ * The entire clicked slot is dropped.
+ */
+ DROP_ALL_SLOT,
+ /**
+ * One item is dropped from the clicked slot.
+ */
+ DROP_ONE_SLOT,
+ /**
+ * The item is moved to the opposite inventory if a space is found.
+ */
+ MOVE_TO_OTHER_INVENTORY,
+ /**
+ * The clicked item is moved to the hotbar, and the item currently
+ * there is re-added to the player's inventory.
+ */
+ HOTBAR_MOVE_AND_READD,
+ /**
+ * The clicked slot and the picked hotbar slot are swapped.
+ */
+ HOTBAR_SWAP,
+ /**
+ * A max-size stack of the clicked item is put on the cursor.
+ */
+ CLONE_STACK,
+ /**
+ * The inventory is searched for the same material, and they are put
+ * on the cursor up to {@link org.bukkit.Material#getMaxStackSize()}.
+ */
+ COLLECT_TO_CURSOR,
+ /**
+ * An unrecognized ClickType.
+ */
+ UNKNOWN,
+ ;
+}
diff --git a/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java
index 26e1d382..28198b8b 100644
--- a/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java
+++ b/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java
@@ -3,133 +3,219 @@ package org.bukkit.event.inventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.entity.HumanEntity;
-import org.bukkit.event.Cancellable;
+import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.inventory.InventoryType.SlotType;
+import org.bukkit.Location;
import org.bukkit.inventory.ItemStack;
-
-public class InventoryClickEvent extends InventoryEvent implements Cancellable {
+import org.bukkit.scheduler.BukkitScheduler;
+import org.bukkit.plugin.Plugin;
+
+/**
+ * This event is called when a player clicks a slot in an inventory.
+ * <p>
+ * Because InventoryClickEvent occurs within a modification of the Inventory,
+ * not all Inventory related methods are safe to use.
+ * <p>
+ * The following should never be invoked by an EventHandler for
+ * InventoryClickEvent using the HumanEntity or InventoryView associated with
+ * this event:
+ * <ul>
+ * <li>{@link HumanEntity#closeInventory()}
+ * <li>{@link HumanEntity#openInventory(Inventory)}
+ * <li>{@link HumanEntity#openWorkbench(Location, boolean)}
+ * <li>{@link HumanEntity#openEnchanting(Location, boolean)}
+ * <li>{@link InventoryView#close()}
+ * </ul>
+ * To invoke one of these methods, schedule a task using
+ * {@link BukkitScheduler#runTask(Plugin, Runnable)}, which will run the task
+ * on the next tick. Also be aware that this is not an exhaustive list, and
+ * other methods could potentially create issues as well.
+ * <p>
+ * Assuming the EntityHuman associated with this event is an instance of a
+ * Player, manipulating the MaxStackSize or contents of an Inventory will
+ * require an Invocation of {@link Player#updateInventory()}.
+ * <p>
+ * Modifications to slots that are modified by the results of this
+ * InventoryClickEvent can be overwritten. To change these slots, this event
+ * should be cancelled and all desired changes to the inventory applied.
+ * Alternatively, scheduling a task using {@link BukkitScheduler#runTask(
+ * Plugin, Runnable)}, which would execute the task on the next tick, would
+ * work as well.
+ */
+public class InventoryClickEvent extends InventoryInteractEvent {
private static final HandlerList handlers = new HandlerList();
+ private final ClickType click;
+ private final InventoryAction action;
private SlotType slot_type;
- private boolean rightClick, shiftClick;
- private Result result;
private int whichSlot;
private int rawSlot;
private ItemStack current = null;
+ private int hotbarKey = -1;
+
+ @Deprecated
+ public InventoryClickEvent(InventoryView view, SlotType type, int slot, boolean right, boolean shift) {
+ this(view, type, slot, right ? (shift ? ClickType.SHIFT_RIGHT : ClickType.RIGHT) : (shift ? ClickType.SHIFT_LEFT : ClickType.LEFT), InventoryAction.SWAP_WITH_CURSOR);
+ }
- public InventoryClickEvent(InventoryView what, SlotType type, int slot, boolean right, boolean shift) {
- super(what);
+ public InventoryClickEvent(InventoryView view, SlotType type, int slot, ClickType click, InventoryAction action) {
+ super(view);
this.slot_type = type;
- this.rightClick = right;
- this.shiftClick = shift;
- this.result = Result.DEFAULT;
this.rawSlot = slot;
- this.whichSlot = what.convertSlot(slot);
+ this.whichSlot = view.convertSlot(slot);
+ this.click = click;
+ this.action = action;
+ }
+
+ public InventoryClickEvent(InventoryView view, SlotType type, int slot, ClickType click, InventoryAction action, int key) {
+ this(view, type, slot, click, action);
+ this.hotbarKey = key;
}
/**
- * Get the type of slot that was clicked.
- * @return The slot type.
+ * Gets the type of slot that was clicked.
+ *
+ * @return the slot type
*/
public SlotType getSlotType() {
return slot_type;
}
/**
- * Get the current item on the cursor.
- * @return The cursor item
+ * Gets the current ItemStack on the cursor.
+ *
+ * @return the cursor ItemStack
*/
public ItemStack getCursor() {
return getView().getCursor();
}
/**
- * Get the current item in the clicked slot.
- * @return The slot item.
+ * Gets the ItemStack currently in the clicked slot.
+ *
+ * @return the item in the clicked
*/
public ItemStack getCurrentItem() {
- if(slot_type == SlotType.OUTSIDE) return current;
+ if (slot_type == SlotType.OUTSIDE) {
+ return current;
+ }
return getView().getItem(rawSlot);
}
/**
- * @return True if the click is a right-click.
+ * Gets whether or not the ClickType for this event represents a right
+ * click.
+ *
+ * @return true if the ClickType uses the right mouse button.
+ * @see ClickType#isRightClick()
*/
public boolean isRightClick() {
- return rightClick;
+ return click.isRightClick();
}
/**
- * @return True if the click is a left-click.
+ * Gets whether or not the ClickType for this event represents a left
+ * click.
+ *
+ * @return true if the ClickType uses the left mouse button.
+ * @see ClickType#isLeftClick()
*/
public boolean isLeftClick() {
- return !rightClick;
+ return click.isLeftClick();
}
/**
- * Shift can be combined with right-click or left-click as a modifier.
- * @return True if the click is a shift-click.
+ * Gets whether the ClickType for this event indicates that the key was
+ * pressed down when the click was made.
+ *
+ * @return true if the ClickType uses Shift or Ctrl.
+ * @see ClickType#isShiftClick()
*/
public boolean isShiftClick() {
- return shiftClick;
- }
-
- public void setResult(Result newResult) {
- result = newResult;
- }
-
- public Result getResult() {
- return result;
+ return click.isShiftClick();
}
/**
- * Get the player who performed the click.
- * @return The clicking player.
+ * Sets the item on the cursor.
+ *
+ * @param stack the new cursor item
+ * @deprecated This changes the ItemStack in their hand before any
+ * calculations are applied to the Inventory, which has a tendency to
+ * create inconsistencies between the Player and the server, and to
+ * make unexpected changes in the behavior of the clicked Inventory.
*/
- public HumanEntity getWhoClicked() {
- return getView().getPlayer();
+ @Deprecated
+ public void setCursor(ItemStack stack) {
+ getView().setCursor(stack);
}
/**
- * Set the item on the cursor.
- * @param what The new cursor item.
+ * Sets the ItemStack currently in the clicked slot.
+ *
+ * @param stack the item to be placed in the current slot
*/
- public void setCursor(ItemStack what) {
- getView().setCursor(what);
+ public void setCurrentItem(ItemStack stack) {
+ if (slot_type == SlotType.OUTSIDE) {
+ current = stack;
+ } else {
+ getView().setItem(rawSlot, stack);
+ }
}
/**
- * Set the current item in the slot.
- * @param what The new slot item.
+ * The slot number that was clicked, ready for passing to
+ * {@link Inventory#getItem(int)}. Note that there may be two slots with
+ * the same slot number, since a view links two different inventories.
+ *
+ * @return The slot number.
*/
- public void setCurrentItem(ItemStack what) {
- if(slot_type == SlotType.OUTSIDE) current = what;
- else getView().setItem(rawSlot, what);
+ public int getSlot() {
+ return whichSlot;
}
- public boolean isCancelled() {
- return result == Result.DENY;
+ /**
+ * The raw slot number clicked, ready for passing to {@link InventoryView
+ * #getItem(int)} This slot number is unique for the view.
+ *
+ * @return the slot number
+ */
+ public int getRawSlot() {
+ return rawSlot;
}
- public void setCancelled(boolean toCancel) {
- result = toCancel ? Result.DENY : Result.ALLOW;
+ /**
+ * If the ClickType is NUMBER_KEY, this method will return the index of
+ * the pressed key (0-8).
+ *
+ * @return the number on the key minus 1 (range 0-8); or -1 if not
+ * a NUMBER_KEY action
+ */
+ public int getHotbarButton() {
+ return hotbarKey;
}
/**
- * The slot number that was clicked, ready for passing to {@link Inventory#getItem(int)}. Note
- * that there may be two slots with the same slot number, since a view links two different inventories.
- * @return The slot number.
+ * Gets the InventoryAction that triggered this event.
+ * <p>
+ * This action cannot be changed, and represents what the normal outcome
+ * of the event will be. To change the behavior of this
+ * InventoryClickEvent, changes must be manually applied.
+ *
+ * @return the InventoryAction that triggered this event.
*/
- public int getSlot() {
- return whichSlot;
+ public InventoryAction getAction() {
+ return action;
}
/**
- * The raw slot number, which is unique for the view.
- * @return The slot number.
+ * Gets the ClickType for this event.
+ * <p>
+ * This is insulated against changes to the inventory by other plugins.
+ *
+ * @return the type of inventory click
*/
- public int getRawSlot() {
- return rawSlot;
+ public ClickType getClick() {
+ return click;
}
@Override
diff --git a/src/main/java/org/bukkit/event/inventory/InventoryCreativeEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryCreativeEvent.java
new file mode 100644
index 00000000..da7dffc0
--- /dev/null
+++ b/src/main/java/org/bukkit/event/inventory/InventoryCreativeEvent.java
@@ -0,0 +1,27 @@
+package org.bukkit.event.inventory;
+
+import org.bukkit.event.inventory.InventoryType.SlotType;
+import org.bukkit.inventory.InventoryView;
+import org.bukkit.inventory.ItemStack;
+
+/**
+ * This event is called when a player in creative mode puts down or picks up
+ * an item in their inventory / hotbar and when they drop items from their
+ * Inventory while in creative mode.
+ */
+public class InventoryCreativeEvent extends InventoryClickEvent {
+ private ItemStack item;
+
+ public InventoryCreativeEvent(InventoryView what, SlotType type, int slot, ItemStack newItem) {
+ super(what, type, slot, ClickType.CREATIVE, InventoryAction.PLACE_ALL);
+ this.item = newItem;
+ }
+
+ public ItemStack getCursor() {
+ return item;
+ }
+
+ public void setCursor(ItemStack item) {
+ this.item = item;
+ }
+}
diff --git a/src/main/java/org/bukkit/event/inventory/InventoryDragEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryDragEvent.java
new file mode 100644
index 00000000..e7e54a75
--- /dev/null
+++ b/src/main/java/org/bukkit/event/inventory/InventoryDragEvent.java
@@ -0,0 +1,164 @@
+package org.bukkit.event.inventory;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang.Validate;
+import org.bukkit.Location;
+import org.bukkit.entity.HumanEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.HandlerList;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryView;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.scheduler.BukkitScheduler;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This event is called when the player drags an item in their cursor across
+ * the inventory. The ItemStack is distributed across the slots the
+ * HumanEntity dragged over. The method of distribution is described by the
+ * DragType returned by {@link #getType()}.
+ * <p>
+ * Canceling this event will result in none of the changes described in
+ * {@link #getNewItems()} being applied to the Inventory.
+ * <p>
+ * Because InventoryDragEvent occurs within a modification of the Inventory,
+ * not all Inventory related methods are safe to use.
+ * <p>
+ * The following should never be invoked by an EventHandler for
+ * InventoryDragEvent using the HumanEntity or InventoryView associated with
+ * this event.
+ * <ul>
+ * <li>{@link HumanEntity#closeInventory()}
+ * <li>{@link HumanEntity#openInventory(Inventory)}
+ * <li>{@link HumanEntity#openWorkbench(Location, boolean)}
+ * <li>{@link HumanEntity#openEnchanting(Location, boolean)}
+ * <li>{@link InventoryView#close()}
+ * </ul>
+ * To invoke one of these methods, schedule a task using
+ * {@link BukkitScheduler#runTask(Plugin, Runnable)}, which will run the task
+ * on the next tick. Also be aware that this is not an exhaustive list, and
+ * other methods could potentially create issues as well.
+ * <p>
+ * Assuming the EntityHuman associated with this event is an instance of a
+ * Player, manipulating the MaxStackSize or contents of an Inventory will
+ * require an Invocation of {@link Player#updateInventory()}.
+ * <p>
+ * Any modifications to slots that are modified by the results of this
+ * InventoryDragEvent will be overwritten. To change these slots, this event
+ * should be cancelled and the changes applied. Alternatively, scheduling a
+ * task using {@link BukkitScheduler#runTask(Plugin, Runnable)}, which would
+ * execute the task on the next tick, would work as well.
+ */
+public class InventoryDragEvent extends InventoryInteractEvent {
+ private static final HandlerList handlers = new HandlerList();
+ private final DragType type;
+ private final Map<Integer, ItemStack> addedItems;
+ private final Set<Integer> containerSlots;
+ private final ItemStack oldCursor;
+ private ItemStack newCursor;
+
+ public InventoryDragEvent(InventoryView what, ItemStack newCursor, ItemStack oldCursor, boolean right, Map<Integer, ItemStack> slots) {
+ super(what);
+
+ Validate.notNull(oldCursor);
+ Validate.notNull(slots);
+
+ type = right ? DragType.SINGLE : DragType.EVEN;
+ this.newCursor = newCursor;
+ this.oldCursor = oldCursor;
+ this.addedItems = slots;
+ ImmutableSet.Builder<Integer> b = ImmutableSet.builder();
+ for (Integer slot : slots.keySet()) {
+ b.add(what.convertSlot(slot));
+ }
+ this.containerSlots = b.build();
+ }
+
+ /**
+ * Gets all items to be added to the inventory in this drag.
+ *
+ * @return map from raw slot id to new ItemStack
+ */
+ public Map<Integer, ItemStack> getNewItems() {
+ return Collections.unmodifiableMap(addedItems);
+ }
+
+ /**
+ * Gets the raw slot ids to be changed in this drag.
+ *
+ * @return list of raw slot ids, suitable for getView().getItem(int)
+ */
+ public Set<Integer> getRawSlots() {
+ return addedItems.keySet();
+ }
+
+ /**
+ * Gets the slots to be changed in this drag.
+ *
+ * @return list of converted slot ids, suitable for {@link
+ * org.bukkit.inventory.Inventory#getItem(int)}.
+ */
+ public Set<Integer> getInventorySlots() {
+ return containerSlots;
+ }
+
+ /**
+ * Gets the result cursor after the drag is done. The returned value is
+ * mutable.
+ *
+ * @return the result cursor
+ */
+ public ItemStack getCursor() {
+ return newCursor;
+ }
+
+ /**
+ * Sets the result cursor after the drag is done.
+ * <p>
+ * Changing this item stack changes the cursor item. Note that changing
+ * the affected "dragged" slots does not change this ItemStack, nor does
+ * changing this ItemStack affect the "dragged" slots.
+ *
+ * @param newCursor the new cursor ItemStack
+ */
+ public void setCursor(ItemStack newCursor) {
+ this.newCursor = newCursor;
+ }
+
+ /**
+ * Gets an ItemStack representing the cursor prior to any modifications
+ * as a result of this drag.
+ *
+ * @return the original cursor
+ */
+ public ItemStack getOldCursor() {
+ return oldCursor.clone();
+ }
+
+ /**
+ * Gets the DragType that describes the behavior of ItemStacks placed
+ * after this InventoryDragEvent.
+ * <p>
+ * The ItemStacks and the raw slots that they're being applied to can be
+ * found using {@link #getNewItems()}.
+ *
+ * @return the DragType of this InventoryDragEvent
+ */
+ public DragType getType() {
+ return type;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}
diff --git a/src/main/java/org/bukkit/event/inventory/InventoryInteractEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryInteractEvent.java
new file mode 100644
index 00000000..8624f8d7
--- /dev/null
+++ b/src/main/java/org/bukkit/event/inventory/InventoryInteractEvent.java
@@ -0,0 +1,78 @@
+package org.bukkit.event.inventory;
+
+import org.bukkit.entity.HumanEntity;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.Event.Result;
+import org.bukkit.inventory.InventoryView;
+import org.bukkit.inventory.ItemStack;
+
+/**
+ * An abstract base class for events that describe an interaction between a
+ * HumanEntity and the contents of an Inventory.
+ */
+public abstract class InventoryInteractEvent extends InventoryEvent implements Cancellable {
+ private Result result = Result.DEFAULT;
+
+ public InventoryInteractEvent(InventoryView transaction) {
+ super(transaction);
+ }
+
+ /**
+ * Gets the player who performed the click.
+ *
+ * @return The clicking player.
+ */
+ public HumanEntity getWhoClicked() {
+ return getView().getPlayer();
+ }
+
+ /**
+ * Sets the result of this event. This will change whether or not this
+ * event is considered cancelled.
+ *
+ * @see #isCancelled()
+ * @param newResult the new {@link Result} for this event
+ */
+ public void setResult(Result newResult) {
+ result = newResult;
+ }
+
+ /**
+ * Gets the {@link Result} of this event. The Result describes the
+ * behavior that will be applied to the inventory in relation to this
+ * event.
+ *
+ * @return the Result of this event.
+ */
+ public Result getResult() {
+ return result;
+ }
+
+ /**
+ * Gets whether or not this event is cancelled. This is based off of the
+ * Result value returned by {@link #getResult()}. Result.ALLOW and
+ * Result.DEFAULT will result in a returned value of false, but
+ * Result.DENY will result in a returned value of true.
+ * <p>
+ * {@inheritDoc}
+ *
+ * @return whether the event is cancelled
+ */
+ public boolean isCancelled() {
+ return getResult() == Result.DENY;
+ }
+
+ /**
+ * Proxy method to {@link #setResult(Event.Result)} for the Cancellable
+ * interface. {@link #setResult(Event.Result)} is preferred, as it allows
+ * you to specify the Result beyond Result.DENY and Result.ALLOW.
+ * <p>
+ * {@inheritDoc}
+ *
+ * @param toCancel result becomes DENY if true, ALLOW if false
+ */
+ public void setCancelled(boolean toCancel) {
+ setResult(toCancel ? Result.DENY : Result.ALLOW);
+ }
+
+}