This is an old revision of the document!
Table of Contents
将物品放在容器中
阅读本教程之前,请确保您已将方块实体制作完成。
将物品存储在BlockEntity中的标准方法是使其成为Inventory
。
这使得漏斗(或其他mods)无需任何额外的工作即可从您的BlockEntity放入和提取物品。
实施Inventory
Inventory
只是一个接口,这意味着实际的ItemStack
状态将需要存储在您的BlockEntity
上。
可以使用DefaultedList <ItemStack>
作为存储这些ItemStacks
的简便方法,
因为可以将其默认设置为ItemStack.Empty
,这是表示插槽中没有项目的正确方法。
实施广告资源
非常简单,但乏味且容易出错,
因此,我们将使用它的默认实现,该实现只需要给它一个DefaultList <ItemStack>
(将其复制为新文件):
- 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; } }
现在在您的BlockEntity
中实施ImplementedInventory
,
并为其提供存储该项目的DefaultedList <ItemStack>项目
实例。
对于此示例,我们将在库存中最多存储2件物品:
public class DemoBlockEntity extends BlockEntity implements ImplementedInventory { private final DefaultedList<ItemStack> items = DefaultedList.ofSize(2, ItemStack.EMPTY); @Override public DefaultedList<ItemStack> getItems() { return items; } [...] }
我们还需要保存容器以标记并从那里加载。
Inventories
具有帮助方法,可以非常轻松地完成此任务:
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); } }
从容器(或任何容器)中提取和放入
在我们的块类中,我们将覆盖activate
行为以从库存中放入和提取物品。
请注意,可以对任何实例执行此操作,而不仅仅是我们自己的(例如,您可以对箱子做相同的事情)。
首先,我们将处理放入内容物。 如果玩家拿着一个物品,他会放入他拿着的物品。
如果为空,它将进入第一个插槽;如果第一个为空,它将进入第二个插槽,
或者如果第二个也为空,我们将打印有关库存的一些信息。
请注意,将
ItemStack
放入内容物时,我们将其称为copy()
,这样它就不会在玩家的ItemStack
旁边被破坏。
public class ExampleBlock extends Block implements BlockEntityProvider { [...] @Override public boolean activate(BlockState blockState, World world, BlockPos blockPos, PlayerEntity player, Hand hand, BlockHitResult blockHitResult) { if (world.isClient) return true; Inventory blockEntity = (Inventory) world.getBlockEntity(blockPos); if (!player.getStackInHand(hand).isEmpty()) { // Check what is the first open slot and put an item from the player's hand there if (blockEntity.getInvStack(0).isEmpty()) { // Put the stack the player is holding into the inventory blockEntity.setInvStack(0, player.getStackInHand(hand).copy()); // Remove the stack from the player's hand player.getStackInHand(hand).setCount(0); } else if (blockEntity.getInvStack(1).isEmpty()) { blockEntity.setInvStack(1, player.getStackInHand(hand).copy()); player.getStackInHand(hand).setCount(0); } else { // If the inventory is full we'll print it's contents System.out.println("The first slot holds " + blockEntity.getInvStack(0) + " and the second slot holds " + blockEntity.getInvStack(1)); } } return true; } }
当玩家不持有物品时,我们将采取相反的行为。 我们将从第二个插槽中取出项目,然后第二个中的第一个为空。 如果第一个也是空的,我们将不做任何事情。
public class ExampleBlock extends Block implements BlockEntityProvider { [...] @Override public boolean activate(BlockState blockState, World world, BlockPos blockPos, PlayerEntity player, Hand hand, BlockHitResult blockHitResult) { ... if (!player.getStackInHand(hand).isEmpty()) { ... } else { // If the player is not holding anything we'll get give him the items in the block entity one by one // Find the first slot that has an item and give it to the player if (!blockEntity.getInvStack(1).isEmpty()) { // Give the player the stack in the inventory player.inventory.offerOrDrop(world, blockEntity.getInvStack(1)); // Remove the stack from the inventory blockEntity.removeInvStack(1); } else if (!blockEntity.getInvStack(0).isEmpty()) { player.inventory.offerOrDrop(world, blockEntity.getInvStack(0)); blockEntity.removeInvStack(0); } } return true; } }
实施补充内容物
如果您希望基于不同的方面(料斗或其他mod)与模块交互而具有不同的逻辑
您需要实施SidedInventory
。
如果说您想这样做,那么您就不能从块的上方插入,您可以这样做:
public class DemoBlockEntity extends BlockEntity implements ImplementedInventory, SidedInventory { [...] @Override public int[] getInvAvailableSlots(Direction var1) { // Just return an array of all slots int[] result = new int[getItems().size()]; for (int i = 0; i < result.length; i++) { result[i] = i; } return result; } @Override public boolean canInsertInvStack(int slot, ItemStack stack, Direction direction) { return direction != Direction.UP; } @Override public boolean canExtractInvStack(int slot, ItemStack stack, Direction direction) { return true; } }