From daf45148d1e35cf279ace8188ed851d0f3d4d835 Mon Sep 17 00:00:00 2001
From: md_5 <git@md-5.net>
Date: Mon, 7 Mar 2016 17:20:24 +1100
Subject: [PATCH] SPIGOT-1526 / SPIGOT-1809: Expand Inventory API

---
 .../craftbukkit/inventory/CraftInventory.java | 38 +++++++----
 .../inventory/CraftInventoryPlayer.java       | 68 ++++++++++++-------
 2 files changed, 66 insertions(+), 40 deletions(-)

diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
index e6506892be..3297216d58 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
@@ -49,6 +49,16 @@ public class CraftInventory implements Inventory {
         return item == null ? null : CraftItemStack.asCraftMirror(item);
     }
 
+    @Override
+    public ItemStack[] getStorageContents() {
+        return getContents();
+    }
+
+    @Override
+    public void setStorageContents(ItemStack[] items) throws IllegalArgumentException {
+        setContents(items);
+    }
+
     public ItemStack[] getContents() {
         ItemStack[] items = new ItemStack[getSize()];
         net.minecraft.server.ItemStack[] mcItems = getInventory().getContents();
@@ -79,7 +89,7 @@ public class CraftInventory implements Inventory {
     }
 
     public boolean contains(int materialId) {
-        for (ItemStack item : getContents()) {
+        for (ItemStack item : getStorageContents()) {
             if (item != null && item.getTypeId() == materialId) {
                 return true;
             }
@@ -96,7 +106,7 @@ public class CraftInventory implements Inventory {
         if (item == null) {
             return false;
         }
-        for (ItemStack i : getContents()) {
+        for (ItemStack i : getStorageContents()) {
             if (item.equals(i)) {
                 return true;
             }
@@ -108,7 +118,7 @@ public class CraftInventory implements Inventory {
         if (amount <= 0) {
             return true;
         }
-        for (ItemStack item : getContents()) {
+        for (ItemStack item : getStorageContents()) {
             if (item != null && item.getTypeId() == materialId) {
                 if ((amount -= item.getAmount()) <= 0) {
                     return true;
@@ -130,7 +140,7 @@ public class CraftInventory implements Inventory {
         if (amount <= 0) {
             return true;
         }
-        for (ItemStack i : getContents()) {
+        for (ItemStack i : getStorageContents()) {
             if (item.equals(i) && --amount <= 0) {
                 return true;
             }
@@ -145,7 +155,7 @@ public class CraftInventory implements Inventory {
         if (amount <= 0) {
             return true;
         }
-        for (ItemStack i : getContents()) {
+        for (ItemStack i : getStorageContents()) {
             if (item.isSimilar(i) && (amount -= i.getAmount()) <= 0) {
                 return true;
             }
@@ -156,7 +166,7 @@ public class CraftInventory implements Inventory {
     public HashMap<Integer, ItemStack> all(int materialId) {
         HashMap<Integer, ItemStack> slots = new HashMap<Integer, ItemStack>();
 
-        ItemStack[] inventory = getContents();
+        ItemStack[] inventory = getStorageContents();
         for (int i = 0; i < inventory.length; i++) {
             ItemStack item = inventory[i];
             if (item != null && item.getTypeId() == materialId) {
@@ -174,7 +184,7 @@ public class CraftInventory implements Inventory {
     public HashMap<Integer, ItemStack> all(ItemStack item) {
         HashMap<Integer, ItemStack> slots = new HashMap<Integer, ItemStack>();
         if (item != null) {
-            ItemStack[] inventory = getContents();
+            ItemStack[] inventory = getStorageContents();
             for (int i = 0; i < inventory.length; i++) {
                 if (item.equals(inventory[i])) {
                     slots.put(i, inventory[i]);
@@ -185,7 +195,7 @@ public class CraftInventory implements Inventory {
     }
 
     public int first(int materialId) {
-        ItemStack[] inventory = getContents();
+        ItemStack[] inventory = getStorageContents();
         for (int i = 0; i < inventory.length; i++) {
             ItemStack item = inventory[i];
             if (item != null && item.getTypeId() == materialId) {
@@ -208,7 +218,7 @@ public class CraftInventory implements Inventory {
         if (item == null) {
             return -1;
         }
-        ItemStack[] inventory = getContents();
+        ItemStack[] inventory = getStorageContents();
         for (int i = 0; i < inventory.length; i++) {
             if (inventory[i] == null) continue;
 
@@ -220,7 +230,7 @@ public class CraftInventory implements Inventory {
     }
 
     public int firstEmpty() {
-        ItemStack[] inventory = getContents();
+        ItemStack[] inventory = getStorageContents();
         for (int i = 0; i < inventory.length; i++) {
             if (inventory[i] == null) {
                 return i;
@@ -230,7 +240,7 @@ public class CraftInventory implements Inventory {
     }
 
     public int firstPartial(int materialId) {
-        ItemStack[] inventory = getContents();
+        ItemStack[] inventory = getStorageContents();
         for (int i = 0; i < inventory.length; i++) {
             ItemStack item = inventory[i];
             if (item != null && item.getTypeId() == materialId && item.getAmount() < item.getMaxStackSize()) {
@@ -246,7 +256,7 @@ public class CraftInventory implements Inventory {
     }
 
     private int firstPartial(ItemStack item) {
-        ItemStack[] inventory = getContents();
+        ItemStack[] inventory = getStorageContents();
         ItemStack filteredItem = CraftItemStack.asCraftCopy(item);
         if (item == null) {
             return -1;
@@ -373,7 +383,7 @@ public class CraftInventory implements Inventory {
     }
 
     public void remove(int materialId) {
-        ItemStack[] items = getContents();
+        ItemStack[] items = getStorageContents();
         for (int i = 0; i < items.length; i++) {
             if (items[i] != null && items[i].getTypeId() == materialId) {
                 clear(i);
@@ -387,7 +397,7 @@ public class CraftInventory implements Inventory {
     }
 
     public void remove(ItemStack item) {
-        ItemStack[] items = getContents();
+        ItemStack[] items = getStorageContents();
         for (int i = 0; i < items.length; i++) {
             if (items[i] != null && items[i].equals(item)) {
                 clear(i);
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
index afdc796a27..09023860f7 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
@@ -1,5 +1,7 @@
 package org.bukkit.craftbukkit.inventory;
 
+import com.google.common.base.Preconditions;
+import java.util.Arrays;
 import net.minecraft.server.EntityPlayer;
 import net.minecraft.server.PacketPlayOutHeldItemSlot;
 import net.minecraft.server.PacketPlayOutSetSlot;
@@ -21,6 +23,12 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i
         return (PlayerInventory) inventory;
     }
 
+    @Override
+    public ItemStack[] getStorageContents() {
+        return Arrays.copyOfRange(getContents(), 0, getInventory().items.length);
+    }
+
+
     @Override
     public ItemStack getItemInMainHand() {
         return CraftItemStack.asCraftMirror(getInventory().getItemInHand());
@@ -38,7 +46,9 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i
 
     @Override
     public void setItemInOffHand(ItemStack item) {
-        getInventory().extraSlots[0] = CraftItemStack.asNMSCopy(item);
+        ItemStack[] extra = getExtraContents();
+        extra[0] = item;
+        setExtraContents(extra);
     }
 
     @Override
@@ -135,35 +145,49 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i
     }
 
     public ItemStack[] getArmorContents() {
-        net.minecraft.server.ItemStack[] mcItems = getInventory().getArmorContents();
-        ItemStack[] ret = new ItemStack[mcItems.length];
-
-        for (int i = 0; i < mcItems.length; i++) {
-            ret[i] = CraftItemStack.asCraftMirror(mcItems[i]);
-        }
-        return ret;
+        int start = getInventory().items.length;
+        return Arrays.copyOfRange(getContents(), start, start + getInventory().armor.length);
     }
 
-    public void setArmorContents(ItemStack[] items) {
-        int cnt = getInventory().items.length;
-
+    private void setSlots(ItemStack[] items, int baseSlot, int length) {
         if (items == null) {
-            items = new ItemStack[4];
+            items = new ItemStack[length];
         }
-        for (ItemStack item : items) {
-            if (item == null || item.getTypeId() == 0) {
-                clear(cnt++);
+        Preconditions.checkArgument(items.length <= length, "items.length must be < %s", length);
+
+        for (int i = 0; i < length; i++) {
+            if (i >= items.length) {
+                setItem(baseSlot + i, null);
             } else {
-                setItem(cnt++, item);
+                setItem(baseSlot + i, items[i]);
             }
         }
     }
 
+    @Override
+    public void setStorageContents(ItemStack[] items) throws IllegalArgumentException {
+        setSlots(items, 0, getInventory().items.length);
+    }
+
+    @Override
+    public void setArmorContents(ItemStack[] items) {
+        setSlots(items, getInventory().items.length, getInventory().armor.length);
+    }
+
+    @Override
+    public ItemStack[] getExtraContents() {
+        int start = getInventory().items.length + getInventory().armor.length;
+        return Arrays.copyOfRange(getContents(), start, start + getInventory().extraSlots.length);
+    }
+
+    @Override
+    public void setExtraContents(ItemStack[] items) {
+        setSlots(items, getInventory().items.length + getInventory().armor.length, getInventory().extraSlots.length);
+    }
+
     public int clear(int id, int data) {
         int count = 0;
         ItemStack[] items = getContents();
-        ItemStack[] armor = getArmorContents();
-        int armorSlot = getSize();
 
         for (int i = 0; i < items.length; i++) {
             ItemStack item = items[i];
@@ -175,14 +199,6 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i
             setItem(i, null);
         }
 
-        for (ItemStack item : armor) {
-            if (item == null) continue;
-            if (id > -1 && item.getTypeId() != id) continue;
-            if (data > -1 && item.getData().getData() != data) continue;
-
-            count += item.getAmount();
-            setItem(armorSlot++, null);
-        }
         return count;
     }