在方块中存储物品 [Fabric Wiki]

您所在的位置:网站首页 免费下载收费歌曲的网站推荐 在方块中存储物品 [Fabric Wiki]

在方块中存储物品 [Fabric Wiki]

2024-03-03 16:22| 来源: 网络整理| 查看: 265

Table of Contents 在方块中存储物品 实现 Inventory 接口 从物品栏(或任何物品栏)中提取和放入 实现 SidedInventory 接口 在方块中存储物品

阅读本教程之前,请确保已经做好了方块实体。

将物品存储在 BlockEntity(方块实体)中的标准方法是使其成为Inventory。这使得漏斗(或其他模组)无需任何额外的工作即可从您的 BlockEntity 放入和提取物品。

实现 Inventory 接口

Inventory 只是一个接口,这意味着实际的 ItemStack 状态将需要存储在您的BlockEntity上。可以使用DefaultedList 作为存储这些ItemStacks的简便方法,且可以将其默认设置为ItemStack.Empty,用来表示物品堆没有任何物品。实现 Inventory非常简单,但乏味且容易出错,因此,我们将使用其默认实现,该实现只需要给它一个DefaultList (将其复制为新文件):

ImplementedInventory.java /** * 一个简单的 {@code Inventory} 实现,仅有默认的方法和物品列表获取器。 * * Originally by Juuz */ public interface ImplementedInventory extends Inventory {   /** * 从此物品栏中检索物品。 * 每次被调用时必须返回相同实例。 */ DefaultedList getItems();   /** * 从物品列表创建物品栏。 */ static ImplementedInventory of(DefaultedList items) { return () -> items; }   /** * 根据指定的尺寸创建新的物品栏。 */ static ImplementedInventory ofSize(int size) { return of(DefaultedList.ofSize(size, ItemStack.EMPTY)); }   /** * 返回物品栏的大小。 */ @Override default int size() { return getItems().size(); }   /** * 检查物品栏是否为空。 * @return true,如果物品栏仅有一个空堆,否则为true。 */ @Override default boolean isEmpty() { for (int i = 0; i getMaxCountPerStack()) { stack.setCount(getMaxCountPerStack()); } }   /** * 清除物品栏。 */ @Override default void clear() { getItems().clear(); }   /** * 将方块状态标记为脏。 * 更改物品栏之后必须调用,所以游戏正确地储存物品栏内容并提取邻近方块物品栏改变。 */ @Override default void markDirty() { // 需要行为时,覆盖此方法。 }   /** * @return true 如果玩家可以使用物品栏,否则为 false。i */ @Override default boolean canPlayerUse(PlayerEntity player) { return true; } }

现在在您的 BlockEntity 中实现ImplementedInventory,并为其提供存储该物品的 DefaultedList items 实例。对于此例,我们将在物品栏中最多存储2件物品:

public class DemoBlockEntity extends BlockEntity implements ImplementedInventory { private final DefaultedList items = DefaultedList.ofSize(2, ItemStack.EMPTY);   @Override public DefaultedList getItems() { return items; } [...]   }

我们还需要将物品栏保存到标签并从那里加载。Inventories 具有帮助方法,可以使得这个非常轻松:

public class DemoBlockEntity extends BlockEntity implements ImplementedInventory { [...] @Override public void readNbt(NbtCompound nbt) { super.readNbt(nbt); Inventories.readNbt(nbt, items); }   @Override public NbtCompound writeNbt(NbtCompound nbt) { Inventories.writeNbt(nbt, items); return super.writeNbt(nbt); } } 从物品栏(或任何物品栏)中提取和放入

我们覆盖方块类中的 `onUse` 行为以从我们的物品栏中加入和提取物品。注意这也可以对任何 Inventory 实例完成,不仅是我们自己的(例如,也因此可以对箱子方块做同样的事)。首先我们处理第一个槽位,如果是空的。玩家如果拿着物品,则会将拿着的物品放入。物品进入第一个槽位,如果是空的,或者进入第二个槽位,如果第一个是空的,或者如果第二个是空的,我们则会输出与物品栏有关的信息。注意我们将 ItemStack 插入物品栏时调用 copy(),这样不会随着玩家的 ItemStack 而被破坏。

public class ExampleBlock extends Block implements BlockEntityProvider { [...] @Override public ActionResult onUse(BlockState blockState, World world, BlockPos blockPos, PlayerEntity player, Hand hand, BlockHitResult blockHitResult) { if (world.isClient) return ActionResult.SUCCESS; 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.getStack(0).isEmpty()) { // Put the stack the player is holding into the inventory blockEntity.setStack(0, player.getStackInHand(hand).copy()); // Remove the stack from the player's hand player.getStackInHand(hand).setCount(0); } else if (blockEntity.getStack(1).isEmpty()) { blockEntity.setStack(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.getStack(0) + " and the second slot holds " + blockEntity.getStack(1)); } } return ActionResult.SUCCESS; } }

当玩家不持有物品时,我们将采取相反的行为。我们将从第二个槽位中取出项目,然后第二个中的第一个为空。如果第一个也是空的,我们将不做任何事情。

public class ExampleBlock extends Block implements BlockEntityProvider { [...] @Override public ActionResult onUse(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.getStack(1).isEmpty()) { // Give the player the stack in the inventory player.getInventory().offerOrDrop(blockEntity.getStack(1)); // Remove the stack from the inventory blockEntity.removeStack(1); } else if (!blockEntity.getStack(0).isEmpty()) { player.getInventory().offerOrDrop(blockEntity.getStack(0)); blockEntity.removeStack(0); } }   return ActionResult.SUCCESS; } } 实现 SidedInventory 接口

如果你希望有基于与方块不同的面(漏斗或者其他模组)进行交互的不同逻辑,你可以实现 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


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3