Skip to main content

Custom Blocks

Beyond basic blocks, Voxelize supports advanced block configurations including rotations, transparency, custom shapes, and dynamic behaviors.

Block Properties

Basic Properties

Block Properties
let block = Block::new("My Block")
.id(100)
.is_solid(true) // Collision enabled
.is_transparent(false) // Renders back faces
.is_passable(false) // Entities can't walk through
.is_fluid(false) // Water-like behavior
.is_light(false) // Emits light
.light_level(0) // Light emission level (0-15)
.build();

Transparency

For transparent blocks like glass:

Transparent Block
let glass = Block::new("Glass")
.id(10)
.is_transparent(true)
.is_see_through(true) // Can see through for lighting
.build();

Light-Emitting Blocks

Light Source
let torch = Block::new("Torch")
.id(20)
.is_light(true)
.light_level(14) // Max is 15
.is_transparent(true)
.is_solid(false)
.build();

Block Rotation

Y-Axis Rotation

Blocks can rotate on the Y axis:

Y-Rotatable Block
let furnace = Block::new("Furnace")
.id(30)
.rotatable(true)
.y_rotatable(true)
.build();

6-Face Rotation

Blocks that can face any direction:

6-Face Rotation
let piston = Block::new("Piston")
.id(31)
.rotatable(true)
.y_rotatable(true)
.build();

Custom Shapes

AABB Shapes

Define custom collision boxes:

Custom AABB
let slab = Block::new("Stone Slab")
.id(40)
.aabbs(&[AABB::new()
.scale_y(0.5)
.build()])
.build();

Multiple AABBs

Multiple AABBs
let stairs = Block::new("Stairs")
.id(41)
.aabbs(&[
AABB::new().scale_y(0.5).build(),
AABB::new()
.scale_x(0.5)
.scale_y(0.5)
.offset_y(0.5)
.build(),
])
.build();

Block Texturing

Server-Side Texture Names

Block Faces
let log = Block::new("Oak Log")
.id(50)
.faces(&[
Face::new("py").build(), // Top
Face::new("ny").build(), // Bottom
Face::new("px").build(), // +X side
Face::new("nx").build(), // -X side
Face::new("pz").build(), // +Z side
Face::new("nz").build(), // -Z side
])
.build();

Client-Side Texturing

Applying Textures
await world.applyBlockTexture("Oak Log", "py", "/textures/log_top.png");
await world.applyBlockTexture("Oak Log", "ny", "/textures/log_top.png");
await world.applyBlockTexture(
"Oak Log",
["px", "nx", "pz", "nz"],
"/textures/log_side.png"
);

Block Entities

Blocks can have associated entities for complex data:

Block Entity
let sign = Block::new("Sign")
.id(60)
.is_entity(true) // Creates entity when placed
.is_solid(false)
.build();

The entity stores JSON data:

Block Entity Data
method.call("vox-builtin:update-block-entity", {
id: entityId,
json: JSON.stringify({ text: "Hello World" }),
});

Dynamic Blocks

Active Blocks

Blocks that update each tick:

Active Block
let redstone = Block::new("Redstone Wire")
.id(70)
.is_active(true)
.active_fn(|world, vx, vy, vz| {
// Called each tick for this block
// Return updates to apply
vec![]
})
.build();

Client-Side Customization

Custom Shaders

Custom Block Shader
world.customizeMaterialShaders(
"Grass",
null,
VOXELIZE.customShaders.sway({ rooted: true })
);

world.customizeMaterialShaders("Water", VOXELIZE.customShaders.water(), null);

Dynamic Textures

Dynamic Texture
const canvas = document.createElement("canvas");
canvas.width = 16;
canvas.height = 16;
const ctx = canvas.getContext("2d")!;

function updateTexture() {
ctx.fillStyle = `hsl(${(Date.now() / 10) % 360}, 100%, 50%)`;
ctx.fillRect(0, 0, 16, 16);

world.applyBlockTextureByIdAt(blockId, "all", canvas, voxelPosition);
}

Example: Slab Variants

Slab Registration
fn register_slabs(registry: &mut Registry, base_id: u32, name: &str) {
let bottom_slab = Block::new(&format!("{} Slab Bottom", name))
.id(base_id)
.aabbs(&[AABB::new().scale_y(0.5).build()])
.build();

let top_slab = Block::new(&format!("{} Slab Top", name))
.id(base_id + 1)
.aabbs(&[AABB::new().scale_y(0.5).offset_y(0.5).build()])
.build();

registry.register_blocks(&[bottom_slab, top_slab]);
}

Example: Door Block

Door Block
let door_bottom = Block::new("Door Bottom")
.id(80)
.rotatable(true)
.y_rotatable(true)
.aabbs(&[AABB::new().scale_z(0.2).build()])
.is_transparent(true)
.build();

let door_top = Block::new("Door Top")
.id(81)
.rotatable(true)
.y_rotatable(true)
.aabbs(&[AABB::new().scale_z(0.2).build()])
.is_transparent(true)
.build();

Read on to learn about TypeScript transport.