Skip to main content
Version: Minecraft 26.2

Blocks

Declaring a block​

BlockHandle block = mod.content().block("copper_bricks", BlockDefinition.builder()
.strength(2.0f, 6.0f)
.requiresCorrectTool()
.sound(BlockSound.COPPER)
.item(ItemDefinition.builder().creativeTab(CreativeTab.BUILDING_BLOCKS).build())
.build());
Builder methodMeaning
strength(hardness, explosionResistance)Hardness and explosion resistance
requiresCorrectTool()Drops only when mined with the right tool (tool tags come from a data pack or addToTag)
sound(BlockSound)STONE, WOOD, GRAVEL, GRASS, METAL, GLASS, WOOL, SAND, COPPER, AMETHYST
lightLevel(int) / lightLevel(state -> …)Light level, or a light level per state
friction(float)Slipperiness
noCollision(), noOcclusion()No collision; does not block light or view
behavior(BlockBehavior)Behavior callbacks
item(ItemDefinition) / noItem()Definition of the block item with the same ID / no block item
properties(...), facesPlayerWhenPlaced(...)State properties
randomTicks()Receive random ticks (onRandomTick)
blockEntity(BlockEntityDefinition)Block entity. See Block entities and menus

Pick the creative tab from CreativeTab: BUILDING_BLOCKS, COLORED_BLOCKS, NATURAL_BLOCKS, FUNCTIONAL_BLOCKS, REDSTONE_BLOCKS, TOOLS_AND_UTILITIES, COMBAT, FOOD_AND_DRINKS, INGREDIENTS, SPAWN_EGGS. The item is added at the end of the tab. A mod's own tab is described in Tags and creative tabs.

Behavior callbacks​

Every method of BlockBehavior has a default implementation, so override only what you need.

MethodCalled when
onUse(BlockUse use)A player uses the block (use.world(), use.pos(), use.player())
onSteppedOn(world, pos, entity)An entity steps on the block
onPlaced(world, pos, placer)The block is placed
onRandomTick(world, pos)Random tick (needs randomTicks())
onNeighborChanged(world, pos)A neighboring block changes

If onUse returns PASS, the game's default behavior applies.

Block state properties​

static final BlockProperty.DirectionProperty FACING = BlockProperty.horizontalFacing("facing");
static final BlockProperty.BooleanProperty POWERED = BlockProperty.bool("powered");

BlockDefinition.builder()
.facesPlayerWhenPlaced(FACING) // face the player when placed
.properties(POWERED)
.randomTicks() // BlockBehavior.onRandomTick
.build();

world.stateAt(pos).get(POWERED);
world.setProperty(pos, POWERED, true);
  • Property kinds: bool, integer(min, max), horizontalFacing, direction, choice(name, values...). Change the default with withDefault(...).
  • Default state: The default values of the properties form the default state.
  • Blockstate file: Pick models in the vanilla format, such as "facing=north,powered=false".
  • Reading vanilla blocks: You can also read the state of a game block when the property has the same name and type (for example facing on a furnace). Check first with stateAt(pos).has(property).
  • Trying to change a property the block does not have throws IllegalArgumentException.

Named properties​

static final BlockProperty.ChoiceProperty COLOR = BlockProperty.choice("color", "red", "green", "blue"); // the first value is the default
  • In a blockstate file, write it as color=blue.
  • Game properties with the same name (half on stairs, axis on logs, and so on) can also be read and changed as strings.
  • A value that is not allowed throws IllegalArgumentException.

Per-state light​

static final BlockProperty.BooleanProperty LIT = BlockProperty.bool("lit");

mod.content().block("lamp", BlockDefinition.builder()
.properties(COLOR, LIT)
.lightLevel(state -> state.get(LIT) ? 15 : 0) // light level per state
.behavior(new BlockBehavior() {
@Override
public InteractionResult onUse(BlockUse use) {
if (!use.world().isClientSide()) {
use.world().setProperty(use.pos(), LIT, true);
}
return InteractionResult.SUCCESS;
}
})
.build());

lightLevel(state -> …) is computed once per state when the block is created. Check it with WorldView.emittedLight(pos). There is no separate light provider API.

Shape and collision​

For blocks that are not a full cube, such as slabs, posts, and pipes, give the outline with shape. The unit is pixels, and one block spans 0..16 on each axis. This matches from/to of block model elements.

// Half-height: entities stand at y + 0.5, and the outline is half a block too
mod.content().block("stone_step", BlockDefinition.builder()
.shape(BlockShape.box(0, 0, 0, 16, 8, 16))
.build());

// A base and a post, plus a handle rotated to the facing direction
static final BlockProperty.DirectionProperty FACING = BlockProperty.horizontalFacing("facing");
static final BlockShape HANDLE = BlockShape.box(6, 10, 0, 10, 12, 4); // shape when facing north

mod.content().block("lever_post", BlockDefinition.builder()
.properties(FACING)
.facesPlayerWhenPlaced(FACING)
.shape(state -> BlockShape.box(0, 0, 0, 16, 2, 16)
.or(BlockShape.box(6, 2, 6, 10, 16, 10))
.or(HANDLE.facing(state.get(FACING))))
.collisionShape(BlockShape.box(0, 0, 0, 16, 2, 16).or(BlockShape.box(6, 2, 6, 10, 16, 10)))
.build());
MethodMeaning
shape(BlockShape), shape(state -> …)The outline the player aims at, which is also the collision shape
collisionShape(…)When only the collision differs
BlockShape.box(…), or(…)One box; combine shapes
BlockShape.facing(direction)Rotates a north-facing shape to that direction
BlockShape.FULL, BlockShape.EMPTYA full block; no shape
  • The game computes the per-state shape once per state at startup. If the function throws or returns null, the result is POLY-CONTENT-006.
  • The game hides only the neighboring faces that the shape covers. The block model does not change, so draw the model to match the shape. For a slab, use "parent": "minecraft:block/slab".
  • With noCollision(), the block does not collide regardless of collisionShape.

Blockstate file example​

assets/my_mod/blockstates/lamp.json
{
"variants": {
"lit=false": {"model": "my_mod:block/lamp_off"},
"lit=true": {"model": "my_mod:block/lamp_on"}
}
}
Block state IDs

The states of mod blocks also go into the game's block state ID table. That is why changes to mod blocks can be sent to the client (this fixed a disconnect problem in early versions).

Buy me a coffee