From 75f835c07ade8b19e48c20e098b32453e2648c6e Mon Sep 17 00:00:00 2001 From: DemonWav Date: Thu, 21 May 2015 06:07:16 -0500 Subject: [PATCH] Send the set item packet to the client when an item is changed or added in a player's inventory - Addresses SPIGOT-883 --- .../craftbukkit/inventory/CraftInventory.java | 4 ++ .../inventory/CraftInventoryPlayer.java | 41 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java index a8028e3f47..e9a3c50133 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java @@ -310,11 +310,15 @@ public class CraftInventory implements Inventory { // Check if it fully fits if (amount + partialAmount <= maxAmount) { partialItem.setAmount(amount + partialAmount); + // To make sure the packet is sent to the client + setItem(firstPartial, partialItem); break; } // It fits partially partialItem.setAmount(maxAmount); + // To make sure the packet is sent to the client + setItem(firstPartial, partialItem); item.setAmount(amount + partialAmount - maxAmount); } } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java index 84955df3f8..ee94dc3c37 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java @@ -1,6 +1,8 @@ package org.bukkit.craftbukkit.inventory; +import net.minecraft.server.EntityPlayer; import net.minecraft.server.PacketPlayOutHeldItemSlot; +import net.minecraft.server.PacketPlayOutSetSlot; import net.minecraft.server.PlayerInventory; import org.apache.commons.lang.Validate; @@ -32,6 +34,45 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i setItem(getHeldItemSlot(), stack); } + @Override + public void setItem(int index, ItemStack item) { + super.setItem(index, item); + EntityPlayer player = ((CraftPlayer) this.getHolder()).getHandle(); + // PacketPlayOutSetSlot places the items differently than setItem() + // + // Between, and including, index 9 (the first index outside of the hotbar) and index 35 (the last index before + // armor slots) both PacketPlayOutSetSlot and setItem() places the items in the player's inventory the same way. + // Index 9 starts at the upper left corner of the inventory and moves to the right as it increases. When it + // reaches the end of the line it goes back to the left side of the new line in the inventory. Basically, it + // follows the path your eyes would follow as you read a book. + // + // The player's hotbar is indexed 0-8 in setItem(). The order goes: 0-8 hotbar, 9-35 normal inventory, 36 boots, + // 37 leggings, 38 chestplate, and 39 helmet. For indexes > 39 an ArrayIndexOutOfBoundsException will be thrown. + // + // PacketPlayOutSetSlot works very differently. Slots 0-8 are as follows: 0 crafting output, 1-4 crafting input, + // 5 helmet, 6 chestplate, 7 leggings, and 8 boots. Then, 9-35 work exactly the same as setItem(). The hotbar + // for PacketPlayOutSetSlot starts at index 36, and continues to index 44. Items placed where index is < 0 or + // > 44 have no action. Basically, the upper part of the player's inventory (crafting area and armor slots) is + // the first "row" of 9 slots for PacketPlayOutSetSlot. From there the rows work as normal, from left to right + // all the way down, including the hotbar. + // + // With this in mind, we have to modify the index we give PacketPlayOutSetSlot to match the index we intended + // with setItem(). First, if the index is 0-8, we need to add 36, or 4 rows worth of slots, to the index. This + // will push the item down to the correct spot in the hotbar. + // + // Now when index is > 35 (if index > 39 an ArrayIndexOutOfBoundsException will be thrown, so we need not worry + // about it) then we need to reset the index, and then count backwards from the "top" of the inventory. That is + // to say, we first find (index - 36), which will give us the index required for the armor slots. Now, we need + // to reverse the order of the index from 8. That means we need 0 to correspond to 8, 1 to correspond to 7, + // 2 to correspond to 6, and 3 to correspond to 5. We do this simply by taking the result of (index - 36) and + // subtracting that value from 8. + if (index < PlayerInventory.getHotbarSize()) + index = index + 36; + else if (index > 35) + index = 8 - (index - 36); + player.playerConnection.sendPacket(new PacketPlayOutSetSlot(player.activeContainer.windowId, index, CraftItemStack.asNMSCopy(item))); + } + public int getHeldItemSlot() { return getInventory().itemInHandIndex; }