summaryrefslogtreecommitdiffstats
path: root/nms-patches/Container.patch
blob: ae9b1e78c9f3f5bd6a100afec16d6002460a25e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
--- a/net/minecraft/server/Container.java
+++ b/net/minecraft/server/Container.java
@@ -7,6 +7,17 @@
 import java.util.Set;
 import javax.annotation.Nullable;
 
+// 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.event.inventory.InventoryType;
+import org.bukkit.inventory.InventoryView;
+// CraftBukkit end
+
 public abstract class Container {
 
     public NonNullList<ItemStack> items = NonNullList.a();
@@ -18,6 +29,18 @@
     protected List<ICrafting> listeners = Lists.newArrayList();
     private final Set<EntityHuman> i = Sets.newHashSet();
 
+    // CraftBukkit start
+    public boolean checkReachable = true;
+    public abstract InventoryView getBukkitView();
+    public void transferTo(Container other, org.bukkit.craftbukkit.entity.CraftHumanEntity player) {
+        InventoryView source = this.getBukkitView(), destination = other.getBukkitView();
+        ((CraftInventory) source.getTopInventory()).getInventory().onClose(player);
+        ((CraftInventory) source.getBottomInventory()).getInventory().onClose(player);
+        ((CraftInventory) destination.getTopInventory()).getInventory().onOpen(player);
+        ((CraftInventory) destination.getBottomInventory()).getInventory().onOpen(player);
+    }
+    // CraftBukkit end
+
     public Container() {}
 
     protected Slot a(Slot slot) {
@@ -128,6 +151,7 @@
                     k = playerinventory.getCarried().getCount();
                     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();
                         ItemStack itemstack3 = playerinventory.getCarried();
@@ -143,12 +167,48 @@
                             }
 
                             k -= itemstack4.getCount() - j1;
-                            slot1.set(itemstack4);
+                            // slot1.set(itemstack4);
+                            draggedSlots.put(slot1.rawSlotIndex, itemstack4); // CraftBukkit - Put in map instead of setting
                         }
                     }
 
-                    itemstack2.setCount(k);
-                    playerinventory.setCarried(itemstack2);
+                    // CraftBukkit start - InventoryDragEvent
+                    InventoryView view = getBukkitView();
+                    org.bukkit.inventory.ItemStack newcursor = CraftItemStack.asCraftMirror(itemstack2);
+                    newcursor.setAmount(k);
+                    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()));
+                    }
+
+                    // 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.dragType == 1, eventmap);
+                    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;
+                        }
+                    } else {
+                        playerinventory.setCarried(oldCursor);
+                    }
+
+                    if (needsUpdate && entityhuman instanceof EntityPlayer) {
+                        ((EntityPlayer) entityhuman).updateInventory(this);
+                    }
+                    // CraftBukkit end
                 }
 
                 this.c();
@@ -165,8 +225,11 @@
                 if (i == -999) {
                     if (!playerinventory.getCarried().isEmpty()) {
                         if (j == 0) {
-                            entityhuman.drop(playerinventory.getCarried(), true);
+                            // CraftBukkit start
+                            ItemStack carried = playerinventory.getCarried();
                             playerinventory.setCarried(ItemStack.a);
+                            entityhuman.drop(carried, true);
+                            // CraftBukkit start
                         }
 
                         if (j == 1) {
@@ -254,6 +317,15 @@
                         }
 
                         slot2.f();
+                        // CraftBukkit start - Make sure the client has the right slot contents
+                        if (entityhuman instanceof EntityPlayer && slot2.getMaxStackSize() != 64) {
+                            ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutSetSlot(this.windowId, slot2.rawSlotIndex, slot2.getItem()));
+                            // Updating a crafting inventory makes the client reset the result slot, have to send it again
+                            if (this.getBukkitView().getType() == InventoryType.WORKBENCH || this.getBukkitView().getType() == InventoryType.CRAFTING) {
+                                ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutSetSlot(this.windowId, 0, this.getSlot(0).getItem()));
+                            }
+                        }
+                        // CraftBukkit end
                     }
                 }
             } else if (inventoryclicktype == InventoryClickType.SWAP && j >= 0 && j < 9) {
@@ -565,6 +637,7 @@
             if (inventorycraftresult.a(world, entityplayer, irecipe) && irecipe != null) {
                 itemstack = irecipe.craftItem(iinventory);
             }
+            itemstack = org.bukkit.craftbukkit.event.CraftEventFactory.callPreCraftEvent(iinventory, inventorycraftresult, itemstack, getBukkitView(), false); // CraftBukkit
 
             inventorycraftresult.setItem(0, itemstack);
             entityplayer.playerConnection.sendPacket(new PacketPlayOutSetSlot(this.windowId, 0, itemstack));