This is an old revision of the document!
Table of Contents
Storing items in a block as an Inventory
The standard way to store items in a BlockEntity is to make it an Inventory
.
This allows hoppers (or other mods) to insert and extract items from your BlockEntity without any extra work.
Implementing Inventory
Inventory
is just an interface, which means the actual ItemStack
state will need to be stored on your BlockEntity
.
A DefaultedList<ItemStack>
can be used as an easy way to store these ItemStacks
,
as it can be set to default to ItemStack.Empty
, which is the proper way of saying that there is no item in a slot.
Implementing Inventory
is fairly simple, but is tedious and prone to error,
so we'll use a default implementation of it which only requires giving it a DefaultList<ItemStack>
(copy this as a new file):
- ImplementedInventory.java
/** * A simple {@code Inventory} implementation with only default methods + an item list getter. * * Originally by Juuz */ public interface ImplementedInventory extends Inventory { /** * Gets the item list of this inventory. * Must return the same instance every time it's called. */ DefaultedList<ItemStack> getItems(); // Creation /** * Creates an inventory from the item list. */ static ImplementedInventory of(DefaultedList<ItemStack> items) { return () -> items; } /** * Creates a new inventory with the size. */ static ImplementedInventory ofSize(int size) { return of(DefaultedList.ofSize(size, ItemStack.EMPTY)); } // Inventory /** * Returns the inventory size. */ @Override default int getInvSize() { return getItems().size(); } /** * @return true if this inventory has only empty stacks, false otherwise */ @Override default boolean isInvEmpty() { for (int i = 0; i < getInvSize(); i++) { ItemStack stack = getInvStack(i); if (!stack.isEmpty()) { return false; } } return true; } /** * Gets the item in the slot. */ @Override default ItemStack getInvStack(int slot) { return getItems().get(slot); } /** * Takes a stack of the size from the slot. * <p>(default implementation) If there are less items in the slot than what are requested, * takes all items in that slot. */ @Override default ItemStack takeInvStack(int slot, int count) { ItemStack result = Inventories.splitStack(getItems(), slot, count); if (!result.isEmpty()) { markDirty(); } return result; } /** * Removes the current stack in the {@code slot} and returns it. */ @Override default ItemStack removeInvStack(int slot) { return Inventories.removeStack(getItems(), slot); } /** * Replaces the current stack in the {@code slot} with the provided stack. * <p>If the stack is too big for this inventory ({@link Inventory#getInvMaxStackAmount()}), * it gets resized to this inventory's maximum amount. */ @Override default void setInvStack(int slot, ItemStack stack) { getItems().set(slot, stack); if (stack.getCount() > getInvMaxStackAmount()) { stack.setCount(getInvMaxStackAmount()); } } /** * Clears {@linkplain #getItems() the item list}}. */ @Override default void clear() { getItems().clear(); } @Override default void markDirty() { // Override if you want behavior. } @Override default boolean canPlayerUseInv(PlayerEntity player) { return true; } }
Now in your BlockEntity
Implement ImplementedInventory
,
and provide it with an instance of DefaultedList<ItemStack> items
that stores the items.
For this example we'll store a maximum of 2 items in the inventory:
public class DemoBlockEntity extends BlockEntity implements ImplementedInventory { private final DefaultedList<ItemStack> items = DefaultedList.ofSize(2, ItemStack.EMPTY); @Override public DefaultedList<ItemStack> getItems() { return items; } ... }
We're also gonna need to save the inventories to tag and load it from there.
Inventories
has helper methods that makes this very easy:
public class DemoBlockEntity extends BlockEntity implements ImplementedInventory { ... @Override public void fromTag(CompoundTag tag) { super.fromTag(tag); Inventories.fromTag(tag,items); } @Override public CompoundTag toTag(CompoundTag tag) { Inventories.toTag(tag,items); return super.toTag(tag); } }
Extracting and inserting from your inventory
Remember that the same thing can be done with any inventory…