zh_cn:tutorial:inventory
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| zh_cn:tutorial:inventory [2019/12/19 05:34] – lightcolour | zh_cn:tutorial:inventory [2024/08/27 03:03] (current) – solidblock | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== | + | ====== 在方块中存储物品 |
| - | 阅读本教程之前,请确保您已将[[tutorial: | + | 阅读本教程之前,请确保已经做好了[[zh_cn:tutorial: |
| + | |||
| + | 将物品存储在 BlockEntity(方块实体)中的标准方法是使其成为 '' | ||
| + | |||
| + | 这个教程是用于 1.21 的,对于旧版本,一些方法可能改变。 | ||
| + | |||
| + | ===== 实现 Inventory 接口 ===== | ||
| + | |||
| + | '' | ||
| - | 将物品存储在BlockEntity中的标准方法是使其成为'' | ||
| - | 这使得漏斗(或其他mods)无需任何额外的工作即可从您的BlockEntity放入和提取物品。 | ||
| - | ===== 实施Inventory ===== | ||
| - | '' | ||
| - | 可以使用'' | ||
| - | 因为可以将其默认设置为'' | ||
| - | 实施'' | ||
| - | 因此,我们将使用它的默认实现,该实现只需要给它一个'' | ||
| <code java ImplementedInventory.java> | <code java ImplementedInventory.java> | ||
| /** | /** | ||
| - | | + | |
| * | * | ||
| * Originally by Juuz | * Originally by Juuz | ||
| */ | */ | ||
| public interface ImplementedInventory extends Inventory { | public interface ImplementedInventory extends Inventory { | ||
| + | |||
| /** | /** | ||
| - | | + | |
| - | | + | |
| */ | */ | ||
| DefaultedList< | DefaultedList< | ||
| - | | + | |
| /** | /** | ||
| - | | + | |
| */ | */ | ||
| static ImplementedInventory of(DefaultedList< | static ImplementedInventory of(DefaultedList< | ||
| return () -> items; | return () -> items; | ||
| } | } | ||
| + | | ||
| /** | /** | ||
| - | | + | |
| */ | */ | ||
| static ImplementedInventory ofSize(int size) { | static ImplementedInventory ofSize(int size) { | ||
| return of(DefaultedList.ofSize(size, | return of(DefaultedList.ofSize(size, | ||
| } | } | ||
| - | | + | |
| /** | /** | ||
| - | | + | |
| */ | */ | ||
| @Override | @Override | ||
| - | default int getInvSize() { | + | default int size() { |
| return getItems().size(); | return getItems().size(); | ||
| } | } | ||
| + | | ||
| /** | /** | ||
| - | * @return true if this inventory has only empty stacks, false otherwise | + | * 检查物品栏是否为空。 |
| + | * @return true,如果物品栏仅有一个空堆,否则为true。 | ||
| */ | */ | ||
| @Override | @Override | ||
| - | default boolean | + | default boolean |
| - | for (int i = 0; i < getInvSize(); i++) { | + | for (int i = 0; i < size(); i++) { |
| - | ItemStack stack = getInvStack(i); | + | ItemStack stack = getStack(i); |
| if (!stack.isEmpty()) { | if (!stack.isEmpty()) { | ||
| return false; | return false; | ||
| Line 56: | Line 60: | ||
| return true; | return true; | ||
| } | } | ||
| + | | ||
| /** | /** | ||
| - | | + | |
| */ | */ | ||
| @Override | @Override | ||
| - | default ItemStack | + | default ItemStack |
| return getItems().get(slot); | return getItems().get(slot); | ||
| } | } | ||
| + | | ||
| /** | /** | ||
| - | | + | |
| - | | + | |
| - | | + | |
| */ | */ | ||
| @Override | @Override | ||
| - | default ItemStack | + | default ItemStack |
| ItemStack result = Inventories.splitStack(getItems(), | ItemStack result = Inventories.splitStack(getItems(), | ||
| if (!result.isEmpty()) { | if (!result.isEmpty()) { | ||
| Line 76: | Line 82: | ||
| return result; | return result; | ||
| } | } | ||
| + | | ||
| /** | /** | ||
| - | | + | |
| + | | ||
| */ | */ | ||
| @Override | @Override | ||
| - | default ItemStack | + | default ItemStack |
| return Inventories.removeStack(getItems(), | return Inventories.removeStack(getItems(), | ||
| } | } | ||
| + | | ||
| /** | /** | ||
| - | | + | |
| - | | + | |
| - | * it gets resized to this inventory' | + | |
| */ | */ | ||
| @Override | @Override | ||
| - | default void setInvStack(int slot, ItemStack stack) { | + | default void setStack(int slot, ItemStack stack) { |
| getItems().set(slot, | getItems().set(slot, | ||
| - | if (stack.getCount() > getInvMaxStackAmount()) { | + | if (stack.getCount() > getMaxCountPerStack()) { |
| - | stack.setCount(getInvMaxStackAmount()); | + | stack.setCount(getMaxCountPerStack()); |
| } | } | ||
| } | } | ||
| + | | ||
| /** | /** | ||
| - | | + | |
| */ | */ | ||
| @Override | @Override | ||
| Line 102: | Line 112: | ||
| getItems().clear(); | getItems().clear(); | ||
| } | } | ||
| + | | ||
| + | /** | ||
| + | * 将方块状态标记为脏。 | ||
| + | * 更改物品栏之后必须调用,所以游戏正确地储存物品栏内容并提取邻近方块物品栏改变。 | ||
| + | | ||
| @Override | @Override | ||
| default void markDirty() { | default void markDirty() { | ||
| - | // Override if you want behavior. | + | // 需要行为时,覆盖此方法。 |
| } | } | ||
| + | | ||
| + | /** | ||
| + | * @return true 如果玩家可以使用物品栏,否则为 false。i | ||
| + | | ||
| @Override | @Override | ||
| - | default boolean | + | default boolean |
| return true; | return true; | ||
| } | } | ||
| Line 113: | Line 132: | ||
| </ | </ | ||
| - | 现在在您的'' | + | 现在在你的 '' |
| - | 并为其提供存储该项目的'' | + | < |
| - | 对于此示例,我们将在库存中最多存储2件物品: | + | |
| - | <code java> | + | |
| public class DemoBlockEntity extends BlockEntity implements ImplementedInventory { | public class DemoBlockEntity extends BlockEntity implements ImplementedInventory { | ||
| private final DefaultedList< | private final DefaultedList< | ||
| Line 129: | Line 146: | ||
| </ | </ | ||
| - | 我们还需要保存容器以标记并从那里加载。 | + | 我们还需要将物品栏保存到 NBT 并从那里加载。'' |
| - | '' | + | < |
| - | <code java> | + | |
| public class DemoBlockEntity extends BlockEntity implements ImplementedInventory { | public class DemoBlockEntity extends BlockEntity implements ImplementedInventory { | ||
| [...] | [...] | ||
| @Override | @Override | ||
| - | public void fromTag(CompoundTag tag) { | + | public void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) { |
| - | super.fromTag(tag); | + | super.readNbt(nbt, registryLookup); |
| - | Inventories.fromTag(tag,items); | + | Inventories.readNbt(nbt, items, registryLookup); |
| } | } | ||
| @Override | @Override | ||
| - | public | + | public |
| - | Inventories.toTag(tag,items); | + | Inventories.writeNbt(nbt, items, registryLookup); |
| - | return super.toTag(tag); | + | return super.writeNbt(nbt, registryLookup); |
| } | } | ||
| } | } | ||
| </ | </ | ||
| - | ===== 从容器(或任何容器)中提取和放入 ===== | + | |
| - | 在我们的块类中,我们将覆盖'' | + | ===== 从物品栏(或任何物品栏)中提取和放入 ===== |
| - | 请注意,可以对任何'''' | + | |
| - | 首先,我们将处理放入内容物。 | + | 我们覆盖方块类中的 '' |
| - | 如果为空,它将进入第一个插槽;如果第一个为空,它将进入第二个插槽, | + | |
| - | 或者如果第二个也为空,我们将打印有关库存的一些信息。 | + | 首先我们处理第一个槽位,如果是空的。玩家如果拿着物品,则会将拿着的物品放入。物品进入第一个槽位,如果是空的,或者进入第二个槽位,如果第一个是空的,或者如果第二个是空的,我们则会输出与物品栏有关的信息。 |
| - | 请注意,将'' | + | |
| - | <code java> | + | 注意我们将 '' |
| - | public class ExampleBlock | + | < |
| + | public class DemoBlock | ||
| [...] | [...] | ||
| @Override | @Override | ||
| - | | + | |
| - | if (world.isClient) return | + | if (world.isClient) return |
| - | | + | |
| + | if (!(world.getBlockEntity(pos) instanceof DemoBlockEntity blockEntity)) { | ||
| + | return ItemActionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; | ||
| + | } | ||
| if (!player.getStackInHand(hand).isEmpty()) { | if (!player.getStackInHand(hand).isEmpty()) { | ||
| - | // Check what is the first open slot and put an item from the player' | + | // 检查第一个开放槽位是什么,并从玩家手中将物品放入 |
| - | if (blockEntity.getInvStack(0).isEmpty()) { | + | if (blockEntity.getStack(0).isEmpty()) { |
| - | // Put the stack the player is holding into the inventory | + | // 将玩家持有的物品堆放入物品栏 |
| - | blockEntity.setInvStack(0, player.getStackInHand(hand).copy()); | + | blockEntity.setStack(0, player.getStackInHand(hand).copy()); |
| - | // Remove the stack from the player' | + | // 从玩家手中移除物品堆 |
| player.getStackInHand(hand).setCount(0); | player.getStackInHand(hand).setCount(0); | ||
| - | } else if (blockEntity.getInvStack(1).isEmpty()) { | + | } else if (blockEntity.getStack(1).isEmpty()) { |
| - | blockEntity.setInvStack(1, player.getStackInHand(hand).copy()); | + | blockEntity.setStack(1, player.getStackInHand(hand).copy()); |
| player.getStackInHand(hand).setCount(0); | player.getStackInHand(hand).setCount(0); | ||
| } else { | } else { | ||
| - | // If the inventory is full we'll print it's contents | + | // 如果物品栏满,提醒玩家 |
| - | | + | |
| - | | + | |
| + | .append(",第二个槽位是") | ||
| + | .append(blockEntity.getStack(1).getName())); | ||
| } | } | ||
| } | } | ||
| - | return | + | return |
| } | } | ||
| } | } | ||
| </ | </ | ||
| + | 玩家不持有物品时,我们将采取相反的行为。我们将从第二个槽位中取出物品,如果第二个是空的就第一个。如果第一个也是空的,就不做任何事情。 | ||
| - | 当玩家不持有物品时,我们将采取相反的行为。 我们将从第二个插槽中取出项目,然后第二个中的第一个为空。 | + | < |
| - | 如果第一个也是空的,我们将不做任何事情。 | + | public class DemoBlock |
| - | + | ||
| - | <code java> | + | |
| - | public class ExampleBlock | + | |
| [...] | [...] | ||
| @Override | @Override | ||
| - | | + | |
| ... | ... | ||
| if (!player.getStackInHand(hand).isEmpty()) { | if (!player.getStackInHand(hand).isEmpty()) { | ||
| ... | ... | ||
| } else { | } 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()) { | + | if (!blockEntity.getStack(1).isEmpty()) { |
| - | // Give the player the stack in the inventory | + | // 给玩家物品栏中的物品堆 |
| - | player.inventory.offerOrDrop(world, | + | player.getInventory().offerOrDrop(blockEntity.getStack(1)); |
| - | // Remove the stack from the inventory | + | // 从物品栏移除物品堆 |
| - | blockEntity.removeInvStack(1); | + | blockEntity.removeStack(1); |
| - | } else if (!blockEntity.getInvStack(0).isEmpty()) { | + | } else if (!blockEntity.getStack(0).isEmpty()) { |
| - | player.inventory.offerOrDrop(world, | + | player.getInventory().offerOrDrop(blockEntity.getStack(0)); |
| - | blockEntity.removeInvStack(0); | + | blockEntity.removeStack(0); |
| + | } else { | ||
| + | return ItemActionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; | ||
| } | } | ||
| } | } | ||
| | | ||
| - | return | + | return |
| } | } | ||
| } | } | ||
| </ | </ | ||
| - | ===== 实施补充内容物 | + | ===== 实现 SidedInventory 接口 |
| - | 如果您希望基于不同的方面(料斗或其他mod)与模块交互而具有不同的逻辑 | + | 如果你希望有基于与方块不同的面(漏斗或者其他模组)进行交互的不同逻辑,你可以实现 SidedInventory |
| - | 您需要实施'' | + | |
| - | 如果说您想这样做,那么您就不能从块的上方插入,您可以这样做: | + | < |
| - | <code java> | + | |
| public class DemoBlockEntity extends BlockEntity implements ImplementedInventory, | public class DemoBlockEntity extends BlockEntity implements ImplementedInventory, | ||
| [...] | [...] | ||
| @Override | @Override | ||
| - | public int[] getInvAvailableSlots(Direction | + | public int[] getInvAvailableSlots(Direction |
| // Just return an array of all slots | // Just return an array of all slots | ||
| - | | + | |
| - | for (int i = 0; i < result.length; i++) { | + | |
| - | result[i] = i; | + | |
| - | } | + | |
| - | + | ||
| - | return result; | + | |
| } | } | ||
| @Override | @Override | ||
| - | public boolean | + | public boolean |
| return direction != Direction.UP; | return direction != Direction.UP; | ||
| } | } | ||
| @Override | @Override | ||
| - | public boolean | + | public boolean |
| return true; | return true; | ||
| } | } | ||
| } | } | ||
| - | |||
| </ | </ | ||
| - | |||
zh_cn/tutorial/inventory.1576733679.txt.gz · Last modified: 2019/12/19 05:34 by lightcolour