Skip to content

API Worldgen Structure Terrain

Piggo41 edited this page Oct 17, 2026 · 6 revisions

Structure terrain placement

Lua API / World generation / Structure terrain placement

Terrain placement controls how a local structure relates to nearby world terrain. It is opt-in: a structure with no terrain field uses exact, preserving its supplied Y coordinate and the behavior of existing scripts. Foundation, terrace, and conform policies describe terrain adaptation; independent excavation can be combined with every mode.

Site profiles answer a separate question: whether the environment is suitable. For example, a foundation can geometrically reach an ocean floor, while site = { type = "land_surface" } still rejects that submerged location.

Fitting a supported surface structure

Declare the terrain behavior on the local structure and the environment requirement on its placement.

local shrine = betamoon.worldgen.structures:add {
    key = "mymod:shrine",
    rotation = "random_horizontal",
    terrain = {
        mode = "foundation",
        surface = "solid_surface",
        anchor = "median",
        maxSlope = 3,
        maxStep = 2,
        verticalOffset = -1,
        foundation = {
            footprint = {
                source = "support",
                shape = "rounded_bounds",
                padding = 1,
                cornerRadius = 2
            },
            edge = { type = "stepped", stepEvery = 1, maxExpansion = 2 },
            material = "minecraft:cobblestone",
            maxDepth = 6
        }
    }
}

betamoon.worldgen.placements:add {
    key = "mymod:shrine",
    feature = shrine,
    position = { height = { type = "solid_surface" } },
    conditions = {
        site = {
            type = "land_surface",
            scope = "support_footprint"
        }
    }
}

The height provider proposes an initial location. The site profile checks the transformed footprint, then the terrain policy resolves the final structure height and prepares any terrain changes. A failed check rejects the complete atomic plan without leaving partial foundations or cuts.

Terrain modes

Choose the least invasive mode that matches the structure:

  • exact for authored elevations, floating structures, or underground pieces that must not move;
  • fit for a rigid small structure that may move vertically but must already have direct support;
  • foundation when a rigid structure may fill bounded gaps below itself;
  • terrace when a rigid building should reshape a bounded, level pad;
  • conform for independently movable marked columns such as roads, fences, and low decorations.
Mode Behavior
exact Uses the supplied Y without fitting. Independent excavation and verticalOffset still apply when declared. This is the default.
fit Chooses one rigid vertical anchor from the support footprint and rejects excessive slope, steps, or insufficient direct support.
foundation Performs a rigid fit, then constructs bounded fill-only support beneath a selected footprint.
terrace Performs a rigid fit and creates a bounded two-sided cut-and-fill grade plus an optional transition.
conform Moves explicitly selected support columns independently. It is intended for paths, fences, and low decorations rather than buildings.

Adaptive modes use these common fields:

Field Default / behavior
surface solid_surface; see surface samplers below.
anchor median; also minimum, maximum, mean, center, or percentile.
percentile 0.5, from 0 through 1 when anchor = "percentile".
maxSlope 2, from 0 through 32; maximum height range across support cells.
maxStep maxSlope, from 0 through 32; maximum difference between neighboring support cells.
requireSupportRatio 0.5 for fit, otherwise 0; required directly supported fraction.
verticalOffset 0, from -32 through 32; applied once to the resolved anchor and shared by structure blocks, excavation, adaptation, markers, loot, preview, and regional persistence.

The anchor is calculated from one candidate per support column. Each candidate subtracts that support point's local Y from its sampled surface Y, so raised support points remain meaningful. minimum and maximum select the lowest and highest candidate. median selects the lower middle candidate when the count is even. mean rounds the arithmetic mean to the nearest integer. center uses the origin column when it is part of the support mask and otherwise falls back to the median. percentile selects the rounded index through the sorted candidates.

Legacy flat foundation fields (foundationBlock, foundationMeta, and maxFoundationDepth) and terrace fields (foundationBlock, foundationMeta, maxCutDepth, maxFillDepth, padding, blendRadius, and maxBlendStep) remain supported. Matching flat and nested values may be combined during migration; conflicting values are rejected.

Footprints and named masks

Foundation cores, terrace cores, conform selections, and footprint excavation share the same transformed mask form.

Field Values and behavior
source support, base_bounds, template_bounds, clearance, or named; authored aliases named. base_bounds surrounds the support mask, so elevated roof-only overhangs do not enlarge it.
name Required for a named mask. Reusable masks are declared in terrain.masks.
shape mask, bounds, convex_hull, rounded_bounds, or authored; support_footprint aliases mask.
cells Explicit authored {x, z} cells. They rotate and mirror with the structure.
padding / inset Bounded dilation or erosion from 0 through 8. An inset may not remove required support.
cornerRadius Radius from 0 through 16 for rounded_bounds.
preserveHoles Retains courtyards and other holes while applying a filled shape.
select Filters support cells by states, tags, match = "any"|"all", authored bounds, local height, or nearMarker.
exclude Removes matching states or tags.

select.states requires one of the listed symbolic palette-state names. select.tags checks the combined palette and element tags; match controls whether any or all listed tags are required. Both state and tag requirements must pass when both are present. select.bounds = { min = {x, y, z}, max = {x, y, z} } and select.height inspect the authored support coordinate before rotation. select.nearMarker accepts a marker name or { name = "marker_name", radius = 0..16 } and uses horizontal distance. exclude.states and exclude.tags always win. The compatibility spellings select.excludeStates and select.excludeTags are also accepted.

terrain = {
    masks = {
        roads = {
            source = "support",
            select = { tags = { "road_surface" }, match = "any" },
            exclude = { tags = { "bridge", "fixed_grade" } }
        },
        courtyard = {
            shape = "authored",
            cells = { { -2, -2 }, { -1, -2 }, { 0, -2 }, { 1, -2 }, { 2, -2 } }
        }
    }
}

Masks are two-dimensional coordinate selections. The consuming policy decides whether those cells receive support, grading, conform movement, or excavation. A resolved footprint is limited to 4096 cells and 64 blocks per horizontal dimension; the complete placement remains subject to the smaller effective radius-32 feature boundary.

Terrain material declarations

Foundation and terrace material fields accept a block reference, { block = ..., metadata = 0 }, "sample_surface", "sample_subsurface", or a deterministic weighted palette:

material = {
    layers = {
        { block = "minecraft:cobblestone", weight = 4 },
        { block = 48, weight = 1 } -- mossy cobblestone in Beta 1.7.3
    }
}

Despite the compatibility field name layers, these are weighted choices sampled stably by coordinate and depth; they are not assigned in list order by depth. A palette accepts 1–64 entries, each with metadata = 0..15 and weight = 1..1024. Every resolved material must be a solid non-air block without a tile entity. Sampled materials come from the pre-mutation terrain.

Foundation policy

terrain.foundation is available with mode = "foundation". Its default footprint is the exact support mask and its default hard edge preserves legacy support-column behavior when the nested table is omitted.

Field Default / behavior
footprint Shared footprint declaration or "support", "base_bounds", or a named mask.
edge.type hard, stepped, blended, natural, or authored. Foundation edges add fill only; they never cut high terrain.
edge.stepEvery Vertical blocks per outward step, 1 through 16.
edge.maxExpansion Maximum skirt expansion, 0 through 8.
edge.mask Named mask used by an authored edge.
material Fixed solid block, sampled material, or deterministic weighted palette; see material declarations above.
capMaterial, edgeMaterial, fillMaterial Optional deterministic overrides for the corresponding part.
maxDepth Required-column depth limit, 1 through 32; defaults to 6.
replace Replacement preset or compiled selector; defaults to terrain_and_vegetation.
fluids reject, replace, or preserve; defaults to reject.
maxUnsupportedSpan Optional maximum horizontal run not backed by an authored support column, 0 through 32; 0 disables the check.
requireSupportRatio Required pre-existing support fraction from 0 through 1.
maxBlocks Maximum foundation writes, 1 through 8192; defaults to 4096.

Every core support is retained after shaping. A stepped or natural skirt may vary only optional boundary cells. Tile entities and bedrock always reject the complete plan. A negative offset moves the foundation with the structure and permits the declared material to replace the terrain layer into which the authored floor is embedded.

Terrace policy

terrain.terrace is available with mode = "terrace". The core is brought to one construction grade. A bounded transition approaches untouched terrain with integer voxel steps.

Field Default / behavior
footprint Shared core footprint. Explicit nested policies default to the support mask.
transition.type hard, stepped, graded, blended, natural, or authored.
transition.radius Bounded transition radius from 0 through 8.
transition.maxStep Maximum height adjustment per transition cell, 1 through 8.
transition.mask Named mask used by an authored transition.
maxCutDepth / maxFillDepth Per-column limits from 0 through 16; defaults to 3 and 6.
topMaterial Fixed/palette material or sample_surface; sampled surface is the default.
fillMaterial Fixed/palette material or sample_subsurface; sampled subsurface is the default.
replace Replacement preset or compiled selector; defaults to ordinary_terrain.
fluids reject, replace, or preserve; defaults to reject.
maxBlocks Maximum terrace writes, 1 through 8192; defaults to 4096.

Cut columns reconstruct their final top material from the pre-mutation sample. Core heights remain level; natural variation affects only optional transition cells. Any depth, grade, protection, fluid, read, or shared mutation-budget failure rejects the whole plan.

Conforming-column selection

Without a nested conform table, conform mode keeps its marker-only compatibility behavior. New structures can move the entire support mask or select tagged/state-filtered columns without authoring one marker per cell.

terrain = {
    mode = "conform",
    masks = {
        roads = {
            source = "support",
            select = { tags = { "road_surface" } },
            exclude = { tags = { "bridge" } }
        }
    },
    conform = {
        columns = { source = "named", name = "roads" },
        maxDisplacement = 5,
        maxStep = 1,
        smoothing = { radius = 1, passes = 2 }
    }
}

columns accepts "support", "markers", a named-mask string, or a footprint selector. An explicit empty selection rejects unless allowEmpty = true. terrain_conform includes one valid support column and terrain_conform_exclude removes it; exclusion wins. Smoothing is deterministic, bounded, and does not move unselected cells. Every structure block, connector, marker, tile-data target, and loot element in a selected X/Z column receives the same offset. Regional plans persist the resolved offsets.

Field Default / behavior
columns Required in an explicit table: "support", "markers", a named mask, or a footprint selector.
maxDisplacement Maximum movement from the rigid anchor, 1 through 16; defaults to 4.
maxStep Maximum neighboring selected-column difference, 0 through 8; defaults to 1.
smoothing.radius Horizontal smoothing radius, 1 through 4.
smoothing.passes Deterministic smoothing passes, 1 through 8.
allowEmpty Allows a conditionally empty explicit selection; defaults to false.

Independent excavation

terrain.excavation removes permitted world cells before foundation/terrace work and final structure geometry. It is valid with exact, fit, foundation, terrace, and conform. Clearance markers and negative offsets never enable excavation implicitly.

terrain = {
    mode = "fit",
    verticalOffset = -4,
    excavation = {
        footprint = { source = "base_bounds", shape = "rounded_bounds", padding = 1, cornerRadius = 1 },
        vertical = { from = 0, to = "surface" },
        result = "air",
        replace = "ordinary_terrain",
        fluids = "reject",
        maxBlocks = 4096
    }
}

A simple declaration extrudes one footprint. from and to are inclusive local integers, "surface", strings such as "surface-1", or { surface = true, offset = -1 }. A surface bound resolves to the highest terrain cell (sampled surface height - 1) plus its optional offset. These values are cached before any terrain mutation.

Use volumes for up to 16 shapes:

  • footprint uses footprint, from, and to;
  • box uses inclusive local min and max vectors;
  • cylinder uses local center, radius, and upward height;
  • ellipsoid uses local center and { x, y, z } radii;
  • authored uses exact local cells, or name to use a reusable three-dimensional mask declared in excavation.masks; when both are omitted, it reuses explicit terrain_clearance voxels.
Shape Required values and limits
footprint Optional shared footprint; inclusive from/to default to 0. Local integer bounds are -64 through 64; surface offsets are -32 through 32.
box Inclusive min and max local vectors, with each component from -64 through 64.
cylinder Local center, radius = 1..16, and height = 1..32.
ellipsoid Local center and radii.x/y/z = 1..16.
authored 1–4096 local voxel cells, a named mask containing 1–4096 voxels, or the template's explicit clearance voxels.

The simple footprint/vertical/from/to form and volumes are mutually exclusive. maxBlocks defaults to 4096 and accepts 1–8192 unique excavation cells, but the complete feature still shares the global 8192-write and radius-32 limits. All local shapes and masks follow the resolved structure rotation and mirror.

Only result = "air" is currently supported. replace accepts ordinary_terrain, terrain_and_vegetation, replaceable, or a compiled selector table. Fluid handling is reject, drain, or preserve. Tile entities and bedrock always reject. With preserve, matching non-fluid cells are still excavated while fluid cells remain. Overlaps are deterministic: excavation has the lowest priority, foundation/terrace work wins over it, and final structure blocks win over both. A processor-removed structure cell leaves the excavation result in place.

Reusable exact voxel masks and replacement selectors look like this:

excavation = {
    masks = {
        cellar = { { -2, 0, -2 }, { -1, 0, -2 }, { 0, 0, -2 } }
    },
    volumes = {
        { shape = "authored", name = "cellar" }
    },
    replace = {
        preset = "ordinary_terrain",
        blocks = { "minecraft:gravel" },
        tags = { "#replaceable" },
        excludeBlocks = { "minecraft:bedrock" },
        match = "any"
    }
}

Selector tables accept preset, blocks, tags, excludeBlocks, excludeTags, and match = "any"|"all". Supported compiled classifier tags are #ordinary_terrain, #replaceable, #terrain_and_vegetation, and #solid_terrain_material. Exclusions win. Tile entities and bedrock remain hard protections regardless of selector.

Surface and underground height providers

Type Result
surface / world_surface The first cell above the world's height-map obstruction, including fluid and foliage.
solid_surface The first cell above structurally solid ground, ignoring air, fluid, plants, leaves, and snow layers.
ocean_floor The first cell above the solid floor below a water column; on dry land it resolves to the solid surface.
fluid_surface The first cell above the top fluid block, or no candidate when the column has no exposed fluid.
underground A random depth below solid_surface; configure minDepth and maxDepth.
cave_floor The floor of an existing open cavity between min and max; minimumClearance defaults to 3.

Surface providers accept offset. exact is a terrain-policy surface only and is not a height provider.

Site profiles

Use conditions.site on a placement and site on a regional structure. A string such as site = "land_surface" selects preset defaults; a table adds thresholds and scope.

Type Default meaning
any No footprint-aware environment restriction.
land_surface Requires a dry support environment; exact placement additionally checks direct surface contact.
underwater Requires a water-covered support environment with sufficient fluid depth; exact placement additionally checks floor contact.
underground The selected volume is below the solid surface.
cave The clearance volume is an existing air cavity below solid cover; it is not carved to pass validation.
fluid_surface Requires an exposed fluid surface in the support columns; outside exact mode it does not move the structure to that surface.

The preset defaults are:

Preset Scope and active defaults
any origin; no check unless another non-default constraint is supplied.
land_surface support_footprint; maxFluidCoverage = 0.
underwater support_footprint; water medium, minFluidCoverage = 1, and minFluidDepth = 1.
underground full_bounds; minDepthBelowSurface = 1.
cave clearance_mask; air medium, depth at least 8, existing-air ratio at least 0.9, solid cover at least 3, and no sky.
fluid_surface support_footprint; an exposed fluid surface must exist. Use a matching height provider or terrain sampler to fit to it.

Scopes select concrete world cells. origin examines the resolved placement-origin cell. support_footprint examines the resolved terrain-contact cell for each support column. clearance_mask examines explicit terrain_clearance cells, or every cell in the transformed bounds if no clearance markers exist. full_bounds examines every coordinate in the transformed inclusive bounds.

Medium, depth, sky, cover, and existing-air checks use the selected scope. Fluid coverage and depth are measured over the support footprint even when another scope is selected. Site checks decide whether an environment is eligible; terrain modes separately decide whether and how a structure can fit there.

For exact placement, the land, underwater, and fluid-surface profiles also validate direct contact at the supplied height. Foundation placement accepts land or underwater support at or above its fitted floor, before applying the configured verticalOffset, so the foundation can bridge downward gaps and an intentional negative offset can embed the authored floor. Other adaptive modes rely primarily on their selected terrain sampler plus the profile's coverage and medium constraints. Pair fluid_surface with the fluid_surface height provider or terrain surface when the structure must actually be fitted to the fluid top.

scope may be origin, support_footprint, clearance_mask, or full_bounds. medium may be any, air, water, lava, any_fluid, or solid. Advanced thresholds are minDepthBelowSurface, maxDepthBelowSurface, minFluidDepth, maxFluidDepth, minFluidCoverage, maxFluidCoverage, minExistingAirRatio, minSolidCover, and maxSolidCover. Coverage and ratios range from 0 through 1. requireSky = true requires every scoped cell to see the sky; false requires every scoped cell not to see it.

Template terrain markers

Terrain markers use ordinary template marker records and place no visible block.

[
  { "type": "marker", "pos": [1, 0, 1], "name": "terrain_support" },
  { "type": "marker", "pos": [2, 1, 1], "name": "terrain_clearance" },
  { "type": "marker", "pos": [4, 0, 1], "name": "terrain_ignore" },
  { "type": "marker", "pos": [3, 0, 1], "name": "terrain_conform" },
  { "type": "marker", "pos": [5, 0, 1], "name": "terrain_conform_exclude" },
  { "type": "marker", "pos": [0, 0, 1], "name": "terrain_blend" }
]
Marker Meaning
terrain_support Declares a cell that should contact terrain or receive support. If any are present, they replace the automatic support mask.
terrain_clearance Declares a cell used by clearance-scoped cave or medium checks, and by an authored excavation volume that explicitly omits name and cells.
terrain_ignore Removes its X/Z column from an automatically derived support mask.
terrain_conform Includes that complete support column in conform mode.
terrain_conform_exclude Excludes that support column after configured and marker inclusions.
terrain_blend Adds its X/Z column to the legacy flat terrace transition area.

Without terrain_support markers, BetaMoon uses non-air blocks on the structure's lowest resolved structural layer in each non-ignored X/Z column. Elevated roof-only and decoration-only columns therefore do not expand base_bounds. Conditional geometry and deterministic processors resolve first. If any explicit support markers are present, they replace the automatic mask rather than adding to it. Conform include/exclude markers never create support by themselves. All masks follow the structure's rotation and mirror.

Regional terrain placement

Regional pieces reuse the complete local terrain policy, including fit, foundation/terrace work, conform offsets, and excavation. The regional start's site profile applies to the root and candidate child pieces. connectorVerticalTolerance controls how far a child may move vertically after terrain fitting or conforming; it defaults to 0 so connected floors remain aligned.

siteSearch = { attempts = 8, radius = 7 } lets an invalid root try a bounded deterministic set of positions inside its selected chunk. It never searches or loads neighboring chunks. Later chunks of the same regional structure use the same chosen origin and terrain result, even when surrounding terrain has changed. If relevant placement definitions change before the plan is complete, BetaMoon pauses the unfinished parts rather than mixing incompatible behavior.

Preview and direct placement use the same local planner. Their optional details table reports anchor and surface samples; foundation core, edge, depth, and bounds; terrace core, transition, cut, fill, and bounds; conform source, selection, components, and displacement range; excavation volume, removed, preserved, and overlap counts; total terrain/structure writes; and the first representative rejected position. Repetitive cells remain aggregated.

Rejection reason Meaning
terrain_unreadable Required terrain samples could not be read within the planner's bounds.
terrain_slope The sampled height range exceeds maxSlope.
terrain_step Neighboring support samples exceed maxStep.
terrain_support The directly supported fraction is below requireSupportRatio.
foundation_invalid_footprint The selected shape is empty, unknown, over limit, or removes required support.
foundation_too_deep A required foundation column exceeds maxDepth.
foundation_protected_block, foundation_tile_collision, foundation_fluid_collision Foundation work intersects forbidden terrain.
terrace_invalid_footprint The core or authored transition mask is invalid.
terrace_cut_limit Required terrace cutting exceeds maxCutDepth.
terrace_fill_limit Required fill exceeds maxFillDepth.
terrace_grade_limit Adjacent planned grades exceed the transition step.
terrace_protected_block, terrace_tile_collision, terrace_fluid_collision Terrace work intersects forbidden terrain.
excavation_invalid_volume, excavation_too_large, excavation_unreadable The excavation shape, budget, or required world data is invalid.
excavation_protected_block, excavation_tile_collision, excavation_fluid_collision Excavation intersects forbidden terrain.
conform_empty_selection, conform_unknown_mask, conform_selector_invalid The explicit conform selection cannot be resolved.
conform_displacement_limit, conform_step_limit, conform_column_collision Selected columns cannot move safely.
terrain_mutation_budget The combined excavation and terrain-adaptation plan exceeds its write budget.
site_wrong_surface_relation The requested surface relationship does not hold.
site_wrong_medium Scoped cells do not match the requested air, water, lava, fluid, or solid medium.
site_fluid_coverage Fluid coverage lies outside the configured range.
site_fluid_depth Fluid depth lies outside the configured range.
site_depth Depth below the solid surface lies outside the configured range.
site_insufficient_cover Solid cover lies outside the configured range.
site_insufficient_cavity The existing-air ratio is too low for the requested cavity.
site_sky_mismatch The cells do not satisfy requireSky.

Examples: rounded stepped foundation, selector-conforming regional roads, minimal sunken-cellar excavation, and authored excavation plus foundation.

Clone this wiki locally