mciwb.builders#

Higher level building blocks: roofs, arches, columns, stairways, roads, foundations that follow the terrain, and Sponge schematic files.

They all build with the RCON client of the current thread (get_client), take Vec3 positions and blocks as Item, block state strings or BlockState, and return the bounding box (a Volume) of the blocks they placed, ready to grab, save or clear. A server error (e.g. an unknown block, or a position in an unloaded chunk) raises BuildError.

Coordinates follow Minecraft: Y is up, north is -z, east is +x.

Members

BlockState

A block id, its block state properties and optionally its block entity data (the contents of a chest, the text of a sign ...).

BuildError

The server rejected a building command, e.g. an unknown block or a position that is not loaded.

Heightmap

The Minecraft heightmaps: what counts as the ground.

PathStep

One block along the middle of a path

Placer

Place blocks with the RCON client of the current thread, recording the bounding box of every block placed.

Schematic

A box of blocks with their block states, e.g. to save to, or load from, a Sponge schematic .schem file.

arch

An arch standing in a vertical wall plane.

arch_profile

The blocks of an arch, as (u, v) cells where u counts across the span from 0 to span - 1 and v counts up from the springing line (v = 0).

column

A square column standing on base.

facing_name

The block state name of a Direction, e.g. "east" for Direction.EAST.

flat_roof

A flat roof: one layer of block, optionally with a parapet around its edge.

foundation

A foundation that follows the terrain: fill each column of a rectangular footprint from the ground up to start.y, giving a level platform at start.y to build on (at start.y + 1).

full_block_of

The full block made of the same material as a stairs block, e.g. Item.OAK_PLANKS for Item.OAK_STAIRS, Item.STONE_BRICKS for Item.STONE_BRICK_STAIRS.

gable_roof

A gable (pitched) roof: two slopes of stairs meeting at a ridge.

ground_height

The y of the top ground block at (x, z), see ground_heights.

ground_heights

The y of the top ground block of each of a set of columns.

hip_roof

A hip roof: four slopes of stairs, one from each side of the footprint, with outer corner stairs where they meet.

road

A road along a path that follows the terrain: each block of the road replaces the top ground block of its column.

slab_of

The slab made of the same material as a stairs block, e.g. Item.OAK_SLAB for Item.OAK_STAIRS.

stair_shapes

Work out the shape of each stairs block in one horizontal layer of stairs of the same half, as Minecraft does when the blocks are placed.

stairway

A stairway along a path, climbing (or descending) between the heights of its points.

trace_path

The blocks along the middle of a path through points, with the heights of the blocks spread evenly between the heights of the points.

class mciwb.builders.BlockState(name: str, props: Mapping[str, str]=<factory>, nbt: str = '')[source]#

A block id, its block state properties and optionally its block entity data (the contents of a chest, the text of a sign …).

str(state) gives the form that setblock and fill accept, and that Sponge schematic palettes use:

>>> state = BlockState.of(Item.OAK_STAIRS, facing="east", half="bottom")
>>> str(state)
'minecraft:oak_stairs[facing=east,half=bottom]'
>>> str(state.rotate(1))
'minecraft:oak_stairs[facing=south,half=bottom]'
>>> BlockState.parse("stone").name
'minecraft:stone'
>>> sign = BlockState.parse("oak_sign[rotation=4]{front_text:{}}")
>>> sign.nbt
'{front_text:{}}'
Variables:
  • name – the namespaced block id, e.g. minecraft:oak_stairs

  • props – the block state properties, e.g. {"facing": "east"}. Properties that are not given take the block’s default value.

  • nbt – the block entity data as SNBT text, including its braces, e.g. {Items:[{Slot:0b,id:"minecraft:apple",count:3}]}, or "" for none. setblock and fill give it to every block they place. It is compared as text, so states that differ only in the spacing or order of their NBT are not equal.

classmethod parse(block: Item | str | BlockState) → BlockState[source]#

Make a BlockState from an Item, a block state string or a BlockState. A string may end with block entity data in SNBT, as setblock takes it, e.g. chest[facing=west]{Items:[...]}.

Raises:

ValueError – if the string is not a valid block state

classmethod of(block: Item | str | BlockState, **props: str | bool | int | Vec3) → BlockState[source]#

Make a BlockState from a block and extra properties, e.g. BlockState.of(Item.OAK_STAIRS, facing=Direction.EAST). A Direction is converted to its name, a bool to true/false and an int to its digits, e.g. BlockState.of(Item.SNOW, layers=3). The new properties replace any that the block already has, and any block entity data is kept.

with_props(**props: str | bool | int | Vec3) → BlockState[source]#

A copy of this state with some properties added or replaced, e.g. .with_props(half="top", waterlogged=True, rotation=4)

with_nbt(nbt: str | None) → BlockState[source]#

A copy of this state with its block entity data replaced, e.g. .with_nbt('{Items:[{Slot:0b,id:"minecraft:apple",count:3}]}'). None or "" removes it.

Raises:

ValueError – if nbt is not one SNBT compound {...}

property item: Item#

The Item for this block, without its properties

Raises:

ValueError – if the block is not in Item e.g. a modded block

rotate(steps: int = 1) → BlockState[source]#

Rotate the block about the Y axis by steps quarter turns clockwise, viewed from above (north becomes east). Updates facing, axis, rotation (signs, banners, heads), direction named connections (fences, walls, panes, redstone) and rail shape. Block entity data is kept unchanged.

mirror(axis: str) → BlockState[source]#

Mirror the block along the "x" axis (east and west swap) or the "z" axis (north and south swap). Also swaps left and right, e.g. the stairs shape outer_left becomes outer_right.

exception mciwb.builders.BuildError[source]#

The server rejected a building command, e.g. an unknown block or a position that is not loaded

class mciwb.builders.Heightmap(value)[source]#

The Minecraft heightmaps: what counts as the ground.

WORLD_SURFACE = 'world_surface'#

the highest block that is not air (includes plants, snow layers …)

MOTION_BLOCKING = 'motion_blocking'#

the highest block that blocks movement, or holds water or lava

MOTION_BLOCKING_NO_LEAVES = 'motion_blocking_no_leaves'#

as MOTION_BLOCKING, but ignoring leaves

OCEAN_FLOOR = 'ocean_floor'#

the highest block that blocks movement, e.g. the bed of a lake or the sea

class mciwb.builders.PathStep(pos: Vec3, direction: Vec3)[source]#

One block along the middle of a path

pos: Vec3#

the position of the block

direction: Vec3#

the horizontal direction of travel into this block (out of it, for the first block)

class mciwb.builders.Placer(client: Client | None = None)[source]#

Place blocks with the RCON client of the current thread, recording the bounding box of every block placed.

Parameters:

client – the client to use, defaults to get_client

property volume: Volume#

The bounding box of every block placed so far

Raises:

ValueError – if nothing has been placed

include(start: Vec3, end: Vec3 | None = None) → None[source]#

Extend the bounding box to include a block, or a box of blocks

setblock(pos: Vec3, block: Item | str | BlockState) → str[source]#

Set one block, e.g. placer.setblock(pos, "oak_stairs[half=top]"). The block may carry block entity data, e.g. a sign’s text:

text = '''{front_text:{messages:['"Hi"','""','""','""']}}'''
placer.setblock(pos, "oak_sign[rotation=4]" + text)
fill(start: Vec3, end: Vec3, block: Item | str | BlockState, mode: FillMode | None = None, filter: str | None = None) → str[source]#

Fill the box between two opposite corners, inclusive. Block entity data in block (chest{Items:[...]}) is given to every block.

Parameters:
  • mode – e.g. FillMode.KEEP to only replace air

  • filter – only replace these blocks, e.g. "minecraft:stone" or a tag like "#minecraft:logs". Implies FillMode.REPLACE

Raises:

ValueError – if a filter is given with a mode other than REPLACE

layer(y: int, cells: Mapping[tuple[int, int], Item | str | BlockState])[source]#

Place one horizontal layer of blocks at height y, given as a mapping of (x, z) to block. Uses one fill for each rectangle of the same block.

class mciwb.builders.Schematic(blocks: ndarray, *, block_entities: list[dict[str, Any]] | None = None, offset: Vec3 = (0, 0, 0), metadata: dict[str, Any] | None = None, data_version: int = 5023)[source]#

A box of blocks with their block states, e.g. to save to, or load from, a Sponge schematic .schem file.

For example, copy a building with its stairs and slabs facing the right way, turned a quarter turn clockwise:

house = Schematic.from_world(Volume.from_corners(corner1, corner2))
house.save("house.schem")
Schematic.load("house.schem").rotate(1).paste(Vec3(100, 64, 0))
Variables:
  • blocks – a 3D numpy array of BlockState, indexed [x][y][z]

  • block_entities – the block entities (chests, signs …) from a file, as Sponge BlockEntity compounds (Pos, Id, Data). These are kept when saving, but not pasted into the world

  • offset – the Sponge Offset of the file, kept when saving, but not used when pasting

  • metadata – the Sponge Metadata compound (Name, Author…)

  • data_version – the Minecraft data version that the blocks are from

property size: Vec3#

The size of the schematic, as (width x, height y, length z)

property palette: list[BlockState]#

The different block states in the schematic

classmethod from_cuboid(cuboid: Sequence[Any] | ndarray) → Schematic[source]#

Make a schematic from a 3D list (or numpy array) of blocks indexed [x][y][z], e.g. from grab or load_items. The blocks may be Item, block state strings or BlockState.

to_cuboid() → list[source]#

The blocks as a 3D list of Item indexed [x][y][z], for use with Blocks or save_items. This loses the block states.

Raises:

ValueError – if a block is not in Item e.g. a modded block

classmethod from_world(volume: Volume, states: bool = True) → Schematic[source]#

Read the blocks in a Volume of the world.

Reading is slow: one RCON command for each block, and when states is True a few more for each stairs, slab and log-like block, to find its facing, half, shape, type or axis. Other block states (e.g. the facing of a door or a furnace) can not be read back, and those blocks take their default state. Block entity data (e.g. chest contents) is not read either. Some blocks read back as a related block, e.g. a wall torch as a torch, see get_block.

Parameters:
  • volume – the box of the world to read

  • states – read the block states of stairs, slabs and logs

paste(position: Vec3, air: bool = False) → Volume[source]#

Place the blocks in the world, with the schematic’s bottom north west corner (blocks[0][0][0]) at position. Uses one fill for each rectangle of the same block state in each layer, bottom layer first.

Parameters:
  • position – where to put the bottom north west corner

  • air – if True, also place the air blocks, clearing whatever is in the box. If False, leave the world unchanged where the schematic has air

Returns:

the box that the schematic covers in the world

rotate(steps: int = 1) → Schematic[source]#

A copy of the schematic turned about the Y axis by steps quarter turns clockwise, viewed from above (so a stairs block facing north faces east after one step). See BlockState.rotate for the block states that turn with it.

mirror(axis: str) → Schematic[source]#

A mirror image copy of the schematic: "x" swaps east and west, "z" swaps north and south. See BlockState.mirror.

classmethod load(filename: Path | str) → Schematic[source]#

Load a Sponge schematic file (version 2 or 3).

save(filename: Path | str) → None[source]#

Save as a Sponge schematic version 3 file (.schem).

Raises:

ValueError – if a block state carries block entity data (BlockState.nbt): a Sponge palette holds block states only, and its block entities are NBT compounds in block_entities

mciwb.builders.arch(start: Vec3, end: Vec3, block: Item | str | BlockState = Item.STONE_BRICKS, *, style: str = 'round', thickness: int = 1, depth: int = 1, clear: bool = False) → Volume[source]#

An arch standing in a vertical wall plane.

start and end are the two outermost blocks at the foot of the arch, on the same y and in a line along x or along z. The arch rises from there: a 7 block span with the default thickness of 1 looks like this (# is the arch, . the opening):

  ###          y = start.y + 3
###.###
#.....#
#.....#        y = start.y: start and end are the # at each end

Its legs are short: build walls or a column under it for a taller opening (or start it higher up). arch_profile gives the shape of any arch without building it.

Parameters:
  • start – the block at one foot of the arch

  • end – the block at the other foot, in line with start along x or z

  • block – the block to build the arch from

  • style – "round" (semicircular) or "pointed" (gothic)

  • thickness – the thickness of the ring of the arch, in blocks

  • depth – how many blocks thick the arch is through the wall. The extra blocks go south (for an arch along x) or east (along z)

  • clear – also set the opening under the arch to air, e.g. to cut an arched doorway through an existing wall

Returns:

the bounding box of the arch, and the opening if cleared

mciwb.builders.arch_profile(span: int, thickness: int = 1, style: str = 'round') → tuple[set[tuple[int, int]], set[tuple[int, int]]][source]#

The blocks of an arch, as (u, v) cells where u counts across the span from 0 to span - 1 and v counts up from the springing line (v = 0).

Parameters:
  • span – the outside width of the arch, in blocks

  • thickness – the thickness of the ring of the arch, in blocks

  • style – "round" (a semicircle) or "pointed" (a gothic, equilateral arch: two arcs whose radius is the width of the opening)

Returns:

(ring, opening): the cells of the ring of the arch, and the cells of the opening under it

mciwb.builders.column(base: Vec3, height: int, block: Item | str | BlockState = Item.QUARTZ_PILLAR, *, width: int = 1, plinth: Item | str | BlockState | None = None, capital: Item | str | BlockState | None = None) → Volume[source]#

A square column standing on base.

Parameters:
  • base – the bottom block in the middle of the column

  • height – the total height of the column, including any plinth and capital

  • block – the block for the shaft

  • width – the width of the shaft. Odd widths are centred on base, even widths have the extra block to the east and south

  • plinth – if given, the bottom layer is this block, one block wider than the shaft on every side

  • capital – if given, the top layer is this block, one block wider than the shaft on every side

Returns:

the bounding box of the column

mciwb.builders.facing_name(direction: Vec3) → str[source]#

The block state name of a Direction, e.g. "east" for Direction.EAST

Raises:

ValueError – if direction is not one of the six Directions

mciwb.builders.flat_roof(start: Vec3, end: Vec3, block: Item | str | BlockState = Item.SMOOTH_STONE, *, parapet: Item | str | BlockState | None = None, parapet_height: int = 1, overhang: int = 0) → Volume[source]#

A flat roof: one layer of block, optionally with a parapet around its edge.

Parameters:
  • start – a corner of the footprint, e.g. the top of a corner of the walls; the roof is at start.y + 1

  • end – the opposite corner of the footprint (only x and z are used)

  • block – the roof block, e.g. a full block or a slab

  • parapet – if given, build a low wall of this block around the edge of the roof, on top of it. Walls, fences and panes join up automatically

  • parapet_height – the height of the parapet

  • overhang – extend the roof this many blocks past the footprint on every side

Returns:

the bounding box of the roof and parapet

mciwb.builders.foundation(start: Vec3, end: Vec3, block: Item | str | BlockState = Item.COBBLESTONE, *, heightmap: Heightmap | str = Heightmap.OCEAN_FLOOR, max_depth: int = 64) → Volume[source]#

A foundation that follows the terrain: fill each column of a rectangular footprint from the ground up to start.y, giving a level platform at start.y to build on (at start.y + 1).

Build the foundation before anything above it: the ground height is the top of the highest block in each column, so a building already standing there would count as the ground. Columns where the ground is higher than start.y just get the top layer (replacing the ground there).

Parameters:
  • start – a corner of the footprint, at the height of the top of the foundation

  • end – the opposite corner of the footprint (only x and z are used)

  • block – the block to build the foundation from

  • heightmap – what counts as the ground. The default ignores water, so the foundation goes down to the bed of a lake or the sea

  • max_depth – the deepest any column may go, in blocks below start.y (a guard against building down into a ravine or the void). 0 gives just the top layer

Returns:

the bounding box of the foundation

mciwb.builders.full_block_of(stairs: Item | str | BlockState) → Item[source]#

The full block made of the same material as a stairs block, e.g. Item.OAK_PLANKS for Item.OAK_STAIRS, Item.STONE_BRICKS for Item.STONE_BRICK_STAIRS

Raises:

ValueError – if there is no matching block

mciwb.builders.gable_roof(start: Vec3, end: Vec3, stairs: Item | str | BlockState = Item.OAK_STAIRS, *, ridge: Item | str | BlockState | None = None, gable: Item | str | BlockState | None = None, axis: str | None = None, overhang: int = 0) → Volume[source]#

A gable (pitched) roof: two slopes of stairs meeting at a ridge.

For a footprint 7 wide across the ridge, seen from the gable end (# is the gable, if one is given):

      ▄            <- ridge slab, y = start.y + 4
    ◢ # ◣
  ◢ # # # ◣
◢ # # # # # ◣      <- stairs, y = start.y + 1
W . . . . . W      <- walls, top at start.y
Parameters:
  • start – a corner of the footprint, e.g. the top of a corner of the walls; the roof starts at start.y + 1

  • end – the opposite corner of the footprint (only x and z are used)

  • stairs – the stairs to build the slopes from

  • ridge – the block along the ridge when the footprint is an odd number of blocks across. Defaults to the slab matching stairs, placed as a bottom slab. The gap under it, between the stairs of the course below, is filled with the same block as a double slab (or with ridge itself if it is not a slab)

  • gable – if given, fill the triangular gable ends under the roof with this block, above the footprint’s end walls

  • axis – "x" or "z", the direction that the ridge runs. Defaults to the longer side of the footprint

  • overhang – extend the roof this many blocks past the footprint on every side (the slopes stay at the same height, so the eaves overhang the walls)

Returns:

the bounding box of the roof (and gables)

mciwb.builders.ground_height(x: float, z: float, heightmap: Heightmap | str = Heightmap.MOTION_BLOCKING_NO_LEAVES) → int[source]#

The y of the top ground block at (x, z), see ground_heights.

mciwb.builders.ground_heights(columns: Iterable[tuple[float, float]], heightmap: Heightmap | str = Heightmap.MOTION_BLOCKING_NO_LEAVES) → dict[tuple[int, int], int][source]#

The y of the top ground block of each of a set of columns.

Teleports a temporary marker entity to the top of each column, which costs one RCON command per column (plus two to make and remove the marker).

Parameters:
  • columns – (x, z) pairs

  • heightmap – what counts as the ground, see Heightmap

Returns:

the y of the top ground block, keyed by (x, z). In a column with no ground at all (e.g. the void in the End) this is one below the bottom of the world

Raises:

BuildError – if a column is not in a loaded chunk

mciwb.builders.hip_roof(start: Vec3, end: Vec3, stairs: Item | str | BlockState = Item.OAK_STAIRS, *, ridge: Item | str | BlockState | None = None, overhang: int = 0) → Volume[source]#

A hip roof: four slopes of stairs, one from each side of the footprint, with outer corner stairs where they meet. Each course is a ring of stairs one block in and one block up from the course below. Where the slopes meet along a line one block wide (the ridge) the roof is finished with ridge blocks, on a line of full blocks (the ridge slab doubled) that fills the middle of the course below.

Parameters:
  • start – a corner of the footprint, e.g. the top of a corner of the walls; the roof starts at start.y + 1

  • end – the opposite corner of the footprint (only x and z are used)

  • stairs – the stairs to build the slopes from

  • ridge – the block for a ridge one block wide, defaults to the slab matching stairs, placed as a bottom slab. The middle of the course below it is filled with the same block as a double slab (or with ridge itself if it is not a slab)

  • overhang – extend the roof this many blocks past the footprint on every side

Returns:

the bounding box of the roof

mciwb.builders.road(points: Sequence[Vec3], block: Item | str | BlockState = Item.DIRT_PATH, *, width: int = 3, border: Item | str | BlockState | None = None, clearance: int = 2, heightmap: Heightmap | str = Heightmap.MOTION_BLOCKING_NO_LEAVES) → Volume[source]#

A road along a path that follows the terrain: each block of the road replaces the top ground block of its column. The y of points is ignored.

The road does not smooth the terrain, it steps up and down with it. Use stairway for a path at fixed heights.

Parameters:
  • points – the start, each corner and the end of the road

  • block – the road surface

  • width – the width of the road

  • border – if given, the blocks along both edges of the road

  • clearance – set this many blocks above the road to air, clearing grass, flowers and snow

  • heightmap – what counts as the ground, see Heightmap. The default ignores leaves, but the road goes over the top of water

Returns:

the bounding box of the road

mciwb.builders.slab_of(stairs: Item | str | BlockState) → Item[source]#

The slab made of the same material as a stairs block, e.g. Item.OAK_SLAB for Item.OAK_STAIRS

Raises:

ValueError – if there is no matching slab

mciwb.builders.stair_shapes(stairs: Mapping[tuple[int, int], str]) → dict[tuple[int, int], str][source]#

Work out the shape of each stairs block in one horizontal layer of stairs of the same half, as Minecraft does when the blocks are placed.

Parameters:

stairs – the facing of each stairs block, keyed by (x, z)

Returns:

the shape of each stairs block, keyed by (x, z)

A stairs block’s facing is the side of its full height step, so people walking up it travel in that direction. A corner forms when the stairs in front of (or behind) it face across it: outer_left has its high corner on the facing side and the side counterclockwise from it, outer_right on the clockwise side. This follows StairBlock.getStairsShape in Minecraft.

mciwb.builders.stairway(points: Sequence[Vec3], stairs: Item | str | BlockState = Item.STONE_BRICK_STAIRS, *, landing: Item | str | BlockState | None = None, width: int = 1, support: Item | str | BlockState | None = None, clearance: int = 0) → Volume[source]#

A stairway along a path, climbing (or descending) between the heights of its points.

Each point is a block of the walkway, the block that people stand on, so the walkway’s surface is one block above it. Each section between two points climbs at most one block for each block along it. Where a block is higher than the one before it there is a stairs block (facing the way up), elsewhere a level landing block. So points at the same height give a level path.

The path may pass over itself, as in a spiral staircase round a tower or a switchback: each pass gets its own blocks. Choose the points so that there is headroom between one pass and the next one above it.

For example, from (0, 64, 0) east to (4, 66, 0):

      ◢ #    y = 66: stairs, then a landing at the end
  ◢ #        y = 65: stairs, landing
#            y = 64: a landing at the start
Parameters:
  • points – the walkway blocks at the start, each corner and the end

  • stairs – the stairs to climb with

  • landing – the block for the level parts, defaults to the full block matching stairs e.g. Item.STONE_BRICKS

  • width – the width of the stairway

  • support – if given, fill the space under the stairway with this block, down to the height of its lowest block (only replacing air). Where the stairway passes over itself, the support stops above the headroom of the pass below

  • clearance – set this many blocks above the walkway to air, to make headroom through the terrain

Returns:

the bounding box of the stairway

mciwb.builders.trace_path(points: Sequence[Vec3]) → list[PathStep][source]#

The blocks along the middle of a path through points, with the heights of the blocks spread evenly between the heights of the points.

In a section that climbs (or descends) by less than its length, the last block before each point (the first block after it, when descending) stays level, so that a corner is a landing.

Raises:

ValueError – if a section is diagonal, or climbs more than one block for each block along