Skip to content
battlemap-mcp docs
You're reading the docs for battlemap-mcp v1.2.0, an earlier release. See this page in the latest docs.

Terrain, paths, water and caves

Generated from battlemap-mcp v1.2.0. Your assistant gets these same names, descriptions and parameters from the server when it connects; the server is named battlemap, so a client may show a tool as battlemap:ping or similar.

set_terrain_slot

Assign a Terrain asset to a terrain slot index so it can be filled/painted with that slot.

ParameterTypeDefaultDescription
asset requiredstring
slotinteger0

fill_terrain

Flood-fill the whole current level with a terrain slot.

If asset is given, it is assigned to the slot first.

The usual first ground call is fill_terrain(asset=<base material>) on the default slot 0: that replaces the base under everything and leaves slots 1-3 free for roads, yards and worn edges painted on top with fill_region.

ParameterTypeDefaultDescription
slotinteger0
assetstring""

fill_region

Fill only a region with a terrain slot (e.g. floor a single room), in woxel coords.

Unlike fill_terrain (whole level), this paints inside a shape. Provide ONE of: rect, points, asset or rate.

ParameterTypeDefaultDescription
rectnumber[] | nullnull[x, y, w, h] axis-aligned rectangle, or
pointsnumber[][] | nullnull[[x,y], ...] a polygon (>= 3 points).
slotinteger0
assetstring""optional Terrain asset to assign to the slot first.
ratenumber1paint strength 0..1 (1 = fully replace). Undoable via undo().

paint_terrain

Paint a soft circular terrain brush of a slot at a woxel position.

a smooth falloff to the rim so strokes blend. asset: optional Terrain asset to assign to the slot first (else set it with set_terrain_slot). Undoable. For a hard-edged region instead of a brush, use fill_region.

ParameterTypeDefaultDescription
slotinteger0
xnumber | nullnull
ynumber | nullnull
radiusnumber64brush radius in woxels.
ratenumber1peak strength 0..1 at the center, with
assetstring""

paint_path

Paint a continuous terrain stroke (a road/trail) along a polyline in one call.

asset is a TERRAIN asset, not a Paths one — this paints ground, it does not lay a Paths element. Use draw_path for that.

bridge rasterizes a uniform ribbon of constant width by measuring each pixel's distance to the nearest segment, so the route comes out smooth with clean edges — no gaps or double-painted overlaps. Prefer this over stamping many paint_terrain dabs for any line/road.

soft falloff to the edges so it blends. asset: optional Terrain asset to assign to the slot first (else set it with set_terrain_slot). Undoable.

ParameterTypeDefaultDescription
points requirednumber[][]a list of [x, y] woxel corners the path runs through (>= 2). The
slotinteger0
radiusnumber96half-width of the stroke in woxels.
ratenumber1peak strength 0..1 with a
assetstring""

paint_material

Paint a MATERIAL patch along a brush stroke. Returns what it painted.

Materials are their own system — irregular patches of stone, earth, lava or moss with their own borders — and they are not terrain and not patterns. A Materials asset passed to place_pattern makes a PATTERN, not a material.

Choose between them deliberately: terrain ground that must BLEND into neighbouring ground pattern a tiled floor inside a building material a sculpted patch with its own edge, sitting on top of ground water actual water

The response reports cell_size_woxels and covered_woxels so the brush size can be reasoned about on the ground. There is no "did it land" flag, because the engine offers no reliable one: verify a stroke by looking at it.

ParameterTypeDefaultDescription
points requirednumber[][]the stroke, in woxels. One point is a single dab.
asset requiredstringa Materials path from list_assets(category='Materials').
sizeinteger2brush radius in mesh CELLS, 1-20. A cell is typically one tile, so size 6 paints roughly twelve tiles across PER DAB. Start at 1-2 and look.
layerinteger-400which material layer to paint into. Materials on different layers stack rather than merge.
smoothbooleantruesmooth the patch's edge, versus following the material's own texture.
erasebooleanfalseremove this material along the stroke instead of adding it.

get_terrain

Read the terrain back: sample the painted terrain on a grid.

Returns a weights grid, row-major from the rect's top-left. Each point is [slot0, slot1, slot2, slot3], read directly from the splat image's RGBA channels and summing to ~1, and slots: the texture each of those four slots holds.

Slot 0 is the BASE: whatever slots 1-3 leave unclaimed shows slot 0's texture. So [1, 0, 0, 0] means "all slot 0" — and what that looks like depends entirely on slots[0]. On a new map every slot holds limestone, so it is ground nobody chose; after fill_terrain(asset=grass) it is grass. The weights cannot tell those apart, which is why slots is reported. paint_terrain(slot=0) is accepted by the engine but never raises slot 0's weight; fill_terrain(slot=0) replaces the base instead.

Slots 4-7 live in a second splat image, reported as weights2. All eight weights are one blend: painting any slot takes weight from the other seven. A slot 4-7 needs a texture (set_terrain_slot) before it is painted.

This is the only way to check terrain without a screenshot — use it to confirm a fill or paint landed where you meant, and to see what ground you inherited on a map you did not build.

ParameterTypeDefaultDescription
rectnumber[] | nullnull[x, y, w, h] in woxels; omit for the whole map.
samplesinteger16grid resolution per side, 2-64 (16 = 256 points).

set_terrain_blending

Choose how terrain slots blend into one another on this level.

This is a per-level setting that affects every terrain edge already painted, not just the next one, so choose it before painting rather than after.

get_terrain reports the current value as smooth_blending.

ParameterTypeDefaultDescription
enabled requiredbooleanTrue for smooth blending (slots fade into each other), False for textured (the blend follows the material's own texture, giving a grainier, more natural seam).

repair_terrain

Rebuild a level's terrain splat when the engine dropped it. Destructive.

Only needed on a map whose terrain has already been lost. Symptom: every terrain call answers "the terrain splat image is empty", and Dungeondraft's log carries Expected data size of N bytes in Image::create() at load.

That happens when a map was resized while its terrain was not. The splat keeps the pixel dimensions it was created with, the mismatch is silent until the map is next opened, and Godot then refuses the image and drops every painted stroke — while the save that produced it reported success. set_map_size now resizes the rasters with the map, so new maps do not reach this state; this repairs one that already did.

It does not recover anything. The painted terrain is gone before this runs; all it restores is a usable surface to paint on, so the terrain has to be laid down again afterwards. Nothing else on the map is touched.

ParameterTypeDefaultDescription
forcebooleanfalseblank a splat that is already usable. This throws away working terrain, so it is off by default.

draw_path

Draw a path/road/river through a list of [x, y] woxel points. Returns the new element id.

A wall-textured path looks like a wall but carries no line of sight into a VTT export. Where vision matters, run a real draw_wall along it too.

End treatments, which are what make a path read as part of the world rather than a strip laid on top of it:

fade_in / fade_out: the path's opacity fades at its start / end. Use where a trail should disappear into undergrowth or run off the map edge, instead of stopping at a hard rectangular cut. grow / shrink: the path's WIDTH tapers at its start / end. A stream that narrows upstream, a track that widens as it approaches a gate.

Set these per path, here: changing the PathTool's own options beforehand does not affect what this draws.

ParameterTypeDefaultDescription
points requirednumber[][]
asset requiredstringa Paths asset path from list_assets(category='Paths').
layerinteger0
sortinginteger0
smoothnessnumber | nullnulloptional curve smoothing.
widthnumber | nullnulloptional width scale multiplier.
fade_inbooleanfalse
fade_outbooleanfalse
growbooleanfalse
shrinkbooleanfalse
snapstring""'none', 'grid' or 'auto'; see get_snap_settings.

add_water

Add a body of water — a pond, pool, river bend, moat, or flooded room.

Water is a polygon layer, not a brush stroke: you give it a closed outline and the whole enclosed area becomes water. Give exactly one of: rect or points.

Call it repeatedly to build up several separate bodies of water. When the level's existing water shares one style (set_water_style), new water takes it too and the response says matched_level_style.

ParameterTypeDefaultDescription
rectnumber[] | nullnull[x, y, w, h] in woxels, or points: [[x,y], ...] for a shoreline. [x, y, w, h] in woxels, for a rectangular pool.
pointsnumber[][] | nullnull[[x, y], ...] with at least 3 points, for an irregular shape — a pond, a river bend, a cave lake. The outline closes automatically.
invertbooleanfalseerase water inside the outline instead of adding it. Water is a layer, not an object — there is nothing to select and delete — so this is how you take a pond back or cut an island out of one.

set_water_style

Style this level's water: what KIND of water it is. Returns the result.

Geometry first (add_water), then this. A muddy river, a clear shallow, a peat swamp and a deep cold pool are the same mesh with different colour.

Per LEVEL: every body of water on this level is restyled, and water drawn later on a level whose bodies share one style takes that style too. The response reads the style back off the water bodies, which are what the map saves; bodies is how many there are, and mixed_styles means they differ.

ParameterTypeDefaultDescription
deep_colorstring""
shallow_colorstring""
blend_distancenumber | nullnull
borderboolean | nullnull

dig_cave

Carve a cave along a path with the Cave Brush (the dig/blast tool).

Dungeondraft caves are a separate layer: you dig open floor out of solid rock, and DD auto-generates the rocky wall border + debris around the opening.

point digs one circular chamber; multiple points dig a connected tunnel (rasterized as a constant-width ribbon, like paint_path). radius: half-width in woxels (default 256 = ~1 tile). dig: True carves open cave; False fills it back to rock. ground_color / wall_color: optional cave floor/wall tints ("#rrggbb" or [r,g,b]). texture: optional Caves floor asset (see list_assets(category="Caves")). The mesh rebuilds automatically.

ParameterTypeDefaultDescription
points requirednumber[][]a list of [x, y] woxel points the cave runs through (>= 1). A single
radiusnumber256
digbooleantrue
ground_colorstring""
wall_colorstring""
texturestring""

get_cave

Read the selected level's cave floor/entrance cell counts and actual colours.

Entrances are a separate blast mask that removes rocky borders; they do not carve floor. Counts describe bitmap cells, not distinct rooms or openings.

No parameters.

set_cave_entrance

Open or restore a circular section of cave border, as one undoable edit.

Place the centre at an existing cave edge in woxels. radius is the half-width (0 < radius <= 2048), rounded to cave cells. open=False removes the blast mask, restoring the border; neither mode digs or fills cave floor. Dig the approach first with dig_cave, then inspect a screenshot of the mouth. The edit belongs to the selected level. Undo requires that same level and unchanged bitmap dimensions. Returns the actual number of changed cells.

ParameterTypeDefaultDescription
x requirednumber
y requirednumber
radiusnumber256
openbooleantrue

clear_caves

Wipe the entire cave layer back to solid rock.

Removes all carved caves at once (the whole cave system), rebuilding the mesh. Undoable like dig_cave. Use this instead of filling regions back with dig_cave(dig=False) when you want to reset all caves.

No parameters.