Skip to content

Block System Overview

The Block System manages all block types, block states, and block-related operations in Hytale. Blocks are the fundamental building units of the world.

  • BlockType: com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType
  • BlockState: com.hypixel.hytale.server.core.universe.world.meta.BlockState (deprecated)
  • BlockStateRegistry: com.hypixel.hytale.server.core.universe.world.meta.BlockStateRegistry
  • TickProcedure: com.hypixel.hytale.server.core.asset.type.blocktick.config.TickProcedure
ComponentDescription
BlockTypeAsset definition for block behavior and appearance
BlockStatePer-block instance data for stateful blocks
BlockStateRegistryRegistration of custom block state types
TickProcedureBlock tick behavior (growth, decay, etc.)

BlockType is an asset that defines a block’s properties and behavior. It’s loaded from JSON files in the blocktype/ directory.

{
"Id": "MyPlugin_CustomBlock",
"Group": "MyBlocks",
"DrawType": "Cube",
"Material": "Stone",
"Opacity": "Solid",
"Textures": [
{
"Up": "textures/block_top.png",
"Down": "textures/block_bottom.png",
"North": "textures/block_side.png",
"South": "textures/block_side.png",
"East": "textures/block_side.png",
"West": "textures/block_side.png"
}
],
"HitboxType": "Full",
"BlockSoundSetId": "Hytale/Stone"
}
PropertyTypeDescription
DrawTypeDrawTypeHow the block is rendered (Cube, Model, Empty)
TexturesBlockTypeTextures[]Textures for each face
CustomModelstringPath to custom 3D model
CustomModelTexturearrayTextures for custom model
CustomModelScalefloatScale factor for model (default: 1.0)
CustomModelAnimationstringAnimation for model
OpacityOpacityLight blocking (Solid, Transparent, SemiTransparent)
RequiresAlphaBlendingboolEnable alpha blending
CubeShadingModeShadingModeShading style (Standard, etc.)
EffectShaderType[]Shader effects
PropertyTypeDescription
MaterialBlockMaterialPhysical material type
HitboxTypestringCollision hitbox type (Full, etc.)
InteractionHitboxTypestringHitbox for interactions
MovementSettingsobjectMovement modifiers on block
PropertyTypeDescription
LightColorLightEmitted light color and intensity
TintColor[]Color tint per face
TintUp/Down/North/South/East/WestColor[]Per-face tints
BiomeTintintBiome color application
ParticleColorColorParticle tint
ParticlesModelParticle[]Block-attached particles
BlockParticleSetIdstringParticle set for interactions
PropertyTypeDescription
BlockSoundSetIdstringSound set for block events
AmbientSoundEventIdstringLooping ambient sound
InteractionSoundEventIdstringSound on interaction
LoopingboolWhether ambient sound loops
PropertyTypeDescription
RandomRotationRandomRotationRandom rotation on placement
VariantRotationVariantRotationVariant-based rotation
FlipTypeBlockFlipTypeFlip behavior
RotationYawPlacementOffsetRotationYaw offset when placed
PropertyTypeDescription
SupportmapRequired support per face
SupportingmapSupport provided to neighbors
SupportDropTypeSupportDropTypeWhat happens when support lost
MaxSupportDistanceintMaximum support reach (0-14)
SupportsRequiredForenumWhen support is checked
IgnoreSupportWhenPlacedboolBypass support on placement
PropertyTypeDescription
Flags.IsUsableboolCan be used/interacted with
Flags.IsStackableboolCan be stacked on top
InteractionsmapInteraction handlers
BenchobjectCrafting bench configuration
GatheringobjectResource gathering settings
PlacementSettingsobjectPlacement restrictions
SeatsarraySeating mount points
BedsarrayBed mount points
IsDoorboolDoor behavior (deprecated)
DamageToEntitiesintContact damage
PropertyTypeDescription
StateStateDataBlock state configuration
BlockEntityHolderECS components for block entity
TickProcedureobjectBlock tick behavior
ValueDescription
EmptyInvisible, no rendering
CubeStandard cube block
ModelCustom 3D model

Common materials:

ValueDescription
EmptyNo physical material
SolidGeneric solid
StoneStone-like
WoodWood-like
MetalMetallic
GlassGlass-like
OrganicPlants, grass
ClothFabric
LiquidWater, lava
// Get by ID
BlockType stone = BlockType.getAssetMap().get("Rock_Stone");
// Get from world position
World world = Universe.get().getDefaultWorld();
BlockType type = world.getBlockType(x, y, z);
// Get block ID (numeric)
int blockId = world.getBlock(x, y, z);
// Check special blocks
BlockType.EMPTY // Air block
BlockType.UNKNOWN // Unknown block placeholder
// Simple set
world.setBlock(x, y, z, blockType);
// With settings
SetBlockSettings settings = new SetBlockSettings();
settings.setNotifyNeighbors(true);
settings.setUpdateLighting(true);
settings.setTriggerBlockUpdate(true);
world.setBlock(x, y, z, blockType, settings);

Block states store per-block instance data for blocks that need persistent state.

Note: The BlockState class is marked as @Deprecated(forRemoval = true). It may be replaced with a new ECS-based block entity system in future versions.

// BlockState is a component for the ChunkStore
public abstract class BlockState implements Component<ChunkStore> {
// Position within chunk
public Vector3i getPosition();
public Vector3i getBlockPosition(); // World coordinates
// Access chunk and block type
public WorldChunk getChunk();
public BlockType getBlockType();
// Rotation
public int getRotationIndex();
// Lifecycle
public boolean initialize(BlockType blockType);
public void onUnload();
public void invalidate();
// Persistence
public void markNeedsSave();
public BsonDocument saveToDocument();
}
@Override
protected void setup() {
// Register a block state type
getBlockStateRegistry().registerBlockState(
MyBlockState.class,
"MyPlugin_CustomState",
MyBlockState.CODEC
);
// With associated data class
getBlockStateRegistry().registerBlockState(
MyBlockState.class,
"MyPlugin_CustomState",
MyBlockState.CODEC,
MyStateData.class,
MyStateData.CODEC
);
}
public class ChestBlockState extends BlockState {
public static final BuilderCodec<ChestBlockState> CODEC =
BuilderCodec.builder(ChestBlockState.class, ChestBlockState::new)
.inherit(BlockState.BASE_CODEC)
.addField(
new KeyedCodec<>("IsOpen", Codec.BOOLEAN),
(state, open) -> state.isOpen = open,
state -> state.isOpen
)
.build();
private boolean isOpen = false;
private ItemContainer inventory;
@Override
public boolean initialize(BlockType blockType) {
this.inventory = new SimpleItemContainer((short) 27);
return true;
}
public void toggle() {
this.isOpen = !this.isOpen;
markNeedsSave();
}
public ItemContainer getInventory() {
return inventory;
}
}
// Get state from chunk
WorldChunk chunk = world.getChunk(chunkX, chunkZ);
BlockState state = chunk.getState(localX, y, localZ);
// Ensure state exists (creates if needed)
BlockState state = BlockState.ensureState(chunk, x, y, z);
// Cast to specific type
if (state instanceof ChestBlockState chestState) {
chestState.toggle();
}

Blocks can have tick procedures for time-based behavior like growth or decay.

public abstract class TickProcedure {
// Called when block should tick
public abstract BlockTickStrategy onTick(
World world,
WorldChunk chunk,
int x, int y, int z,
int blockId
);
}

Return value indicating what happened:

StrategyDescription
NONENo change
CHANGEDBlock was modified
REMOVEDBlock was removed
// Basic chance-based growth
public class BasicChanceBlockGrowthProcedure extends TickProcedure {
// Grows block to next stage with configurable chance
}
// Split chance growth (different chances per stage)
public class SplitChanceBlockGrowthProcedure extends TickProcedure {
// Different growth chances for each stage
}
{
"Id": "MyPlugin_GrowingPlant",
"TickProcedure": {
"Type": "BasicChanceBlockGrowthProcedure",
"GrowChance": 0.1,
"GrowToBlock": "MyPlugin_MaturePlant"
}
}

Blocks can require and provide support to neighboring blocks.

{
"Support": {
"Down": [{ "Type": "Full" }]
},
"Supporting": {
"Up": [{ "Type": "Full" }],
"North": [{ "Type": "Full" }],
"South": [{ "Type": "Full" }],
"East": [{ "Type": "Full" }],
"West": [{ "Type": "Full" }]
},
"SupportDropType": "BREAK"
}
TypeDescription
BREAKBlock breaks when support lost
DROPBlock drops as item
NONEBlock stays (no physics)

Blocks can connect to neighbors for visual continuity (fences, glass panes, etc.).

{
"ConnectedBlockRuleSet": {
"Rules": [
{
"Condition": { "Type": "SameBlock" },
"Connect": true
}
]
}
}

Define interactions in the block type:

{
"Interactions": {
"Primary": "MyPlugin_PrimaryInteraction",
"Secondary": "MyPlugin_SecondaryInteraction"
},
"InteractionHint": "ui.interaction.open"
}
getEventRegistry().register(BreakBlockEvent.class, event -> {
BlockType blockType = event.getBlockType();
Vector3i position = event.getPosition();
PlayerRef player = event.getPlayerRef();
// Cancel to prevent breaking
event.setCancelled(true);
});
getEventRegistry().register(PlaceBlockEvent.class, event -> {
BlockType blockType = event.getBlockType();
// Handle placement
});
getEventRegistry().register(UseBlockEvent.class, event -> {
BlockType blockType = event.getBlockType();
// Handle interaction
});
  1. Use groups: Organize related blocks with the Group property
  2. Minimize states: Only use block states when truly needed
  3. Optimize hitboxes: Use appropriate hitbox complexity
  4. Consider support: Define support requirements for physics
  5. Batch updates: Group block changes when possible
  6. Check loaded: Verify chunks are loaded before block access