+ * Caveats: + *
+ * The returned HashMap contains what it couldn't store, where the key is + * the index of the parameter, and the value is the ItemStack at that + * index of the varargs parameter. If all items are stored, it will return + * an empty HashMap. + *
+ * If you pass in ItemStacks which exceed the maximum stack size for the + * Material, first they will be added to partial stacks where + * Material.getMaxStackSize() is not exceeded, up to + * Material.getMaxStackSize(). When there are no partial stacks left + * stacks will be split on Inventory.getMaxStackSize() allowing you to + * exceed the maximum stack size for that material. + *
+ * It is known that in some implementations this method will also set
+ * the inputted argument amount to the number of that item not placed in
+ * slots.
+ *
+ * @param items The ItemStacks to add
+ * @return A HashMap containing items that didn't fit.
+ * @throws IllegalArgumentException if items or any element in it is null
+ */
+ HashMap
+ * It will try to remove 'as much as possible' from the types and amounts
+ * you give as arguments.
+ *
+ * The returned HashMap contains what it couldn't remove, where the key is
+ * the index of the parameter, and the value is the ItemStack at that
+ * index of the varargs parameter. If all the given ItemStacks are
+ * removed, it will return an empty HashMap.
+ *
+ * It is known that in some implementations this method will also set the
+ * inputted argument amount to the number of that item not removed from
+ * slots.
+ *
+ * @param items The ItemStacks to remove
+ * @return A HashMap containing items that couldn't be removed.
+ * @throws IllegalArgumentException if items is null
+ */
+ HashMap
+ * This will only return true if both the type and the amount of the stack
+ * match.
+ *
+ * @param item The ItemStack to match against
+ * @return false if item is null, true if any exactly matching ItemStacks
+ * were found
+ */
+ @Contract("null -> false")
+ boolean contains(ItemStack item);
+
+ /**
+ * Checks if the inventory contains any ItemStacks with the given
+ * material, adding to at least the minimum amount specified.
+ *
+ * @param material The material to check for
+ * @param amount The minimum amount
+ * @return true if amount is less than 1, true if enough ItemStacks were
+ * found to add to the given amount
+ * @throws IllegalArgumentException if material is null
+ */
+ boolean contains(Key material, int amount) throws IllegalArgumentException;
+
+ /**
+ * Checks if the inventory contains at least the minimum amount specified
+ * of exactly matching ItemStacks.
+ *
+ * An ItemStack only counts if both the type and the amount of the stack
+ * match.
+ *
+ * @param item the ItemStack to match against
+ * @param amount how many identical stacks to check for
+ * @return false if item is null, true if amount less than 1, true if
+ * amount of exactly matching ItemStacks were found
+ * @see #containsAtLeast(ItemStack, int)
+ */
+ @Contract("null, _ -> false")
+ boolean contains(ItemStack item, int amount);
+
+ /**
+ * Checks if the inventory contains ItemStacks matching the given
+ * ItemStack whose amounts sum to at least the minimum amount specified.
+ *
+ * @param item the ItemStack to match against
+ * @param amount the minimum amount
+ * @return false if item is null, true if amount less than 1, true if
+ * enough ItemStacks were found to add to the given amount
+ */
+ @Contract("null, _ -> false")
+ boolean containsAtLeast(ItemStack item, int amount);
+
+ /**
+ * Returns a HashMap with all slots and ItemStacks in the inventory with
+ * the given Material.
+ *
+ * The HashMap contains entries where, the key is the slot index, and the
+ * value is the ItemStack in that slot. If no matching ItemStack with the
+ * given Material is found, an empty map is returned.
+ *
+ * @param material The material to look for
+ * @return A HashMap containing the slot index, ItemStack pairs
+ * @throws IllegalArgumentException if material is null
+ */
+ HashMap
+ * The HashMap contains entries where, the key is the slot index, and the
+ * value is the ItemStack in that slot. If no matching ItemStack with the
+ * given Material is found, an empty map is returned.
+ *
+ * @param item The ItemStack to match against
+ * @return A map from slot indexes to item at index
+ */
+ HashMap
+ * This will only match a slot if both the type and the amount of the
+ * stack match
+ *
+ * @param item The ItemStack to match against
+ */
+ void remove(ItemStack item);
+
+ /**
+ * Clears out a particular slot in the index.
+ *
+ * @param index The index to empty.
+ */
+ void clear(int index);
+
+ /**
+ * Clears out the whole Inventory.
+ */
+ void clear();
+
+ /**
+ * Gets a list of players viewing the inventory. Note that a player is
+ * considered to be viewing their own inventory and internal crafting
+ * screen even when said inventory is not open. They will normally be
+ * considered to be viewing their inventory even when they have a
+ * different inventory screen open, but it's possible for customized
+ * inventory screens to exclude the viewer's inventory, so this should
+ * never be assumed to be non-empty.
+ *
+ * @return A set of HumanEntities who are viewing this Inventory.
+ */
+ Set
+ * This is a value between 0 and 20, with 0 making the bar empty, and 20
+ * making the bar full.
+ */
+ FUEL_TIME(1, InventoryType.BREWING),
+ /**
+ * The progress of the flame in a furnace inventory.
+ */
+ BURN_TIME(0, InventoryType.FURNACE),
+ /**
+ * How many total ticks the current fuel should last.
+ */
+ TICKS_FOR_CURRENT_FUEL(1, InventoryType.FURNACE),
+ /**
+ * The progress of the right-pointing arrow in a furnace inventory.
+ */
+ COOK_TIME(2, InventoryType.FURNACE),
+ /**
+ * How many total ticks the current smelting should last.
+ */
+ TICKS_FOR_CURRENT_SMELTING(3, InventoryType.FURNACE),
+ /**
+ * In an enchanting inventory, the top button's experience level
+ * value.
+ */
+ ENCHANT_BUTTON1(0, InventoryType.ENCHANTING),
+ /**
+ * In an enchanting inventory, the middle button's experience level
+ * value.
+ */
+ ENCHANT_BUTTON2(1, InventoryType.ENCHANTING),
+ /**
+ * In an enchanting inventory, the bottom button's experience level
+ * value.
+ */
+ ENCHANT_BUTTON3(2, InventoryType.ENCHANTING),
+ /**
+ * In an enchanting inventory, the first four bits of the player's xpSeed.
+ */
+ ENCHANT_XP_SEED(3, InventoryType.ENCHANTING),
+ /**
+ * In an enchanting inventory, the top button's enchantment's id
+ */
+ ENCHANT_ID1(4, InventoryType.ENCHANTING),
+ /**
+ * In an enchanting inventory, the middle button's enchantment's id
+ */
+ ENCHANT_ID2(5, InventoryType.ENCHANTING),
+ /**
+ * In an enchanting inventory, the bottom button's enchantment's id
+ */
+ ENCHANT_ID3(6, InventoryType.ENCHANTING),
+ /**
+ * In an enchanting inventory, the top button's level value.
+ */
+ ENCHANT_LEVEL1(7, InventoryType.ENCHANTING),
+ /**
+ * In an enchanting inventory, the middle button's level value.
+ */
+ ENCHANT_LEVEL2(8, InventoryType.ENCHANTING),
+ /**
+ * In an enchanting inventory, the bottom button's level value.
+ */
+ ENCHANT_LEVEL3(9, InventoryType.ENCHANTING),
+ /**
+ * In an beacon inventory, the levels of the beacon
+ */
+ LEVELS(0, InventoryType.BEACON),
+ /**
+ * In an beacon inventory, the primary potion effect
+ */
+ PRIMARY_EFFECT(1, InventoryType.BEACON),
+ /**
+ * In an beacon inventory, the secondary potion effect
+ */
+ SECONDARY_EFFECT(2, InventoryType.BEACON),
+ /**
+ * The repair's cost in xp levels
+ */
+ REPAIR_COST(0, InventoryType.ANVIL),
+ /**
+ * The lectern's current open book page
+ */
+ BOOK_PAGE(0, InventoryType.LECTERN);
+
+ private final int id;
+ private final InventoryType style;
+
+ Property(int id, InventoryType appliesTo) {
+ this.id = id;
+ style = appliesTo;
+ }
+
+ public InventoryType getType() {
+ return style;
+ }
+
+ /**
+ * Gets the id of this view.
+ *
+ * @return the id of this view
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public int getId() {
+ return id;
+ }
+ }
+
+}
diff --git a/src/main/java/com/loohp/limbo/inventory/ItemStack.java b/src/main/java/com/loohp/limbo/inventory/ItemStack.java
new file mode 100644
index 0000000..31ae90e
--- /dev/null
+++ b/src/main/java/com/loohp/limbo/inventory/ItemStack.java
@@ -0,0 +1,122 @@
+/*
+ * This file is part of Limbo.
+ *
+ * Copyright (C) 2022. LoohpJames
+ * It is these contents which will be used for add / contains / remove
+ * methods which look for a specific stack.
+ *
+ * @return inventory storage contents. Individual items may be null.
+ */
+ ItemStack[] getStorageContents();
+
+ /**
+ * Put the given ItemStacks into the storage slots
+ *
+ * @param items The ItemStacks to use as storage contents
+ * @throws IllegalArgumentException If the array has more items than the
+ * inventory.
+ */
+ void setStorageContents(ItemStack[] items) throws IllegalArgumentException;
+
+ /**
+ * Checks if the inventory contains any ItemStacks with the given
+ * material.
+ *
+ * @param material The material to check for
+ * @return true if an ItemStack is found with the given Material
+ * @throws IllegalArgumentException if material is null
+ */
+ boolean contains(Key material) throws IllegalArgumentException;
+
+ /**
+ * Checks if the inventory contains any ItemStacks matching the given
+ * ItemStack.
+ *