Block Components
Block Components
Section titled “Block Components”Block components store per-block instance data for blocks that need persistent state (e.g., chests with inventory, crafting benches with tier levels). They are standard ECS components registered on the ChunkStore.
Package Location
Section titled “Package Location”- Block components:
com.hypixel.hytale.server.core.modules.block.components - BlockModule:
com.hypixel.hytale.server.core.modules.block.BlockModule - BlockEntity:
com.hypixel.hytale.server.core.modules.block.BlockEntity - BlockReplaceEvent:
com.hypixel.hytale.server.core.modules.block.BlockReplaceEvent
Defining a Block Component
Section titled “Defining a Block Component”Block components implement Component<ChunkStore> and are registered via the chunk store registry.
import com.hypixel.hytale.codec.Codec;import com.hypixel.hytale.codec.KeyedCodec;import com.hypixel.hytale.codec.builder.BuilderCodec;import com.hypixel.hytale.component.Component;import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
public class CustomBlockComponent implements Component<ChunkStore> { public static final BuilderCodec<CustomBlockComponent> CODEC = BuilderCodec.builder(CustomBlockComponent.class, CustomBlockComponent::new) .append(new KeyedCodec<>("IsOpen", Codec.BOOLEAN), (c, v) -> c.isOpen = v, c -> c.isOpen) .add() .append(new KeyedCodec<>("Capacity", Codec.SHORT), (c, v) -> c.capacity = v, c -> c.capacity) .add() .build();
private boolean isOpen = false; private short capacity = 20;
public boolean isOpen() { return isOpen; } public void setOpen(boolean open) { this.isOpen = open; } public short getCapacity() { return capacity; }
@Override public Component<ChunkStore> clone() { CustomBlockComponent copy = new CustomBlockComponent(); copy.isOpen = this.isOpen; copy.capacity = this.capacity; return copy; }}Registering Block Components
Section titled “Registering Block Components”Register block components during plugin setup using the chunk store registry:
@Overrideprotected void setup() { ComponentType<ChunkStore, CustomBlockComponent> componentType = getChunkStoreRegistry().registerComponent( CustomBlockComponent.class, "myplugin:custom_block", CustomBlockComponent.CODEC );}Built-in Block Components
Section titled “Built-in Block Components”ItemContainerBlock
Section titled “ItemContainerBlock”Block component for blocks that contain item inventories (chests, containers). Replaces the former ItemContainerBlockState and ItemContainerState.
package com.hypixel.hytale.server.core.modules.block.components;
public class ItemContainerBlock implements Component<ChunkStore> { public static ComponentType<ChunkStore, ItemContainerBlock> getComponentType();
public SimpleItemContainer getItemContainer(); public short getCapacity(); @Nullable public String getDroplist(); public void setDroplist(@Nullable String droplist); public Map<UUID, ContainerBlockWindow> getWindows();
public static final BuilderCodec<ItemContainerBlock> CODEC;}Accessing Block Components
Section titled “Accessing Block Components”Use BlockModule.getComponent() to read block components from world positions:
ItemContainerBlock container = BlockModule.getComponent( ItemContainerBlock.getComponentType(), world, x, y, z);
if (container != null) { SimpleItemContainer items = container.getItemContainer();}You can also access block components via chunk store entity references:
BlockComponentChunk componentChunk = accessor.getComponent( chunkRef, BlockComponentChunk.getComponentType());
if (componentChunk != null) { int index = ChunkUtil.indexBlockInColumn(x, y, z); Ref<ChunkStore> entityRef = componentChunk.getEntityReference(index); if (entityRef != null) { ItemContainerBlock container = accessor.getComponent( entityRef, ItemContainerBlock.getComponentType() ); }}BlockEntity Utility
Section titled “BlockEntity Utility”BlockEntity provides a static utility method for setting block entities on chunks. It handles filler block replacement events, cross-chunk entity references, and BlockReplaceEvent dispatch.
BlockEntity.setBlockEntity( accessor, chunkRef, componentChunk, x, y, z, blockType, rotation, holder);Pass null for the holder to remove an existing block entity.
BlockReplaceEvent
Section titled “BlockReplaceEvent”BlockReplaceEvent is an ECS event dispatched when a block entity is being replaced. It provides the chunk reference, the position of the block being replaced, and the new entity holder.
public class BlockReplaceEvent extends EcsEvent { public Ref<ChunkStore> getChunkRef(); public int getSelfX(); public int getSelfY(); public int getSelfZ(); public Holder<ChunkStore> getNewEntity();}Migration from BlockState
Section titled “Migration from BlockState”| v3 (Removed) | v4 (Replacement) |
|---|---|
BlockState base class | Component<ChunkStore> |
BlockStateRegistry.registerBlockState(...) | getChunkStoreRegistry().registerComponent(...) |
BlockStateModule | BlockModule |
chunk.getState(x, y, z) | BlockModule.getComponent(type, world, x, y, z) |
BlockState.ensureState(chunk, x, y, z) | Use BlockEntity.setBlockEntity(...) |
ItemContainerBlockState | ItemContainerBlock |
TickableBlockState | EntityTickingSystem<ChunkStore> |
DestroyableBlockState | RefSystem<ChunkStore> with remove handling |
SendableBlockState | Custom packet logic in systems |
BlockState.markNeedsSave() | Handled automatically by the component system |
Best Practices
Section titled “Best Practices”- Use
Component<ChunkStore>: Implement the standard ECS component interface - Register with codec: Provide a
BuilderCodecfor persistence - Use systems for behavior: Lifecycle logic belongs in
RefSystem<ChunkStore>orEntityTickingSystem<ChunkStore>, not in the component - Handle replacement events: Listen for
BlockReplaceEventif your component needs to transfer data when blocks are replaced - Access via BlockModule: Use
BlockModule.getComponent(...)for positional lookups
Related
Section titled “Related”- Block Types - BlockType properties
- Block Events - Block event handling
- ECS Overview - Entity Component System
- Serialization - Data persistence