tutorial:inventory
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| tutorial:inventory [2025/03/30 22:06] – [Storing items in a block as an Inventory] technici4n | tutorial:inventory [2026/01/24 02:29] (current) – try_with_empty_hand i believe infinitychances | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== Storing items in a block as an Inventory ====== | ====== Storing items in a block as an Inventory ====== | ||
| + | :!: This page has been updated for mojmap. Because of this change, the class known as " | ||
| + | |||
| Make sure you've [[tutorial: | Make sure you've [[tutorial: | ||
| - | The simplest way to store items in a BlockEntity is to make it an '' | + | The simplest way to store items in a BlockEntity is to make it a '' |
| - | This tutorial is written for 1.21. For older versions, some methods may change. | + | This tutorial is written for 1.21.11. For older versions, some methods may change. |
| - | ===== Implementing | + | ===== Implementing |
| - | '' | + | '' |
| - | <code java ImplementedInventory.java> | + | <code java ImplementedContainer.java> |
| /** | /** | ||
| - | * A simple {@code | + | * A simple {@code |
| * | * | ||
| * @author Juuz | * @author Juuz | ||
| */ | */ | ||
| - | public interface | + | public interface |
| /** | /** | ||
| - | * Retrieves the item list of this inventory. | + | * Retrieves the item list of this container. |
| * Must return the same instance every time it's called. | * Must return the same instance every time it's called. | ||
| */ | */ | ||
| - | | + | |
| | | ||
| /** | /** | ||
| - | * Creates | + | * Creates |
| */ | */ | ||
| - | static | + | static |
| return () -> items; | return () -> items; | ||
| } | } | ||
| | | ||
| /** | /** | ||
| - | * Creates a new inventory | + | * Creates a new container |
| */ | */ | ||
| - | static | + | static |
| - | return of(DefaultedList.ofSize(size, ItemStack.EMPTY)); | + | return of(NonNullList.withSize(size, ItemStack.EMPTY)); |
| } | } | ||
| | | ||
| /** | /** | ||
| - | * Returns the inventory | + | * Returns the container |
| */ | */ | ||
| @Override | @Override | ||
| - | default int size() { | + | default int getContainerSize() { |
| return getItems().size(); | return getItems().size(); | ||
| } | } | ||
| | | ||
| /** | /** | ||
| - | * Checks if the inventory | + | * Checks if the container |
| - | * @return true if this inventory | + | * @return true if this container |
| */ | */ | ||
| @Override | @Override | ||
| default boolean isEmpty() { | default boolean isEmpty() { | ||
| - | for (int i = 0; i < size(); i++) { | + | for (int i = 0; i < getContainerSize(); i++) { |
| - | ItemStack stack = getStack(i); | + | ItemStack stack = getItem(i); |
| if (!stack.isEmpty()) { | if (!stack.isEmpty()) { | ||
| return false; | return false; | ||
| Line 65: | Line 67: | ||
| */ | */ | ||
| @Override | @Override | ||
| - | default ItemStack | + | default ItemStack |
| return getItems().get(slot); | return getItems().get(slot); | ||
| } | } | ||
| | | ||
| /** | /** | ||
| - | * Removes items from an inventory | + | * Removes items from a container |
| * @param slot The slot to remove from. | * @param slot The slot to remove from. | ||
| * @param count How many items to remove. If there are less items in the slot than what are requested, | * @param count How many items to remove. If there are less items in the slot than what are requested, | ||
| Line 76: | Line 78: | ||
| */ | */ | ||
| @Override | @Override | ||
| - | default ItemStack | + | default ItemStack |
| - | ItemStack result = Inventories.splitStack(getItems(), | + | ItemStack result = ContainerHelper.removeItem(getItems(), |
| if (!result.isEmpty()) { | if (!result.isEmpty()) { | ||
| - | | + | |
| } | } | ||
| return result; | return result; | ||
| Line 85: | Line 87: | ||
| | | ||
| /** | /** | ||
| - | * Removes all items from an inventory | + | * Removes all items from a container |
| * @param slot The slot to remove from. | * @param slot The slot to remove from. | ||
| */ | */ | ||
| @Override | @Override | ||
| - | default ItemStack | + | default ItemStack |
| - | return | + | return |
| } | } | ||
| | | ||
| /** | /** | ||
| - | * Replaces the current stack in an inventory | + | * Replaces the current stack in a container |
| - | * @param slot The inventory | + | * @param slot The container |
| * @param stack The replacing itemstack. If the stack is too big for | * @param stack The replacing itemstack. If the stack is too big for | ||
| - | | + | |
| - | | + | |
| */ | */ | ||
| @Override | @Override | ||
| - | default void setStack(int slot, ItemStack stack) { | + | default void setItem(int slot, ItemStack stack) { |
| getItems().set(slot, | getItems().set(slot, | ||
| - | if (stack.getCount() > stack.getMaxCount()) { | + | if (stack.getCount() > stack.getMaxStackSize()) { |
| - | stack.setCount(stack.getMaxCount()); | + | stack.setCount(stack.getMaxStackSize()); |
| } | } | ||
| } | } | ||
| | | ||
| /** | /** | ||
| - | * Clears the inventory. | + | * Clears the container. |
| */ | */ | ||
| @Override | @Override | ||
| - | default void clear() { | + | default void clearContent() { |
| getItems().clear(); | getItems().clear(); | ||
| } | } | ||
| Line 118: | Line 120: | ||
| /** | /** | ||
| * Marks the state as dirty. | * Marks the state as dirty. | ||
| - | * Must be called after changes in the inventory, so that the game can properly save | + | * Must be called after changes in the container, so that the game can properly save |
| - | * the inventory | + | * the container |
| | | ||
| @Override | @Override | ||
| - | default void markDirty() { | + | default void setChanged() { |
| // Override if you want behavior. | // Override if you want behavior. | ||
| } | } | ||
| | | ||
| /** | /** | ||
| - | * @return true if the player can use the inventory, false otherwise. | + | * @return true if the player can use the container, false otherwise. |
| | | ||
| @Override | @Override | ||
| - | default boolean | + | default boolean |
| return true; | return true; | ||
| } | } | ||
| Line 136: | Line 138: | ||
| </ | </ | ||
| - | Now in your '' | + | Now in your '' |
| <code java DemoBlockEntity.java> | <code java DemoBlockEntity.java> | ||
| - | public class DemoBlockEntity extends BlockEntity implements | + | public class DemoBlockEntity extends BlockEntity implements |
| - | private final DefaultedList< | + | private final NonNullList< |
| @Override | @Override | ||
| - | public | + | public |
| return items; | return items; | ||
| } | } | ||
| Line 150: | Line 152: | ||
| </ | </ | ||
| - | We're also gonna need to save the inventories to NBT and load it from there. '' | + | We're also gonna need to save the inventories to NBT and load it from there. '' |
| <code java DemoBlockEntity.java> | <code java DemoBlockEntity.java> | ||
| - | public class DemoBlockEntity extends BlockEntity implements | + | public class DemoBlockEntity extends BlockEntity implements |
| [...] | [...] | ||
| @Override | @Override | ||
| - | public void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) { | + | public void loadAdditional(ValueInput valueInput) { |
| - | super.readNbt(nbt, registryLookup); | + | super.loadAdditional(valueInput); |
| - | | + | |
| + | ContainerHelper.loadAllItems(valueInput, items); | ||
| } | } | ||
| @Override | @Override | ||
| - | public | + | public |
| - | | + | |
| - | | + | |
| } | } | ||
| } | } | ||
| </ | </ | ||
| - | ===== Extracting and inserting from your inventory | + | ===== Extracting and inserting from your container |
| In our block class, we'll override the '' | In our block class, we'll override the '' | ||
| - | First we'll handle inserting into the inventory. The player will insert the item he is holding if he is holding one. It'll go into the first slot if it is empty, or to the second slot if the first one is empty, or if the second is empty too we'll print some information about the inventory. | + | First we'll handle inserting into the container. The player will insert the item he is holding if he is holding one. It'll go into the first slot if it is empty, or to the second slot if the first one is empty, or if the second is empty too we'll print some information about the container. |
| - | Note that we call '' | + | Note that we call '' |
| <code java DemoBlock.java> | <code java DemoBlock.java> | ||
| - | public class DemoBlock extends | + | public class DemoBlock extends |
| [...] | [...] | ||
| @Override | @Override | ||
| - | protected | + | protected |
| - | if (world.isClient) return | + | if (level.isClient) return |
| | | ||
| - | if (!(world.getBlockEntity(pos) instanceof DemoBlockEntity blockEntity)) { | + | if (!(level.getBlockEntity(pos) instanceof DemoBlockEntity blockEntity)) { |
| - | return | + | return |
| } | } | ||
| - | if (!player.getStackInHand(hand).isEmpty()) { | + | if (!player.getItemInHand(hand).isEmpty()) { |
| // Check what is the first open slot and put an item from the player' | // Check what is the first open slot and put an item from the player' | ||
| - | if (blockEntity.getStack(0).isEmpty()) { | + | if (blockEntity.getItem(0).isEmpty()) { |
| - | // Put the stack the player is holding into the inventory | + | // Put the stack the player is holding into the container |
| - | blockEntity.setStack(0, player.getStackInHand(hand).copy()); | + | blockEntity.setItem(0, player.getItemInHand(hand).copy()); |
| // Remove the stack from the player' | // Remove the stack from the player' | ||
| - | player.getStackInHand(hand).setCount(0); | + | player.getItemInHand(hand).setCount(0); |
| - | } else if (blockEntity.getStack(1).isEmpty()) { | + | } else if (blockEntity.getItem(1).isEmpty()) { |
| - | blockEntity.setStack(1, player.getStackInHand(hand).copy()); | + | blockEntity.setItem(1, player.getItemInHand(hand).copy()); |
| - | player.getStackInHand(hand).setCount(0); | + | player.getItemInHand(hand).setCount(0); |
| } else { | } else { | ||
| - | // If the inventory | + | // If the container |
| - | player.sendMessage(Text.literal(" | + | player.displayClientMessage(Component.literal(" |
| - | .append(blockEntity.getStack(0).getName()) | + | .append(blockEntity.getItem(0).getItemName()) |
| .append(" | .append(" | ||
| - | .append(blockEntity.getStack(1).getName())); | + | .append(blockEntity.getItem(1).getItemName())); |
| } | } | ||
| } | } | ||
| - | return | + | return |
| } | } | ||
| } | } | ||
| Line 213: | Line 216: | ||
| If the first is empty we pass it to default behavior. | If the first is empty we pass it to default behavior. | ||
| <code java DemoBlock.java> | <code java DemoBlock.java> | ||
| - | public class DemoBlock extends | + | public class DemoBlock extends |
| [...] | [...] | ||
| @Override | @Override | ||
| - | protected | + | protected |
| ... | ... | ||
| - | if (!player.getStackInHand(hand).isEmpty()) { | + | if (!player.getItemInHand(hand).isEmpty()) { |
| ... | ... | ||
| } else { | } else { | ||
| Line 224: | Line 227: | ||
| // Find the first slot that has an item and give it to the player | // Find the first slot that has an item and give it to the player | ||
| - | if (!blockEntity.getStack(1).isEmpty()) { | + | if (!blockEntity.getItem(1).isEmpty()) { |
| - | // Give the player the stack in the inventory | + | // Give the player the stack in the container |
| - | player.getInventory().offerOrDrop(blockEntity.getStack(1)); | + | player.getInventory().placeItemBackInInventory(blockEntity.getItem(1)); |
| - | // Remove the stack from the inventory | + | // Remove the stack from the container |
| - | blockEntity.removeStack(1); | + | blockEntity.removeItem(1); |
| - | } else if (!blockEntity.getStack(0).isEmpty()) { | + | } else if (!blockEntity.getItem(0).isEmpty()) { |
| - | player.getInventory().offerOrDrop(blockEntity.getStack(0)); | + | player.getInventory().placeItemBackInInventory(blockEntity.getItem(0)); |
| - | blockEntity.removeStack(0); | + | blockEntity.removeItem(0); |
| } else { | } else { | ||
| - | return | + | return |
| } | } | ||
| } | } | ||
| | | ||
| - | return | + | return |
| } | } | ||
| } | } | ||
| </ | </ | ||
| - | ===== Implementing | + | ===== Implementing |
| - | If you want to have different logic based on what side things (hopper or other mods) interact with your block you need to implement '' | + | If you want to have different logic based on what side things (hopper or other mods) interact with your block you need to implement '' |
| <code java DemoBlockEntity.java> | <code java DemoBlockEntity.java> | ||
| - | public class DemoBlockEntity extends BlockEntity implements | + | public class DemoBlockEntity extends BlockEntity implements |
| [...] | [...] | ||
| @Override | @Override | ||
| - | public int[] getInvAvailableSlots(Direction side) { | + | public int[] getSlotsForFace(Direction side) { |
| // Just return an array of all slots | // Just return an array of all slots | ||
| return IntStream.of(getItems().size()).toArray(); | return IntStream.of(getItems().size()).toArray(); | ||
| Line 255: | Line 258: | ||
| @Override | @Override | ||
| - | public boolean | + | public boolean |
| return direction != Direction.UP; | return direction != Direction.UP; | ||
| } | } | ||
| @Override | @Override | ||
| - | public boolean | + | public boolean |
| return true; | return true; | ||
| } | } | ||
tutorial/inventory.1743372403.txt.gz · Last modified: 2025/03/30 22:06 by technici4n