summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/main/java/net/minecraft/server/Container.java48
-rw-r--r--src/main/java/net/minecraft/server/PlayerConnection.java350
2 files changed, 326 insertions, 72 deletions
diff --git a/src/main/java/net/minecraft/server/Container.java b/src/main/java/net/minecraft/server/Container.java
index e9ba2f42..d48282cf 100644
--- a/src/main/java/net/minecraft/server/Container.java
+++ b/src/main/java/net/minecraft/server/Container.java
@@ -7,7 +7,12 @@ import java.util.List;
import java.util.Set;
// CraftBukkit start
+import java.util.HashMap;
+import java.util.Map;
import org.bukkit.craftbukkit.inventory.CraftInventory;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.event.Event.Result;
+import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.inventory.InventoryView;
// CraftBukkit end
@@ -18,7 +23,7 @@ public abstract class Container {
public int windowId = 0;
private short a = 0;
private int f = -1;
- private int g = 0;
+ public int g = 0; // CraftBukkit - private -> public
private final Set h = new HashSet();
protected List listeners = new ArrayList();
private Set i = new HashSet();
@@ -140,6 +145,7 @@ public abstract class Container {
l = playerinventory.getCarried().count;
Iterator iterator = this.h.iterator();
+ Map<Integer, ItemStack> draggedSlots = new HashMap<Integer, ItemStack>(); // CraftBukkit - Store slots from drag in map (raw slot id -> new stack)
while (iterator.hasNext()) {
Slot slot1 = (Slot) iterator.next();
@@ -157,16 +163,46 @@ public abstract class Container {
}
l -= itemstack2.count - j1;
- slot1.set(itemstack2);
+ draggedSlots.put(slot1.g, itemstack2); // CraftBukkit - Put in map instead of setting, Should be Slot.rawSlotIndex
}
}
- itemstack1.count = l;
- if (itemstack1.count <= 0) {
- itemstack1 = null;
+ // CraftBukkit start - InventoryDragEvent
+ InventoryView view = getBukkitView();
+ org.bukkit.inventory.ItemStack newcursor = CraftItemStack.asCraftMirror(itemstack1);
+ newcursor.setAmount(l);
+ Map<Integer, org.bukkit.inventory.ItemStack> eventmap = new HashMap<Integer, org.bukkit.inventory.ItemStack>();
+ for (Map.Entry<Integer, ItemStack> ditem : draggedSlots.entrySet()) {
+ eventmap.put(ditem.getKey(), CraftItemStack.asBukkitCopy(ditem.getValue()));
}
- playerinventory.setCarried(itemstack1);
+ // It's essential that we set the cursor to the new value here to prevent item duplication if a plugin closes the inventory.
+ ItemStack oldCursor = playerinventory.getCarried();
+ playerinventory.setCarried(CraftItemStack.asNMSCopy(newcursor));
+
+ InventoryDragEvent event = new InventoryDragEvent(view, (newcursor.getType() != org.bukkit.Material.AIR ? newcursor : null), CraftItemStack.asBukkitCopy(oldCursor), this.f == 1, eventmap); // Should be dragButton
+ entityhuman.world.getServer().getPluginManager().callEvent(event);
+
+ // Whether or not a change was made to the inventory that requires an update.
+ boolean needsUpdate = event.getResult() != Result.DEFAULT;
+
+ if (event.getResult() != Result.DENY) {
+ for (Map.Entry<Integer, ItemStack> dslot : draggedSlots.entrySet()) {
+ view.setItem(dslot.getKey(), CraftItemStack.asBukkitCopy(dslot.getValue()));
+ }
+ // The only time the carried item will be set to null is if the inventory is closed by the server.
+ // If the inventory is closed by the server, then the cursor items are dropped. This is why we change the cursor early.
+ if (playerinventory.getCarried() != null) {
+ playerinventory.setCarried(CraftItemStack.asNMSCopy(event.getCursor()));
+ needsUpdate = true;
+
+ }
+ }
+
+ if (needsUpdate && entityhuman instanceof EntityPlayer) {
+ ((EntityPlayer) entityhuman).updateInventory(this);
+ }
+ // CraftBukkit end
}
this.d();
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
index 5d103824..42dbc56f 100644
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
@@ -21,12 +21,18 @@ import org.bukkit.craftbukkit.util.Waitable;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.SignChangeEvent;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.event.inventory.CraftItemEvent;
+import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryCreativeEvent;
+import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryType.SlotType;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerAnimationEvent;
@@ -1153,53 +1159,259 @@ public class PlayerConnection extends Connection {
if (this.player.activeContainer.windowId == packet102windowclick.a && this.player.activeContainer.c(this.player)) {
// CraftBukkit start - Call InventoryClickEvent
- if (packet102windowclick.slot == -1) {
- // Vanilla doesn't do anything with this, neither should we
+ if (packet102windowclick.slot < -1 && packet102windowclick.slot != -999) {
return;
}
InventoryView inventory = this.player.activeContainer.getBukkitView();
SlotType type = CraftInventoryView.getSlotType(inventory, packet102windowclick.slot);
- InventoryClickEvent event = new InventoryClickEvent(inventory, type, packet102windowclick.slot, packet102windowclick.button != 0, packet102windowclick.shift == 1);
- org.bukkit.inventory.Inventory top = inventory.getTopInventory();
- if (packet102windowclick.slot == 0 && top instanceof CraftingInventory) {
- org.bukkit.inventory.Recipe recipe = ((CraftingInventory) top).getRecipe();
- if (recipe != null) {
- event = new org.bukkit.event.inventory.CraftItemEvent(recipe, inventory, type, packet102windowclick.slot, packet102windowclick.button != 0, packet102windowclick.shift == 1);
- }
- }
- server.getPluginManager().callEvent(event);
+ InventoryClickEvent event = null;
+ ClickType click = ClickType.UNKNOWN;
+ InventoryAction action = InventoryAction.UNKNOWN;
ItemStack itemstack = null;
- boolean defaultBehaviour = false;
-
- switch(event.getResult()) {
- case DEFAULT:
- itemstack = this.player.activeContainer.clickItem(packet102windowclick.slot, packet102windowclick.button, packet102windowclick.shift, this.player);
- defaultBehaviour = true;
- break;
- case DENY: // Deny any change, including changes from the event
- break;
- case ALLOW: // Allow changes unconditionally
- org.bukkit.inventory.ItemStack cursor = event.getCursor();
- if (cursor == null) {
- this.player.inventory.setCarried((ItemStack) null);
- } else {
- this.player.inventory.setCarried(CraftItemStack.asNMSCopy(cursor));
+
+ if (packet102windowclick.slot == -1) {
+ type = SlotType.OUTSIDE; // override
+ click = packet102windowclick.button == 0 ? ClickType.WINDOW_BORDER_LEFT : ClickType.WINDOW_BORDER_RIGHT;
+ action = InventoryAction.NOTHING;
+ } else if (packet102windowclick.shift == 0) {
+ if (packet102windowclick.button == 0) {
+ click = ClickType.LEFT;
+ } else if (packet102windowclick.button == 1) {
+ click = ClickType.RIGHT;
+ }
+ if (packet102windowclick.button == 0 || packet102windowclick.button == 1) {
+ action = InventoryAction.NOTHING; // Don't want to repeat ourselves
+ if (packet102windowclick.slot == -999) {
+ if (player.inventory.getCarried() != null) {
+ action = packet102windowclick.button == 0 ? InventoryAction.DROP_ALL_CURSOR : InventoryAction.DROP_ONE_CURSOR;
+ }
+ } else {
+ Slot slot = this.player.activeContainer.getSlot(packet102windowclick.slot);
+ if (slot != null) {
+ ItemStack clickedItem = slot.getItem();
+ ItemStack cursor = player.inventory.getCarried();
+ if (clickedItem == null) {
+ if (cursor != null) {
+ action = packet102windowclick.button == 0 ? InventoryAction.PLACE_ALL : InventoryAction.PLACE_ONE;
+ }
+ } else if (slot.a(player)) { // Should be Slot.isPlayerAllowed
+ if (cursor == null) {
+ action = packet102windowclick.button == 0 ? InventoryAction.PICKUP_ALL : InventoryAction.PICKUP_HALF;
+ } else if (slot.isAllowed(cursor)) { // Should be Slot.isItemAllowed
+ if (clickedItem.doMaterialsMatch(cursor) && ItemStack.equals(clickedItem, cursor)) {
+ int toPlace = packet102windowclick.button == 0 ? cursor.count : 1;
+ toPlace = Math.min(toPlace, clickedItem.getMaxStackSize() - clickedItem.count);
+ toPlace = Math.min(toPlace, slot.inventory.getMaxStackSize() - clickedItem.count);
+ if (toPlace == 1) {
+ action = InventoryAction.PLACE_ONE;
+ } else if (toPlace == cursor.count) {
+ action = InventoryAction.PLACE_ALL;
+ } else if (toPlace < 0) {
+ action = toPlace != -1 ? InventoryAction.PICKUP_SOME : InventoryAction.PICKUP_ONE; // this happens with oversized stacks
+ } else if (toPlace != 0) {
+ action = InventoryAction.PLACE_SOME;
+ }
+ } else if (cursor.count <= slot.a()) { // Should be Slot.getMaxStackSize()
+ action = InventoryAction.SWAP_WITH_CURSOR;
+ }
+ } else if (cursor.id == clickedItem.id && (!cursor.usesData() || cursor.getData() == clickedItem.getData()) && ItemStack.equals(cursor, clickedItem)) {
+ if (clickedItem.count >= 0) {
+ if (clickedItem.count + cursor.count <= cursor.getMaxStackSize()) {
+ // As of 1.5, this is result slots only
+ action = InventoryAction.PICKUP_ALL;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else if (packet102windowclick.shift == 1) {
+ if (packet102windowclick.button == 0) {
+ click = ClickType.SHIFT_LEFT;
+ } else if (packet102windowclick.button == 1) {
+ click = ClickType.SHIFT_RIGHT;
+ }
+ if (packet102windowclick.button == 0 || packet102windowclick.button == 1) {
+ if (packet102windowclick.slot < 0) {
+ action = InventoryAction.NOTHING;
+ } else {
+ Slot slot = this.player.activeContainer.getSlot(packet102windowclick.slot);
+ if (slot != null && slot.a(this.player) && slot.d()) { // Should be Slot.hasItem()
+ action = InventoryAction.MOVE_TO_OTHER_INVENTORY;
+ } else {
+ action = InventoryAction.NOTHING;
+ }
+ }
+ }
+ } else if (packet102windowclick.shift == 2) {
+ if (packet102windowclick.button >= 0 && packet102windowclick.button < 9) {
+ click = ClickType.NUMBER_KEY;
+ Slot clickedSlot = this.player.activeContainer.getSlot(packet102windowclick.slot);
+ if (clickedSlot.a(player)) {
+ ItemStack hotbar = this.player.inventory.getItem(packet102windowclick.button);
+ boolean canCleanSwap = hotbar == null || (clickedSlot.inventory == player.inventory && clickedSlot.isAllowed(hotbar)); // the slot will accept the hotbar item
+ if (clickedSlot.d()) {
+ if (canCleanSwap) {
+ action = InventoryAction.HOTBAR_SWAP;
+ } else {
+ int firstEmptySlot = player.inventory.j(); // Should be Inventory.firstEmpty()
+ if (firstEmptySlot > -1) {
+ action = InventoryAction.HOTBAR_MOVE_AND_READD;
+ } else {
+ action = InventoryAction.NOTHING; // This is not sane! Mojang: You should test for other slots of same type
+ }
+ }
+ } else if (!clickedSlot.d() && hotbar != null && clickedSlot.isAllowed(hotbar)) {
+ action = InventoryAction.HOTBAR_SWAP;
+ } else {
+ action = InventoryAction.NOTHING;
+ }
+ } else {
+ action = InventoryAction.NOTHING;
+ }
+ // Special constructor for number key
+ event = new InventoryClickEvent(inventory, type, packet102windowclick.slot, click, action, packet102windowclick.button);
}
- org.bukkit.inventory.ItemStack item = event.getCurrentItem();
- if (item != null) {
- itemstack = CraftItemStack.asNMSCopy(item);
+ } else if (packet102windowclick.shift == 3) {
+ if (packet102windowclick.button == 2) {
+ click = ClickType.MIDDLE;
if (packet102windowclick.slot == -999) {
- this.player.drop(itemstack);
+ action = InventoryAction.NOTHING;
} else {
- this.player.activeContainer.getSlot(packet102windowclick.slot).set(itemstack);
+ Slot slot = this.player.activeContainer.getSlot(packet102windowclick.slot);
+ if (slot != null && slot.d() && player.abilities.canInstantlyBuild && player.inventory.getCarried() == null) {
+ action = InventoryAction.CLONE_STACK;
+ } else {
+ action = InventoryAction.NOTHING;
+ }
+ }
+ } else {
+ click = ClickType.UNKNOWN;
+ action = InventoryAction.UNKNOWN;
+ }
+ } else if (packet102windowclick.shift == 4) {
+ if (packet102windowclick.slot >= 0) {
+ if (packet102windowclick.button == 0) {
+ click = ClickType.DROP;
+ Slot slot = this.player.activeContainer.getSlot(packet102windowclick.slot);
+ if (slot != null && slot.d() && slot.a(player) && slot.getItem() != null && slot.getItem().id != 0) {
+ action = InventoryAction.DROP_ONE_SLOT;
+ } else {
+ action = InventoryAction.NOTHING;
+ }
+ } else if (packet102windowclick.button == 1) {
+ click = ClickType.CONTROL_DROP;
+ Slot slot = this.player.activeContainer.getSlot(packet102windowclick.slot);
+ if (slot != null && slot.d() && slot.a(player) && slot.getItem() != null && slot.getItem().id != 0) {
+ action = InventoryAction.DROP_ALL_SLOT;
+ } else {
+ action = InventoryAction.NOTHING;
+ }
+ }
+ } else {
+ // Sane default (because this happens when they are holding nothing. Don't ask why.)
+ click = ClickType.LEFT;
+ if (packet102windowclick.button == 1) {
+ click = ClickType.RIGHT;
+ }
+ action = InventoryAction.NOTHING;
+ }
+ } else if (packet102windowclick.shift == 5) {
+ itemstack = this.player.activeContainer.clickItem(packet102windowclick.slot, packet102windowclick.button, 5, this.player);
+ } else if (packet102windowclick.shift == 6) {
+ click = ClickType.DOUBLE_CLICK;
+ action = InventoryAction.NOTHING;
+ if (packet102windowclick.slot >= 0 && this.player.inventory.getCarried() != null) {
+ ItemStack cursor = this.player.inventory.getCarried();
+ action = InventoryAction.NOTHING;
+ // Quick check for if we have any of the item
+ if (inventory.getTopInventory().contains(cursor.id) || inventory.getBottomInventory().contains(cursor.id)) {
+ action = InventoryAction.COLLECT_TO_CURSOR;
+ }
+ }
+ }
+ // TODO check on updates
+
+ if (packet102windowclick.shift != 5) {
+ if (click == ClickType.NUMBER_KEY) {
+ event = new InventoryClickEvent(inventory, type, packet102windowclick.slot, click, action, packet102windowclick.button);
+ } else {
+ event = new InventoryClickEvent(inventory, type, packet102windowclick.slot, click, action);
+ }
+
+ org.bukkit.inventory.Inventory top = inventory.getTopInventory();
+ if (packet102windowclick.slot == 0 && top instanceof CraftingInventory) {
+ org.bukkit.inventory.Recipe recipe = ((CraftingInventory) top).getRecipe();
+ if (recipe != null) {
+ if (click == ClickType.NUMBER_KEY) {
+ event = new CraftItemEvent(recipe, inventory, type, packet102windowclick.slot, click, action, packet102windowclick.button);
+ } else {
+ event = new CraftItemEvent(recipe, inventory, type, packet102windowclick.slot, click, action);
+ }
}
- } else if (packet102windowclick.slot != -999) {
- this.player.activeContainer.getSlot(packet102windowclick.slot).set((ItemStack) null);
}
- break;
+
+ server.getPluginManager().callEvent(event);
+
+ switch (event.getResult()) {
+ case ALLOW:
+ case DEFAULT:
+ itemstack = this.player.activeContainer.clickItem(packet102windowclick.slot, packet102windowclick.button, packet102windowclick.shift, this.player);
+ break;
+ case DENY:
+ /* Needs enum constructor in InventoryAction
+ if (action.modifiesOtherSlots()) {
+
+ } else {
+ if (action.modifiesCursor()) {
+ this.player.playerConnection.sendPacket(new Packet103SetSlot(-1, -1, this.player.inventory.getCarried()));
+ }
+ if (action.modifiesClicked()) {
+ this.player.playerConnection.sendPacket(new Packet103SetSlot(this.player.activeContainer.windowId, packet102windowclick.slot, this.player.activeContainer.getSlot(packet102windowclick.slot).getItem()));
+ }
+ }*/
+ switch (action) {
+ // Modified other slots
+ case MOVE_TO_OTHER_INVENTORY:
+ case HOTBAR_MOVE_AND_READD:
+ case HOTBAR_SWAP:
+ case COLLECT_TO_CURSOR:
+ case UNKNOWN:
+ this.player.updateInventory(this.player.activeContainer);
+ break;
+ // Modified cursor and clicked
+ case PICKUP_ALL:
+ case PICKUP_SOME:
+ case PICKUP_HALF:
+ case PICKUP_ONE:
+ case PLACE_ALL:
+ case PLACE_SOME:
+ case PLACE_ONE:
+ case SWAP_WITH_CURSOR:
+ this.player.playerConnection.sendPacket(new Packet103SetSlot(-1, -1, this.player.inventory.getCarried()));
+ this.player.playerConnection.sendPacket(new Packet103SetSlot(this.player.activeContainer.windowId, packet102windowclick.slot, this.player.activeContainer.getSlot(packet102windowclick.slot).getItem()));
+ break;
+ // Modified clicked only
+ case DROP_ALL_SLOT:
+ case DROP_ONE_SLOT:
+ this.player.playerConnection.sendPacket(new Packet103SetSlot(this.player.activeContainer.windowId, packet102windowclick.slot, this.player.activeContainer.getSlot(packet102windowclick.slot).getItem()));
+ break;
+ // Modified cursor only
+ case DROP_ALL_CURSOR:
+ case DROP_ONE_CURSOR:
+ case CLONE_STACK:
+ this.player.playerConnection.sendPacket(new Packet103SetSlot(-1, -1, this.player.inventory.getCarried()));
+ break;
+ // Nothing
+ case NOTHING:
+ break;
+ }
+ return;
+ }
}
// CraftBukkit end
@@ -1247,40 +1459,46 @@ public class PlayerConnection extends Connection {
boolean flag3 = itemstack == null || itemstack.getData() >= 0 && itemstack.getData() >= 0 && itemstack.count <= 64 && itemstack.count > 0;
// CraftBukkit start - Call click event
- org.bukkit.entity.HumanEntity player = this.player.getBukkitEntity();
- InventoryView inventory = new CraftInventoryView(player, player.getInventory(), this.player.defaultContainer);
- SlotType slot = SlotType.QUICKBAR;
- if (packet107setcreativeslot.slot == -1) {
- slot = SlotType.OUTSIDE;
- }
-
- InventoryClickEvent event = new InventoryClickEvent(inventory, slot, slot == SlotType.OUTSIDE ? -999 : packet107setcreativeslot.slot, false, false);
- server.getPluginManager().callEvent(event);
- org.bukkit.inventory.ItemStack item = event.getCurrentItem();
-
- switch (event.getResult()) {
- case ALLOW:
- if (slot == SlotType.QUICKBAR) {
- if (item == null) {
- this.player.defaultContainer.setItem(packet107setcreativeslot.slot, (ItemStack) null);
- } else {
- this.player.defaultContainer.setItem(packet107setcreativeslot.slot, CraftItemStack.asNMSCopy(item));
+ if (flag1 || flag) { // Insist on valid slot
+ ItemStack existingItem = this.player.defaultContainer.getSlot(packet107setcreativeslot.slot).getItem();
+ // Client assumes that the server forgets the contents of the inventory. It doesn't.
+ if (!ItemStack.matches(existingItem, packet107setcreativeslot.b)) {
+
+ org.bukkit.entity.HumanEntity player = this.player.getBukkitEntity();
+ InventoryView inventory = new CraftInventoryView(player, player.getInventory(), this.player.defaultContainer);
+ org.bukkit.inventory.ItemStack item = CraftItemStack.asBukkitCopy(packet107setcreativeslot.b); // Should be packet107setcreativeslot.newitem
+
+ SlotType type = SlotType.QUICKBAR;
+ if (flag) {
+ type = SlotType.OUTSIDE;
+ } else if (packet107setcreativeslot.slot < 36) {
+ if (packet107setcreativeslot.slot >= 5 && packet107setcreativeslot.slot < 9) {
+ type = SlotType.ARMOR;
+ } else {
+ type = SlotType.CONTAINER;
+ }
+ }
+ InventoryCreativeEvent event = new InventoryCreativeEvent(inventory, type, flag ? -999 : packet107setcreativeslot.slot, item);
+ server.getPluginManager().callEvent(event);
+
+ itemstack = CraftItemStack.asNMSCopy(event.getCursor());
+
+ switch (event.getResult()) {
+ case ALLOW:
+ // Plugin cleared the id / stacksize checks
+ flag2 = flag3 = true;
+ break;
+ case DEFAULT:
+ break;
+ case DENY:
+ // Reset the slot
+ if (packet107setcreativeslot.slot >= 0) {
+ this.player.playerConnection.sendPacket(new Packet103SetSlot(this.player.defaultContainer.windowId, packet107setcreativeslot.slot, this.player.defaultContainer.getSlot(packet107setcreativeslot.slot).getItem()));
+ this.player.playerConnection.sendPacket(new Packet103SetSlot(-1, -1, null));
+ }
+ return;
}
- } else if (item != null) {
- this.player.drop(CraftItemStack.asNMSCopy(item));
- }
- return;
- case DENY:
- // TODO: Will this actually work?
- if (packet107setcreativeslot.slot > -1) {
- this.player.playerConnection.sendPacket(new Packet103SetSlot(this.player.defaultContainer.windowId, packet107setcreativeslot.slot, CraftItemStack.asNMSCopy(item)));
}
- return;
- case DEFAULT:
- // We do the stuff below
- break;
- default:
- return;
}
// CraftBukkit end