tutorial:blockentity
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
tutorial:blockentity [2024/08/25 23:50] – according to vanilla, block entity id usually match block id solidblock | tutorial:blockentity [2025/04/01 12:20] (current) – [Block entity ticking] solidblock | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== Adding a BlockEntity ====== | ====== Adding a BlockEntity ====== | ||
- | ===== Introduction ===== | + | A **block entity** is primarily used to store data within blocks. Before creating one, you will need a [[blocks|Block]]. This tutorial will cover the creation of your BlockEntity class, and its registration. |
- | A BlockEntity is primarily used to store data within blocks. Before creating one, you will need a [[tutorial: | + | ===== Creating |
- | ===== Creating a BlockEntity ===== | + | The simplest |
- | + | ||
- | The simplest | + | |
<code java DemoBlockEntity.java> | <code java DemoBlockEntity.java> | ||
public class DemoBlockEntity extends BlockEntity { | public class DemoBlockEntity extends BlockEntity { | ||
public DemoBlockEntity(BlockPos pos, BlockState state) { | public DemoBlockEntity(BlockPos pos, BlockState state) { | ||
- | super(ExampleMod.DEMO_BLOCK_ENTITY, pos, state); | + | super(TutorialBlockEntityTypes.DEMO_BLOCK, pos, state); |
} | } | ||
} | } | ||
</ | </ | ||
- | Please ensure that the constructor only takes the two parameters, otherwise the method reference '' | + | Please ensure that the constructor only takes the two parameters, otherwise the method reference '' |
Block entities support a variety of methods to enable functionality such as serialization to and deserialization from NBT, providing inventories, | Block entities support a variety of methods to enable functionality such as serialization to and deserialization from NBT, providing inventories, | ||
- | ===== Registering | + | ===== Registering |
- | Once you have created the '' | + | Once you have created the '' |
- | The '' | + | The '' |
+ | <code java TutorialBlocks.java> | ||
+ | public final class TutorialBlocks { | ||
+ | [...] | ||
+ | | ||
+ | // For versions before 1.21.2 | ||
+ | // public static final DemoBlock DEMO_BLOCK = register(" | ||
+ | | ||
+ | // For version 1.21.2 and later | ||
+ | public static final DemoBlock DEMO_BLOCK = register(" | ||
+ | | ||
+ | [...] | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | <code java TutorialBlockEntityTypes.java> | ||
+ | public class TutorialBlockEntityTypes { | ||
+ | public static <T extends BlockEntityType<?>> | ||
+ | return Registry.register(Registries.BLOCK_ENTITY_TYPE, | ||
+ | } | ||
+ | |||
+ | public static final BlockEntityType< | ||
+ | " | ||
+ | // For versions before 1.21.2, please use BlockEntityType.Builder. | ||
+ | FabricBlockEntityTypeBuilder.create(DemoBlockEntity:: | ||
+ | ); | ||
+ | | ||
+ | public static void initialize() { | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | Remember to refer to the '' | ||
<code java ExampleMod.java> | <code java ExampleMod.java> | ||
- | public class ExampleMod | + | public class ExampleMod |
- | | + | |
- | Registries.BLOCK, | + | |
- | Identifier.of(" | + | |
- | new DemoBlock(AbstractBlock.Settings.create()) | + | |
- | ); | + | |
- | public static final BlockEntityType< | + | |
- | Registries.BLOCK_ENTITY_TYPE, | + | |
- | Identifier.of(" | + | |
- | BlockEntityType.Builder.create(DemoBlockEntity:: | + | |
- | ); | + | |
| | ||
@Override | @Override | ||
public void onInitialize() { | public void onInitialize() { | ||
[...] | [...] | ||
+ | | ||
+ | TutorialBlockEntityTypes.initialize(); | ||
} | } | ||
} | } | ||
</ | </ | ||
- | |||
- | > :!: In this example, for simplicity, we just placed the block and block entities inside the '' | ||
For old versions, if you cannot access '' | For old versions, if you cannot access '' | ||
- | The block entity type defines that only the '' | + | The block entity type defines that only the '' |
+ | |||
+ | > **Note:** Like other blocks, the block also needs a block model and an item model, and may also need a loot table, see [[blocks]] for how to create them. As for loot tables, [[blockentity_sync_itemstack|subsequent tutorials]] will cover how to improve the loot tables to include block entity data. | ||
- | ==== Connecting | + | ===== Connecting |
- | Once your '' | + | Once your '' |
<code java DemoBlock.java> | <code java DemoBlock.java> | ||
Line 72: | Line 96: | ||
return new DemoBlockEntity(pos, | return new DemoBlockEntity(pos, | ||
} | } | ||
- | } | ||
- | </ | ||
- | ===== Serializing Data ===== | ||
- | |||
- | If you want to store any data in your '' | ||
- | |||
- | '' | ||
- | |||
- | Knowing this, the example below demonstrates saving an integer from your '' | ||
- | |||
- | <code java DemoBlockEntity.java> | ||
- | public class DemoBlockEntity extends BlockEntity { | ||
- | |||
- | // Store the current value of the number | ||
- | private int number = 7; | ||
- | |||
- | public DemoBlockEntity(BlockPos pos, BlockState state) { | ||
- | super(ExampleMod.DEMO_BLOCK_ENTITY, | ||
- | } | ||
- | |||
- | // Serialize the BlockEntity | ||
@Override | @Override | ||
- | | + | |
- | | + | |
- | nbt.putInt(" | + | |
- | + | ||
- | super.writeNbt(nbt, | + | |
} | } | ||
} | } | ||
</ | </ | ||
- | In order to read the data, you will also need to override | + | Overriding |
- | + | ||
- | <code java> | + | |
- | // Deserialize the BlockEntity | + | |
- | @Override | + | |
- | public void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup wrapper) { | + | |
- | super.readNbt(nbt, | + | |
- | + | ||
- | number = nbt.getInt(" | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | Once you have implemented the '' | + | |
- | + | ||
- | ===== Sync data from server to client ===== | + | |
- | The data is read in the server world usually. Most data are not needed by the client, for example, your client does not need to know what's in the chest or furnace, until you open the GUI. But for some block entities, such as signs and banners, you have to inform the client of the data of the block entity, for example, for rendering. | + | |
- | + | ||
- | For version 1.17.1 and below, implement '' | + | |
- | + | ||
- | For version 1.18 and above, override '' | + | |
- | <code java> | + | |
- | @Nullable | + | |
- | @Override | + | |
- | public Packet< | + | |
- | return BlockEntityUpdateS2CPacket.create(this); | + | |
- | } | + | |
- | + | ||
- | @Override | + | |
- | public NbtCompound toInitialChunkDataNbt(RegistryWrapper.WrapperLookup registryLookup) { | + | |
- | return createNbt(registryLookup); | + | |
- | } | + | |
- | </ | + | |
- | **Warning**: | + | |
- | ===== Block Entity Ticking | + | ===== Block entity ticking |
Ticking means the block should run something on every tick (which is 1/20 second). For your block to tick, you would normally use '' | Ticking means the block should run something on every tick (which is 1/20 second). For your block to tick, you would normally use '' | ||
Line 155: | Line 123: | ||
And in your '' | And in your '' | ||
<code java DemoBlockEntity.java> | <code java DemoBlockEntity.java> | ||
- | public class DemoBlockEntity extends BlockEntity { | + | public class DemoBlockEntity extends BlockEntity |
[...] | [...] | ||
| | ||
Line 165: | Line 133: | ||
</ | </ | ||
- | ===== Overview | + | ===== Next steps ===== |
+ | |||
+ | You should now have your very own '' | ||
- | You should now have your very own '' | + | You also learned how to add ticking for it. Next step, you can try some other complex operations for the block entities, such as: |
+ | * [[blockentity_modify_data|Modifying block entity data]] | ||
+ | * [[inventory|Storing items in the block entity as an inventory]] | ||
+ | * [[blockentityrenderers|Using block entity renderers | ||
+ | * [[screenhandler|Creating a container block]] |
tutorial/blockentity.1724629854.txt.gz · Last modified: 2024/08/25 23:50 by solidblock