9.5 KiB
title, type, weight
| title | type | weight |
|---|---|---|
| Blocks | docs | 3 |
Block manipulation is a core part of world modification in Hytale plugins. The World class provides block access through the IChunkAccessorSync interface, while WorldChunk implements the full BlockAccessor interface for rotation-aware placement.
{{< callout type="warning" >}}
Important: World does NOT implement BlockAccessor directly. For placeBlock() with rotation, you must get the chunk first using world.getChunk().
{{< /callout >}}
Getting Blocks
import com.hypixel.hytale.server.core.universe.Universe;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import com.hypixel.hytale.math.vector.Vector3i;
World world = Universe.get().getWorld("default");
// Get block ID (int index) at position
int blockId = world.getBlock(x, y, z);
int blockId = world.getBlock(new Vector3i(x, y, z));
// Get BlockType at position
BlockType blockType = world.getBlockType(x, y, z);
BlockType blockType = world.getBlockType(new Vector3i(x, y, z));
// Check if block is empty
if (blockType == BlockType.EMPTY) {
// Air or empty space
}
Setting Blocks
The setBlock method takes a String block type key, not a BlockType object or int ID:
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
World world = player.getWorld();
// Set block by block type key (string ID)
world.setBlock(x, y, z, "stone");
world.setBlock(x, y, z, "oak_planks", 0); // with settings
// Using BlockType - get the ID string first
BlockType stone = BlockType.getAssetMap().getAsset("stone");
if (stone != null) {
world.setBlock(x, y, z, stone.getId()); // Use getId() to get the string key
}
// Block ID index (for internal use)
int stoneIndex = BlockType.getAssetMap().getIndex("stone");
// Note: setBlock takes String, not int - use the key directly
Block Placement with Rotation
{{< callout type="info" >}} placeBlock() is on WorldChunk, not World! You must get the chunk first to place blocks with rotation. {{< /callout >}}
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.Rotation;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.RotationTuple;
import com.hypixel.hytale.math.util.ChunkUtil;
// Get the chunk containing this block position
WorldChunk chunk = world.getChunk(ChunkUtil.indexChunkFromBlock(x, z));
if (chunk != null) {
// Place block with rotation
// Rotation values: None, Ninety, OneEighty, TwoSeventy
chunk.placeBlock(x, y, z, "oak_log",
Rotation.Ninety, // yaw (90 degrees)
Rotation.None, // pitch
Rotation.None // roll
);
// Place with rotation tuple and options
chunk.placeBlock(x, y, z, "oak_log",
RotationTuple.of(Rotation.Ninety, Rotation.None, Rotation.None),
0, // settings
true // validatePlacement
);
}
Rotation Values
The Rotation enum has these values (NOT cardinal directions):
| Rotation | Degrees |
|---|---|
Rotation.None |
0° |
Rotation.Ninety |
90° |
Rotation.OneEighty |
180° |
Rotation.TwoSeventy |
270° |
Breaking Blocks
// Break block at position (requires settings parameter)
world.breakBlock(x, y, z, 0); // 0 = default settings
BlockType Assets
BlockType assets define block properties:
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import com.hypixel.hytale.protocol.BlockMaterial;
// Get block type by ID
BlockType blockType = BlockType.getAssetMap().getAsset("stone");
if (blockType != null) {
// Get block ID string
String blockId = blockType.getId();
// Get material
BlockMaterial material = blockType.getMaterial();
}
// Get block ID index (for internal use)
int blockIndex = BlockType.getAssetMap().getIndex("stone");
// Get block from index
BlockType fromIndex = BlockType.getAssetMap().getAsset(blockIndex);
Block Events
BreakBlockEvent
Fired when a block is broken:
import com.hypixel.hytale.server.core.event.events.ecs.BreakBlockEvent;
import com.hypixel.hytale.math.vector.Vector3i;
import java.util.logging.Level;
getEventRegistry().register(BreakBlockEvent.class, event -> {
// Get break info
Vector3i position = event.getTargetBlock();
BlockType blockType = event.getBlockType();
getLogger().at(Level.INFO).log("Block broken at " + position);
// Cancel if protected
event.setCancelled(true);
});
PlaceBlockEvent
Fired when a block is placed:
import com.hypixel.hytale.server.core.event.events.ecs.PlaceBlockEvent;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.RotationTuple;
getEventRegistry().register(PlaceBlockEvent.class, event -> {
// Get place info
Vector3i position = event.getTargetBlock();
RotationTuple rotation = event.getRotation();
getLogger().at(Level.INFO).log("Block placed at " + position);
// Cancel if not allowed
event.setCancelled(true);
});
DamageBlockEvent
Fired when a block is damaged (before breaking):
import com.hypixel.hytale.server.core.event.events.ecs.DamageBlockEvent;
getEventRegistry().register(DamageBlockEvent.class, event -> {
Vector3i position = event.getTargetBlock();
BlockType blockType = event.getBlockType();
// Cancel to prevent damage
event.setCancelled(true);
});
Block Interaction State
Blocks can have interaction states (like open/closed doors):
BlockType currentBlock = world.getBlockType(x, y, z);
if (currentBlock != null) {
// Set block to a different state
world.setBlockInteractionState(
new Vector3i(x, y, z),
currentBlock,
"open" // state name
);
}
Working with Blocks
Check Area for Block Type
public boolean containsBlockType(World world, Vector3i min, Vector3i max, String blockTypeKey) {
// Note: Vector3i uses getX(), getY(), getZ() - NOT x(), y(), z()
for (int x = min.getX(); x <= max.getX(); x++) {
for (int y = min.getY(); y <= max.getY(); y++) {
for (int z = min.getZ(); z <= max.getZ(); z++) {
BlockType block = world.getBlockType(x, y, z);
if (block != null && block.getId().equals(blockTypeKey)) {
return true;
}
}
}
}
return false;
}
Fill Area
public void fillArea(World world, Vector3i min, Vector3i max, String blockTypeKey) {
for (int x = min.getX(); x <= max.getX(); x++) {
for (int y = min.getY(); y <= max.getY(); y++) {
for (int z = min.getZ(); z <= max.getZ(); z++) {
world.setBlock(x, y, z, blockTypeKey);
}
}
}
}
Replace Blocks
public void replaceBlocks(World world, Vector3i min, Vector3i max,
String fromBlock, String toBlock) {
for (int x = min.getX(); x <= max.getX(); x++) {
for (int y = min.getY(); y <= max.getY(); y++) {
for (int z = min.getZ(); z <= max.getZ(); z++) {
BlockType current = world.getBlockType(x, y, z);
if (current != null && current.getId().equals(fromBlock)) {
world.setBlock(x, y, z, toBlock);
}
}
}
}
}
Block Positions
import com.hypixel.hytale.math.vector.Vector3i;
// Vector3i for integer block positions
Vector3i blockPos = new Vector3i(100, 64, 200);
// Get individual coordinates - use getX(), getY(), getZ()
int x = blockPos.getX();
int y = blockPos.getY();
int z = blockPos.getZ();
// Adjacent positions
Vector3i above = new Vector3i(x, y + 1, z);
Vector3i below = new Vector3i(x, y - 1, z);
Vector3i north = new Vector3i(x, y, z - 1);
Vector3i south = new Vector3i(x, y, z + 1);
Vector3i east = new Vector3i(x + 1, y, z);
Vector3i west = new Vector3i(x - 1, y, z);
Best Practices
{{< callout type="info" >}} Block Manipulation Tips:
- Block operations must run on the world's ticking thread
- Use
getBlockType()for checking block types,getBlock()for raw IDs - Check
BlockType.EMPTYfor air/empty blocks - Events extend
CancellableEcsEvent- usesetCancelled(true)to prevent - Consider chunk boundaries when processing large areas
- For
placeBlock()with rotation, get the chunk first {{< /callout >}}
// Safe block modification from async context
world.execute(() -> {
world.setBlock(x, y, z, "stone");
});
API Reference
World (IChunkAccessorSync) Methods
| Method | Returns | Description |
|---|---|---|
getBlock(int, int, int) |
int |
Get block ID at position |
getBlock(Vector3i) |
int |
Get block ID at position |
getBlockType(int, int, int) |
BlockType? |
Get BlockType at position |
getBlockType(Vector3i) |
BlockType? |
Get BlockType at position |
setBlock(x, y, z, String) |
void |
Set block by type key |
setBlock(x, y, z, String, int) |
void |
Set block with settings |
breakBlock(x, y, z, int) |
boolean |
Break block with settings |
setBlockInteractionState(...) |
void |
Set block state |
WorldChunk (BlockAccessor) Methods
| Method | Returns | Description |
|---|---|---|
placeBlock(x, y, z, String, Rotation, Rotation, Rotation) |
boolean |
Place with rotation |
placeBlock(x, y, z, String, RotationTuple, int, boolean) |
boolean |
Place with options |
testPlaceBlock(...) |
boolean |
Test if placement valid |