public static int amountCanHold(ItemStack[] items, JItem check, boolean extraStack) {
   int amt = 0;
   if (items == null) {
     return 0;
   } else if (check == null) {
     return emptySlots(items);
   } else if (check.isEntity()) {
     return -1;
   } else if (check.isKit()) {
     Kit kit = check instanceof Kit ? (Kit) check : JItemDB.getKit(check);
     Kit.KitItem kititems[] = kit.getKitItems();
     ItemStack invCopy[] = copy(items);
     // loop through & "add" one at a time
     while (true) {
       int numtoadd = 0;
       for (int itn = 0; itn < kititems.length; ++itn) {
         numtoadd = kititems[itn].itemAmount;
         int maxStack =
             !extraStack || noStack.contains(kititems[itn].ID())
                 ? kititems[itn].MaxStackSize()
                 : 64;
         for (int i = 0; i < invCopy.length && numtoadd > 0; ++i) {
           if (invCopy[i] == null || invCopy[i].getAmount() == 0) {
             invCopy[i] = kititems[itn].toItemStack();
             invCopy[i].setAmount(numtoadd);
             numtoadd -= numtoadd;
           } else if (invCopy[i].getAmount() < maxStack && kititems[itn].iequals(invCopy[i])) {
             int d = maxStack < numtoadd ? maxStack : numtoadd;
             invCopy[i].setAmount(invCopy[i].getAmount() + d);
             numtoadd -= d;
           }
         }
         if (numtoadd > 0) {
           // has scanned through full stack & cannot add more
           return amt;
         }
       }
       // 1 was added to the copy
       ++amt;
     }
   } else {
     for (ItemStack item : items) {
       int mx =
           !extraStack || (item != null && noStack.contains(item.getTypeId()))
               ? check.MaxStackSize()
               : 64;
       if (item == null
           || item.getAmount() == 0
           || (check.equals(item) && item.getAmount() <= mx)) {
         amt += mx - (item == null ? 0 : item.getAmount());
       }
     }
   }
   return amt;
 }
  public static ItemStack[] add(ItemStack[] items, JItem toAdd, int amt, boolean extraStack) {
    if (items == null) {
      return null;
    } else if (toAdd == null) {
      return items;
    } else if (toAdd.IsValidItem()) {
      int mx = !extraStack || noStack.contains(toAdd.ID()) ? toAdd.MaxStackSize() : 64;
      while (amt > 0) {
        add(items, toAdd.toItemStack(amt > mx ? mx : amt), extraStack);
        amt -= mx;
      }
      return items;
    } else if (toAdd.isKit()) {
      Kit kit = toAdd instanceof Kit ? (Kit) toAdd : JItemDB.getKit(toAdd);
      Kit.KitItem kititems[] = kit.getKitItems();

      // add one of each until fails
      for (int num = 0; num < amt; ++num) {
        int numtoadd = 0;
        for (int itn = 0; itn < kit.numItems(); ++itn) {
          numtoadd = kititems[itn].itemAmount;
          int maxStack =
              !extraStack || noStack.contains(kititems[itn].ID())
                  ? kititems[itn].MaxStackSize()
                  : 64;
          for (int i = 0; i < items.length && numtoadd > 0; ++i) {
            if (items[i] == null || items[i].getAmount() == 0) {
              items[i] = kititems[itn].toItemStack();
              items[i].setAmount(numtoadd);
              numtoadd -= numtoadd;
            } else if (items[i].getAmount() < maxStack && kititems[itn].iequals(items[i])) {
              int d = maxStack < numtoadd ? maxStack : numtoadd;
              items[i].setAmount(items[i].getAmount() + d);
              numtoadd -= d;
            }
          }
          if (numtoadd > 0) {
            break;
          }
        }
        if (numtoadd > 0) {
          // early exit while adding
          break;
        }
      }
    }
    return items;
  }