Skip to main content

Overview

Blocks are the building blocks of the Minecraft world. Minestom provides a powerful API for manipulating blocks, registering custom handlers, and controlling placement rules.

Block Class

Immutable representation of a block with properties, NBT data, and optional handler.

Getting Blocks

fromKey(String)
static Block
Gets a block by its namespaced key.Parameters:
  • key - The block key (e.g., “minecraft:stone”)
Returns: The Block, or null if not found
Block stone = Block.fromKey("minecraft:stone");
Block oakPlanks = Block.fromKey("minecraft:oak_planks");
fromState(String)
static Block
Parses a block from a state string.Parameters:
  • state - Block state string (e.g., “minecraft:oak_stairs[facing=north,half=top]”)
Returns: The Block with properties, or null if invalid
Block stairs = Block.fromState("minecraft:oak_stairs[facing=north,half=top]");
fromStateId(int)
static Block
Gets a block from its state ID.Parameters:
  • stateId - The block state ID
Returns: The Block, or null if invalid
fromBlockId(int)
static Block
Gets a block from its base ID.Parameters:
  • blockId - The block ID
Returns: The default block state, or null
values()
static Collection<Block>
Gets all registered blocks.Returns: Collection of all blocks
for (Block block : Block.values()) {
    System.out.println(block.key());
}

Block Properties

withProperty(String, String)
Block
Creates a new block with a property changed.Parameters:
  • property - Property name
  • value - Property value
Returns: New Block with the property setThrows: IllegalArgumentException if property or value is invalid
Block stairs = Block.OAK_STAIRS
    .withProperty("facing", "north")
    .withProperty("half", "top");
withProperties(Map<String, String>)
Block
Changes multiple properties at once.Parameters:
  • properties - Map of property names to values
Returns: New Block with properties changed
Map<String, String> props = Map.of(
    "facing", "north",
    "half", "top"
);
Block stairs = Block.OAK_STAIRS.withProperties(props);
getProperty(String)
String
Gets a property value.Parameters:
  • property - Property name
Returns: Property value, or null if not present
Block door = Block.OAK_DOOR.withProperty("open", "true");
String isOpen = door.getProperty("open"); // "true"
properties()
Map<String, String>
Gets all properties.Returns: Unmodifiable map of properties
Map<String, String> props = block.properties();
possibleStates()
Collection<Block>
Gets all possible states for this block type.Returns: Collection of block states
defaultState()
Block
Gets the default state with no properties or handlers.Returns: The default Block

NBT Data

withNbt(CompoundBinaryTag)
Block
Creates a new block with NBT data.Parameters:
  • compound - The NBT compound (null to remove)
Returns: New Block with NBT
CompoundBinaryTag nbt = CompoundBinaryTag.builder()
    .putString("CustomName", "My Chest")
    .build();
Block chest = Block.CHEST.withNbt(nbt);
withTag(Tag<T>, T)
Block
Creates a block with a tag modified.Parameters:
  • tag - The tag to modify
  • value - The tag value (null to remove)
Returns: New Block with tag changed
nbt()
CompoundBinaryTag
Gets the block NBT data.Returns: The NBT compound, or null if none
hasNbt()
boolean
Checks if the block has NBT data.Returns: true if NBT is present

Block Handlers

withHandler(BlockHandler)
Block
Creates a block with a handler attached.Parameters:
  • handler - The block handler (null to remove)
Returns: New Block with handler
Block customBlock = Block.STONE.withHandler(new MyBlockHandler());
instance.setBlock(pos, customBlock);
handler()
BlockHandler
Gets the block handler.Returns: The BlockHandler, or null if not present

Block Information

key()
Key
Gets the block namespaced key.Returns: The Key (e.g., “minecraft:stone”)
id()
int
Gets the block ID.Returns: The block ID
stateId()
int
Gets the state ID (unique for each property combination).Returns: The state ID
state()
String
Gets the block state as a string.Returns: State string (e.g., “minecraft:oak_stairs[facing=north]”)
String state = block.state();
Block restored = Block.fromState(state);
isAir()
boolean
Checks if the block is air.Returns: true if air
isSolid()
boolean
Checks if the block is solid.Returns: true if solid
isLiquid()
boolean
Checks if the block is a liquid.Returns: true if liquid
compare(Block, Comparator)
boolean
Compares two blocks.Parameters:
  • block - Block to compare to
  • comparator - Comparison mode (IDENTITY, ID, STATE)
Returns: true if blocks match according to comparator
// Compare by ID (ignores properties)
if (block.compare(Block.STONE, Block.Comparator.ID)) {
    // Same block type
}

// Compare by state (exact match including properties)
if (block.compare(otherBlock, Block.Comparator.STATE)) {
    // Exact same block
}
registry()
RegistryData.BlockEntry
Gets the block registry data.Returns: The registry entry with collision shape, etc.

BlockManager

Manages block handlers and placement rules.

Handler Registration

registerHandler(String, Supplier<BlockHandler>)
void
Registers a block handler by namespace.Parameters:
  • namespace - The block namespace (e.g., “custom:my_block”)
  • handlerSupplier - Supplier that creates handler instances
BlockManager blockManager = MinecraftServer.getBlockManager();
blockManager.registerHandler("custom:teleporter", () -> new TeleporterHandler());
registerHandler(Key, Supplier<BlockHandler>)
void
Registers a handler using a Key.Parameters:
  • key - The block key
  • handlerSupplier - Handler supplier
getHandler(String)
BlockHandler
Gets a handler by namespace.Parameters:
  • namespace - The block namespace
Returns: The BlockHandler, or null if not registered

Placement Rules

registerBlockPlacementRule(BlockPlacementRule)
void
Registers a placement rule for a block.Parameters:
  • blockPlacementRule - The placement rule
Throws: IllegalArgumentException if block ID is negative
BlockPlacementRule rule = new BlockPlacementRule(Block.TORCH);
rule.setPlacementCondition((instance, block, pos) -> {
    // Can only place on solid blocks
    Block below = instance.getBlock(pos.sub(0, 1, 0));
    return below.isSolid();
});
blockManager.registerBlockPlacementRule(rule);
getBlockPlacementRule(Block)
BlockPlacementRule
Gets the placement rule for a block.Parameters:
  • block - The block
Returns: The placement rule, or null if not registered

BlockHandler Interface

Defines custom behavior for blocks. All methods are optional.

Lifecycle Events

onPlace(Placement)
void
Called when the block is placed.Parameters:
  • placement - Details about the placement
@Override
public void onPlace(Placement placement) {
    System.out.println("Block placed at: " + placement.getBlockPosition());
}
onDestroy(Destroy)
void
Called when the block is destroyed or replaced.Parameters:
  • destroy - Details about the destruction
@Override
public void onDestroy(Destroy destroy) {
    // Drop custom items, save data, etc.
}

Interaction

onInteract(Interaction)
boolean
Handles player interaction with the block.Parameters:
  • interaction - Interaction details
Returns: true to allow interaction, false to cancel
@Override
public boolean onInteract(Interaction interaction) {
    Player player = interaction.getPlayer();
    player.sendMessage(Component.text("You clicked the block!"));
    return true;
}
onTouch(Touch)
void
Called when an entity touches the block.Parameters:
  • touch - Touch details
@Override
public void onTouch(Touch touch) {
    Entity entity = touch.getEntity();
    if (entity instanceof Player player) {
        player.setVelocity(new Vec(0, 10, 0)); // Launch player
    }
}

Ticking

tick(Tick)
void
Called every tick if isTickable() returns true.Parameters:
  • tick - Tick details
@Override
public void tick(Tick tick) {
    // Update block state, particles, etc.
}
isTickable()
boolean
Determines if this handler should receive tick updates.Returns: true to receive ticks
@Override
public boolean isTickable() {
    return true; // This block needs ticking
}

Block Entity

getKey()
Key
Gets the handler key (required for block entities).Returns: The handler namespace key
@Override
public Key getKey() {
    return Key.key("custom:my_block");
}
getBlockEntityTags()
Collection<Tag<?>>
Specifies which tags should be sent to clients.Returns: Collection of tags to sync

Block.Getter Interface

Interface for retrieving blocks (implemented by Instance).
getBlock(int, int, int)
Block
Gets a block at coordinates.Parameters:
  • x, y, z - Block coordinates
Returns: The Block
getBlock(Point)
Block
Gets a block at a point.Parameters:
  • point - The position
Returns: The Block
getBlock(int, int, int, Condition)
Block
Gets a block with a retrieval hint.Parameters:
  • x, y, z - Coordinates
  • condition - Retrieval condition (NONE, CACHED, TYPE)
Returns: The Block (may be null for CACHED)
// Only get if cached (fast, may return null)
Block cached = instance.getBlock(x, y, z, Block.Getter.Condition.CACHED);

// Only care about block type (may not have correct NBT/handler)
Block type = instance.getBlock(x, y, z, Block.Getter.Condition.TYPE);

Block.Setter Interface

Interface for placing blocks (implemented by Instance, Batch).
setBlock(int, int, int, Block)
void
Sets a block at coordinates.Parameters:
  • x, y, z - Block coordinates
  • block - The block to place
setBlock(Point, Block)
void
Sets a block at a point.Parameters:
  • blockPosition - The position
  • block - The block to place

Examples

public class TeleporterHandler implements BlockHandler {
    private final Pos destination;
    
    public TeleporterHandler(Pos destination) {
        this.destination = destination;
    }
    
    @Override
    public void onTouch(Touch touch) {
        Entity entity = touch.getEntity();
        if (entity instanceof Player player) {
            player.teleport(destination);
            player.sendMessage(
                Component.text("Teleported!").color(NamedTextColor.GREEN)
            );
        }
    }
    
    @Override
    public Key getKey() {
        return Key.key("custom:teleporter");
    }
}

// Register and use
BlockManager manager = MinecraftServer.getBlockManager();
manager.registerHandler("custom:teleporter", 
    () -> new TeleporterHandler(new Pos(100, 64, 100)));

Block teleporter = Block.DIAMOND_BLOCK.withHandler(
    new TeleporterHandler(new Pos(100, 64, 100))
);
instance.setBlock(0, 64, 0, teleporter);
Blocks are immutable. Methods like withProperty() and withNbt() return new Block instances rather than modifying the existing one.
Block handlers must be thread-safe as they can be called from multiple threads simultaneously.

Build docs developers (and LLMs) love