User Tools

Site Tools


zh_cn:tutorial:inventory

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
zh_cn:tutorial:inventory [2019/12/19 05:34] lightcolourzh_cn:tutorial:inventory [2024/08/27 03:03] (current) solidblock
Line 1: Line 1:
-====== 将物品放容器中 ====== +====== 在方块存储物品 ====== 
-阅读本教程之前,请确保[[tutorial:blockentity |方块实体]]制作完成。+阅读本教程之前,请确保已经做好了[[zh_cn:tutorial:blockentity|方块实体]]。 
 + 
 +将物品存储在 BlockEntity(方块实体)中的标准方法是使其为 ''Inventory''这使得漏斗(或其他模组)无需任何额外的工作即可从您的 BlockEntity 放入和提取物品。  
 + 
 +这个教程是用于 1.21 的,对于旧版本,一些方法可能改变。 
 + 
 +===== 实现 Inventory 接口 ===== 
 + 
 +''Inventory'' 只是一个接口,这意味着实际的 ''ItemStack'' 状态将需要存储在您的''BlockEntity''上。可以使用''DefaultedList <ItemStack>''作为存储这些''ItemStacks''的简便方法,且可以将其默认设置为''ItemStack.Empty'',用来表示物品堆没有任何物品。实现 ''Inventory''非常简单,但乏味且容易出错,因此,我们将使用其默认实现,该实现只需要给它一个''DefaultList <ItemStack>''(将其复制为新文件):
  
-将物品存储在BlockEntity中的标准方法是使其成为''Inventory'' 
-这使得漏斗(或其他mods)无需任何额外的工作即可从您的BlockEntity放入和提取物品。  
-===== 实施Inventory ===== 
-''Inventory''只是一个接口,这意味着实际的''ItemStack''状态将需要存储在您的''BlockEntity''上。 
-可以使用''DefaultedList <ItemStack>''作为存储这些''ItemStacks''的简便方法, 
-因为可以将其默认设置为''ItemStack.Empty'',这是表示插槽中没有项目的正确方法。 
-实施''广告资源''非常简单,但乏味且容易出错, 
-因此,我们将使用它的默认实现,该实现只需要给它一个''DefaultList <ItemStack>''(将其复制为新文件): 
 <code java ImplementedInventory.java> <code java ImplementedInventory.java>
 /** /**
- A simple {@code Inventory} implementation with only default methods + an item list getter.+ 一个简单的 {@code Inventory} 实现,仅有默认的方法和物品列表的 getter
  *  *
  * Originally by Juuz  * Originally by Juuz
  */  */
 public interface ImplementedInventory extends Inventory { 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();     DefaultedList<ItemStack> getItems();
-    // Creation+    
     /**     /**
-     Creates an inventory from the item list.+     从物品列表创建物品栏。
      */      */
     static ImplementedInventory of(DefaultedList<ItemStack> items) {     static ImplementedInventory of(DefaultedList<ItemStack> items) {
         return () -> items;         return () -> items;
     }     }
 +    
     /**     /**
-     Creates a new inventory with the size.+     根据指定的尺寸创建新的物品栏。
      */      */
     static ImplementedInventory ofSize(int size) {     static ImplementedInventory ofSize(int size) {
         return of(DefaultedList.ofSize(size, ItemStack.EMPTY));         return of(DefaultedList.ofSize(size, ItemStack.EMPTY));
     }     }
-    // Inventory+    
     /**     /**
-     Returns the inventory 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 isInvEmpty() { +    default boolean isEmpty() { 
-        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;
     }     }
 +    
     /**     /**
-     Gets the item in the slot.+     检索槽位中的物品。
      */      */
     @Override     @Override
-    default ItemStack getInvStack(int slot) {+    default ItemStack getStack(int slot) {
         return getItems().get(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, +     @param slot  从该槽位移除。 
-     takes all items in that slot.+     @param count 需要移除的物品个数。如果槽位中的物品少于需要的,则将其全部取出。
      */      */
     @Override     @Override
-    default ItemStack takeInvStack(int slot, int count) {+    default ItemStack removeStack(int slot, int count) {
         ItemStack result = Inventories.splitStack(getItems(), slot, count);         ItemStack result = Inventories.splitStack(getItems(), slot, count);
         if (!result.isEmpty()) {         if (!result.isEmpty()) {
Line 76: Line 82:
         return result;         return result;
     }     }
 +    
     /**     /**
-     Removes the current stack in the {@code slot} and returns it.+     从物品栏槽位移除所有物品。 
 +     @param slot 从该槽位移除。
      */      */
     @Override     @Override
-    default ItemStack removeInvStack(int slot) {+    default ItemStack removeStack(int slot) {
         return Inventories.removeStack(getItems(), 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()}), +     @param slot  替换该槽位的物品堆。 
-     * it gets resized to this inventory's maximum amount.+     @param stack 替换后新的物品堆。如果堆对于此物品栏过大({@link Inventory#getMaxCountPerStack()}),则压缩为物品栏的最大数量。
      */      */
     @Override     @Override
-    default void setInvStack(int slot, ItemStack stack) {+    default void setStack(int slot, ItemStack stack) {
         getItems().set(slot, stack);         getItems().set(slot, stack);
-        if (stack.getCount() > getInvMaxStackAmount()) { +        if (stack.getCount() > getMaxCountPerStack()) { 
-            stack.setCount(getInvMaxStackAmount());+            stack.setCount(getMaxCountPerStack());
         }         }
     }     }
 +    
     /**     /**
-     Clears {@linkplain #getItems() the item list}}.+     清除物品栏。
      */      */
     @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 canPlayerUseInv(PlayerEntity player) {+    default boolean canPlayerUse(PlayerEntity player) {
         return true;         return true;
     }     }
Line 113: Line 132:
 </code> </code>
  
-现在在的''BlockEntity''中实''ImplementedInventory''+现在在的 ''BlockEntity'' 中实现 ''ImplementedInventory''并为其提供存储该物品的 ''DefaultedList<ItemStack> items'' 实例。对于此例,我们将在物品栏中最多存储 2 件物品: 
-并为其提供存储该项目的''DefaultedList <ItemStack>项目''实例。 +<code java DemoBlockEntity.java>
-对于此例,我们将在库存中最多存储2件物品: +
-<code java>+
 public class DemoBlockEntity extends BlockEntity implements ImplementedInventory { public class DemoBlockEntity extends BlockEntity implements ImplementedInventory {
     private final DefaultedList<ItemStack> items = DefaultedList.ofSize(2, ItemStack.EMPTY);     private final DefaultedList<ItemStack> items = DefaultedList.ofSize(2, ItemStack.EMPTY);
Line 129: Line 146:
  
 </code> </code>
-我们还需要保存容器以标记并从那里加载。 +我们还需要将物品栏保存到 NBT 并从那里加载。''Inventories'' 具有助方法,可以使得这个非常轻松: 
-''Inventories''具有助方法,可以非常轻松地完成此任务: +<code java DemoBlockEntity.java>
-<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 CompoundTag toTag(CompoundTag tag) { +    public NbtCompound writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) { 
-        Inventories.toTag(tag,items); +        Inventories.writeNbt(nbt, items, registryLookup); 
-        return super.toTag(tag);+        return super.writeNbt(nbt, registryLookup);
     }     }
 } }
 </code> </code>
-===== 从容器(或任何容器)中提取和放入 ===== + 
-我们块类中,我们将覆盖''activate''行为以从库存入和提取物品。 +===== 从物品栏(或任何物品栏)中提取和放入 ===== 
-注意可以对任何''''实例执行此操作仅是我们自己的(例如,可以对箱子做同的事)。 + 
-首先我们处理放入内容物。 如果玩家拿着一个物品,放入他拿着的物品。 +我们覆盖方块类中的 ''onUss'' 行为以从我们的物品栏入和提取物品。注意这也可以对任何 ''Inventory'' 实例完成,不仅是我们自己的(例如,也因此可以对箱子方块做同的事)。 
-如果为空,它将进入第一个如果第一个为空,它将进入第二个槽, + 
-或者如果第二个也为空,我们将打印有关库存一些信息。 +首先我们处理第一个槽位,如果是空的。玩家如果拿着物品,拿着的物品放入物品进入第一个槽位,如果或者进入第二个槽位,如果第一个是空的,或者如果第二个,我们则会输出与物品栏有关的信息。 
-注意将''ItemStack''内容物时,我们将其称为''copy()'',这样它就不会玩家的''ItemStack''旁边被破坏。 + 
-<code java> +注意我们将 ''ItemStack'' 入物品栏调用 ''copy()'',这样不会随着玩家的 ''ItemStack'' 被破坏。 
-public class ExampleBlock extends Block implements BlockEntityProvider {+<code java DemoBlock.java> 
 +public class DemoBlock extends BlockWithEntity {
     [...]     [...]
     @Override     @Override
-    public boolean activate(BlockState blockState, World world, BlockPos blockPos, PlayerEntity player, Hand hand, BlockHitResult blockHitResult) { +    protected ItemActionResult onUseWithItem(ItemStack stack, BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { 
-        if (world.isClient) return true+        if (world.isClient) return ActionResult.SUCCESS
-        Inventory blockEntity = (Inventory) world.getBlockEntity(blockPos); +         
 +        if (!(world.getBlockEntity(posinstanceof 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's hand there +            // 检查第一个开放槽位是什么,并从玩家手中将物品放入 
-            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's hand+                // 从玩家手中移除物品堆
                 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 +                // 如果物品栏满,提醒玩家 
-                System.out.println("The first slot holds +                player.sendMessage(Text.literal("物品栏满!第一个槽位是") 
-                        blockEntity.getInvStack(0) and the second slot holds blockEntity.getInvStack(1));+                    .append(blockEntity.getStack(0).getName()) 
 +                    .append(",第二个槽位是"
 +                    .append(blockEntity.getStack(1).getName()));
             }             }
         }          } 
-        return true;+        return ItemActionResult.SUCCESS;
     }     }
 } }
 </code> </code>
  
 +玩家不持有物品时,我们将采取相反的行为。我们将从第二个槽位中取出物品,如果第二个是空的就第一个。如果第一个也是空的,就不做任何事情。
  
-当玩家不持有物品时,我们将采取相反的行为。 我们将从第二个插槽中取出项目,然后第二个中的第一个为空。 +<code java DemoBlock.java> 
-如果第一个也是空的,我们将不做任何事情。 +public class DemoBlock extends BlockWithEntity {
- +
-<code java> +
-public class ExampleBlock extends Block implements BlockEntityProvider {+
     [...]     [...]
     @Override     @Override
-    public boolean activate(BlockState blockState, World world, BlockPos blockPos, PlayerEntity player, Hand hand, BlockHitResult blockHitResult) {+    protected ItemActionResult onUseWithItem(ItemStack stack, BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
         ...         ...
         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, blockEntity.getInvStack(1)); +                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, blockEntity.getInvStack(0)); +                player.getInventory().offerOrDrop(blockEntity.getStack(0)); 
-                blockEntity.removeInvStack(0);+                blockEntity.removeStack(0)
 +            } else { 
 +                return ItemActionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
             }             }
         }         }
                  
-        return true;+        return ItemActionResult.SUCCESS;
     }     }
 } }
 </code> </code>
  
-===== 实施补充内容物 ===== +===== 实现 SidedInventory 接口 ===== 
-如果希望基于不同的面(斗或其他mod与模块交互而具有不同逻辑 +如果希望基于与方块不同的面(斗或其他模组进行交互不同逻辑,你可以现 SidedInventory 接口。如果说使得方块不能从上插入,可以这样做: 
-您需要施''SidedInventory'' + 
-如果说这样做,那么您就不能从块的插入,可以这样做: +<code java DemoBlockEntity.java>
-<code java>+
 public class DemoBlockEntity extends BlockEntity implements ImplementedInventory, SidedInventory { public class DemoBlockEntity extends BlockEntity implements ImplementedInventory, SidedInventory {
     [...]     [...]
     @Override     @Override
-    public int[] getInvAvailableSlots(Direction var1) {+    public int[] getInvAvailableSlots(Direction side) {
         // Just return an array of all slots         // Just return an array of all slots
-        int[] result = new int[getItems().size()]; +        return IntStream.of(getItems().size()).toArray();
-        for (int i = 0; i < result.length; i+++
-            result[i] = i; +
-        } +
- +
-        return result;+
     }     }
  
     @Override     @Override
-    public boolean canInsertInvStack(int slot, ItemStack stack, Direction direction) {+    public boolean canInsert(int slot, ItemStack stack, Direction direction) {
         return direction != Direction.UP;         return direction != Direction.UP;
     }     }
  
     @Override     @Override
-    public boolean canExtractInvStack(int slot, ItemStack stack, Direction direction) {+    public boolean canExtract(int slot, ItemStack stack, Direction direction) {
         return true;         return true;
     }     }
 } }
- 
 </code> </code>
- 
zh_cn/tutorial/inventory.1576733679.txt.gz · Last modified: 2019/12/19 05:34 by lightcolour