Handle inventory max stack sizes better. Fixes BUKKIT-5564

Make sure we check the inventory's max stack size where appropriate and
don't assume the inventory slot is able to take our entire stack just
because it is empty. We also ensure the client is updated with the correct
slot contents and cursor contents in cases where the max stack changes
result in different behavior than the client expected.
This commit is contained in:
Travis Watkins 2014-04-23 13:46:19 -05:00
parent c99de378c6
commit 5dfb74032c

View File

@ -282,7 +282,11 @@ public abstract class Container {
if (itemstack4.count == 0) { if (itemstack4.count == 0) {
playerinventory.setCarried((ItemStack) null); playerinventory.setCarried((ItemStack) null);
// CraftBukkit start - Update client cursor if we didn't empty it
} else if (entityhuman instanceof EntityPlayer) {
((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutSetSlot(-1, -1, entityhuman.inventory.getCarried()));
} }
// CraftBukkit end
} }
} else if (slot2.isAllowed(entityhuman)) { } else if (slot2.isAllowed(entityhuman)) {
if (itemstack4 == null) { if (itemstack4 == null) {
@ -308,7 +312,11 @@ public abstract class Container {
itemstack4.a(k1); itemstack4.a(k1);
if (itemstack4.count == 0) { if (itemstack4.count == 0) {
playerinventory.setCarried((ItemStack) null); playerinventory.setCarried((ItemStack) null);
// CraftBukkit start - Update client cursor if we didn't empty it
} else if (entityhuman instanceof EntityPlayer) {
((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutSetSlot(-1, -1, entityhuman.inventory.getCarried()));
} }
// CraftBukkit end
itemstack1.count += k1; itemstack1.count += k1;
} else if (itemstack4.count <= slot2.getMaxStackSize()) { } else if (itemstack4.count <= slot2.getMaxStackSize()) {
@ -317,7 +325,10 @@ public abstract class Container {
} }
} else if (itemstack1.getItem() == itemstack4.getItem() && itemstack4.getMaxStackSize() > 1 && (!itemstack1.usesData() || itemstack1.getData() == itemstack4.getData()) && ItemStack.equals(itemstack1, itemstack4)) { } else if (itemstack1.getItem() == itemstack4.getItem() && itemstack4.getMaxStackSize() > 1 && (!itemstack1.usesData() || itemstack1.getData() == itemstack4.getData()) && ItemStack.equals(itemstack1, itemstack4)) {
k1 = itemstack1.count; k1 = itemstack1.count;
if (k1 > 0 && k1 + itemstack4.count <= itemstack4.getMaxStackSize()) { // CraftBukkit start - itemstack4.getMaxStackSize() -> maxStack
int maxStack = Math.min(itemstack4.getMaxStackSize(), slot2.getMaxStackSize());
if (k1 > 0 && k1 + itemstack4.count <= maxStack) {
// CraftBukkit end
itemstack4.count += k1; itemstack4.count += k1;
itemstack1 = slot2.a(k1); itemstack1 = slot2.a(k1);
if (itemstack1.count == 0) { if (itemstack1.count == 0) {
@ -325,11 +336,20 @@ public abstract class Container {
} }
slot2.a(entityhuman, playerinventory.getCarried()); slot2.a(entityhuman, playerinventory.getCarried());
// CraftBukkit start - Update client cursor if we didn't empty it
} else if (entityhuman instanceof EntityPlayer) {
((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutSetSlot(-1, -1, entityhuman.inventory.getCarried()));
} }
// CraftBukkit end
} }
} }
slot2.f(); slot2.f();
// CraftBukkit start - Make sure the client has the right slot contents
if (entityhuman instanceof EntityPlayer) {
((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutSetSlot(this.windowId, slot2.rawSlotIndex, slot2.getItem()));
}
// CraftBukkit end
} }
} }
} else if (k == 2 && j >= 0 && j < 9) { } else if (k == 2 && j >= 0 && j < 9) {
@ -468,17 +488,20 @@ public abstract class Container {
if (itemstack1 != null && itemstack1.getItem() == itemstack.getItem() && (!itemstack.usesData() || itemstack.getData() == itemstack1.getData()) && ItemStack.equals(itemstack, itemstack1)) { if (itemstack1 != null && itemstack1.getItem() == itemstack.getItem() && (!itemstack.usesData() || itemstack.getData() == itemstack1.getData()) && ItemStack.equals(itemstack, itemstack1)) {
int l = itemstack1.count + itemstack.count; int l = itemstack1.count + itemstack.count;
if (l <= itemstack.getMaxStackSize()) { // CraftBukkit start - itemstack.getMaxStackSize() -> maxStack
int maxStack = Math.min(itemstack.getMaxStackSize(), slot.getMaxStackSize());
if (l <= maxStack) {
itemstack.count = 0; itemstack.count = 0;
itemstack1.count = l; itemstack1.count = l;
slot.f(); slot.f();
flag1 = true; flag1 = true;
} else if (itemstack1.count < itemstack.getMaxStackSize()) { } else if (itemstack1.count < maxStack) {
itemstack.count -= itemstack.getMaxStackSize() - itemstack1.count; itemstack.count -= maxStack - itemstack1.count;
itemstack1.count = itemstack.getMaxStackSize(); itemstack1.count = maxStack;
slot.f(); slot.f();
flag1 = true; flag1 = itemstack.count == 0; // Don't give a success return if we have leftovers
} }
// CraftBukkit end
} }
if (flag) { if (flag) {
@ -502,8 +525,10 @@ public abstract class Container {
if (itemstack1 == null) { if (itemstack1 == null) {
slot.set(itemstack.cloneItemStack()); slot.set(itemstack.cloneItemStack());
slot.f(); slot.f();
itemstack.count = 0; // CraftBukkit start - Don't assume entire stack went in
flag1 = true; itemstack.count -= slot.getItem().count;
flag1 = itemstack.count == 0;
// CraftBukkit end
break; break;
} }