User Tools

Site Tools


zh_cn:tutorial:blockentity

添加一个方块实体

介绍

BlockEntity主要用于在块内存储数据。 在创建一个之前,您需要一个 Block。 本教程将介绍BlockEntity类的创建及其注册。

创建一个方块实体

最简单的块实体仅扩展BlockEntity,并使用默认构造函数。 这是完全有效的,但不会为您的块授予任何特殊功能。

public class DemoBlockEntity extends BlockEntity {
   public DemoBlockEntity() {
      super(ExampleMod.DEMO_BLOCK_ENTITY);
   }
}

Bellow将向您展示如何创建ExampleMod.DEMO_BLOCK_ENTITY字段。

您可以简单地向此准系统类添加变量,或实现诸如TickableInventory之类的接口以添加更多功能。Tickable提供了一个单独的tick()方法,该滴答对世界上每个已加载的Block实例每滴答被调用一次。而Inventory则允许您的BlockEntity与自动化进行交互,例如 料斗-稍后可能会有专门针对此界面的单独教程。

注册你的方块实体

一旦创建了BlockEntity类,您将需要对其进行注册以使其起作用。 此过程的第一步是创建一个BlockEntityType,它将BlockBlockEntity链接在一起。 假设您的Block已创建并保存到本地变量DEMO_BLOCK,则将在下面的行中创建匹配的BlockEntityTypemodid:demo应替换为您的Mod ID和您要在其下注册BlockEntity的名称。

BlockEntityType应在您的onInitialize方法中注册,以确保它在正确的时候被注册。

public static BlockEntityType<DemoBlockEntity> DEMO_BLOCK_ENTITY;
 
@Override
public void onInitialize() {
   DEMO_BLOCK_ENTITY = Registry.register(Registry.BLOCK_ENTITY, "modid:demo", BlockEntityType.Builder.create(DemoBlockEntity::new, DEMO_BLOCK).build(null));
}

如上所示,一旦创建并注册了BlockEntityType,就可以在Block类中简单地实现BlockEntityProvider

@Override
public BlockEntity createBlockEntity(BlockView blockView) {
   return new DemoBlockEntity();
}

序列化数据

如果要将任何数据存储在BlockEntity中,则需要保存并加载,或者仅在加载BlockEntity时保留,并且只要您返回到它。幸运的是,保存和加载非常简单-您只需要覆盖toTag()fromTag()即可。

toTag()返回一个CompoundTag,其中应包含BlockEntity中的所有数据。如果您需要将BlockEntity数据与客户端同步,则此数据将保存到磁盘并通过数据包发送。调用toTag的默认实现非常重要,因为它将“标识数据(位置和ID)保存到标签中。否则,您尝试保存的所有其他数据都将丢失,因为它与头寸和BlockEntityType不相关。知道了这一点,下面的示例演示了如何将BlockEntity中的整数保存到标签中。在此示例中,整数保存在键数字下-您可以将其替换为任何字符串,但是标签中的每个键只能有一个条目,并且需要记住该键以便以后检索数据。

public class DemoBlockEntity extends BlockEntity {
 
   // Store the current value of the number
   private int number = 7;
 
   public DemoBlockEntity() {
      super(ExampleMod.DEMO_BLOCK_ENTITY);
   }
 
   // Serialize the BlockEntity
   public CompoundTag toTag(CompoundTag tag) {
      super.toTag(tag);
 
      // Save the current value of the number to the tag
      tag.putInt("number", number);
 
      return tag;
   }
}

为了以后检索数据,您还需要覆盖fromTag。 此方法与toTag相反-不会将数据保存到CompoundTag,而是为您提供了之前保存的标签,使您可以检索所需的任何数据。 与toTag一样,必须调用super.fromTag,并且您将需要使用相同的键来检索保存的数据。 要检索我们之前保存的号码,请参见下面的示例。

// Deserialize the BlockEntity
public void fromTag(CompoundTag tag) {
   super.fromTag(tag);
   number = tag.getInt("number");
}

一旦实现了toTagfromTag方法,您只需要确保在正确的时间调用它们即可。 每当您的BlockEntity数据发生更改并需要保存时,请调用markDirty()。 通过将您的块所在的块标记为脏,这将在下次保存世界时强制调用toTag方法。 根据一般经验,只要在BlockEntity类中更改任何自定义变量,只需调用markDirty()即可。

如果您需要将某些BlockEntity数据同步到客户端,出于渲染等目的,则应从Fabric API中实现BlockEntityClientSerializable。 此类提供了fromClientTagtoClientTag方法,它们的作用与前面讨论的fromTagtoTag方法基本相同,只是它们专门用于发送和接收。 客户端上的数据。

Overview

现在,您应该拥有自己的BlockEntity,可以按照各种方式扩展它以适应您的需求。 您注册了BlockEntityType,并用它来将BlockBlockEntity类连接在一起。 然后,您在Block类中实现了BlockEntityProvider,并使用该接口提供了新BlockEntity的实例。 最后,您学习了如何将数据保存到BlockEntity中,以及如何检索以备后用。

zh_cn/tutorial/blockentity.txt · Last modified: 2019/12/19 05:19 by lightcolour