This is an old revision of the document!
添加一个方块实体
介绍
BlockEntity主要用于在块内存储数据。 在创建一个之前,您需要一个 Block。 本教程将介绍BlockEntity类的创建及其注册。
创建一个方块实体
最简单的块实体仅扩展BlockEntity
,并使用默认构造函数。 这是完全有效的,但不会为您的块授予任何特殊功能。
public class DemoBlockEntity extends BlockEntity { public DemoBlockEntity() { super(ExampleMod.DEMO_BLOCK_ENTITY); } }
Bellow将向您展示如何创建ExampleMod.DEMO_BLOCK_ENTITY
字段。
您可以简单地向此准系统类添加变量,或实现诸如Tickable
和Inventory
之类的接口以添加更多功能。Tickable
提供了一个单独的tick()
方法,该滴答对世界上每个已加载的Block实例每滴答被调用一次。而``Inventory则允许您的BlockEntity与自动化进行交互,例如 料斗-稍后可能会有专门针对此界面的单独教程。
===== 注册你的方块实体 =====
一旦创建了
BlockEntity类,您将需要对其进行注册以使其起作用。 此过程的第一步是创建一个
BlockEntityType,它将
Block和
BlockEntity链接在一起。 假设您的
Block已创建并保存到本地变量
DEMO_BLOCK,则将在下面的行中创建匹配的
BlockEntityType。
modid:demo应替换为您的Mod ID和您要在其下注册
BlockEntity的名称。
BlockEntityType应在您的
onInitialize方法中注册,以确保它在正确的时候被注册。
<code java>
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));
}
</code>
如上所示,一旦创建并注册了
BlockEntityType,就可以在
Block类中简单地实现
BlockEntityProvider:
<code java>
@Override
public BlockEntity createBlockEntity(BlockView blockView) {
return new DemoBlockEntity();
}
</code>
===== 序列化数据 =====
If you want to store any data in your
BlockEntity, you will need to save and load it, or it will only be held while the
BlockEntity is loaded, and the data will reset whenever you come back to it. Luckily, saving and loading is quite simple - you only need to override
toTag() and
fromTag().
toTag() returns a
CompoundTag, which should contain all of the data in your
BlockEntity. This data is saved to the disk and also send through packets if you need to sync your
BlockEntity data with clients. It is very important to call the default implementation of
toTag, as it saves “Identifying Data” (position and ID) to the tag. Without this, any further data you try and save will be lost as it is not associated with a position and
BlockEntityType. Knowing this, the example below demonstrates saving an integer from your
BlockEntity to the tag. In the example, the integer is saved under the key
“number” - you can replace this with any string, but you can only have one entry for each key in your tag, and you will need to remember the key in order to retrieve the data later.
<code java>
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;
}
}
</code>
In order to retrieve the data later, you will also need to override
toTagfromTag
. This method is the opposite of toTag
- instead of saving your data to a CompoundTag
, you are given the tag which you saved earlier, enabling you to retrieve any data that you need. As with toTag
, it is essential that you call super.fromTag
, and you will need to use the same keys to retrieve data that you saved. To retrieve, the number we saved earlier, see the example below.
<code java>
Deserialize the BlockEntity
public void fromTag(CompoundTag tag) {
super.fromTag(tag);
number = tag.getInt(“number”);
}
</code>
Once you have implemented the and
fromTag methods, you simply need to ensure that they are called at the right time. Whenever your
BlockEntity data changes and needs to be saved, call
markDirty(). This will force the
toTag method to be called when the world is next saved by marking the chunk which your block is in as dirty. As a general rule of thumb, simply call
markDirty() whenever you change any custom variable in your
BlockEntity class.
If you need to sync some of your
BlockEntity data to the client, for purposes such as rendering, you should implement
BlockEntityClientSerializable from the Fabric API. This class provides the
fromClientTag and
toClientTag methods, which work much the same as the previously discussed
fromTag and
toTag methods, except that they are used specifically for sending to and receiving data on the client.
===== Overview =====
You should now have your very own
BlockEntity, which you can expand in various ways to suit your needs. You registered a
BlockEntityType, and used it to connect your
Block and
BlockEntity classes together. Then, you implemented
BlockEntityProvider in your
Block class, and used the interface to provide an instance of your new
BlockEntity. Finally, you learned how to save data to your
BlockEntity'', and how to retrieve for use later.