Repository navigation
API Worldgen Structure Terrain
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.
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.
Choose the least invasive mode that matches the structure:
-
exactfor authored elevations, floating structures, or underground pieces that must not move; -
fitfor a rigid small structure that may move vertically but must already have direct support; -
foundationwhen a rigid structure may fill bounded gaps below itself; -
terracewhen a rigid building should reshape a bounded, level pad; -
conformfor 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.
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.
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.
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.
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.
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. |
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:
-
footprintusesfootprint,from, andto; -
boxuses inclusive localminandmaxvectors; -
cylinderuses localcenter,radius, and upwardheight; -
ellipsoiduses localcenterand{ x, y, z }radii; -
authoreduses exact localcells, ornameto use a reusable three-dimensional mask declared inexcavation.masks; when both are omitted, it reuses explicitterrain_clearancevoxels.
| 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.
| 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.
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.
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 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.
- Installation
- Install scripts
- Getting started
- VS Code and LuaLS
- Examples
- Reload and compatibility
- Troubleshooting
- Changelog
Scripts and shared values
- Script lifecycle
- Packaged Lua mods
- Modules
- References and stacks
- Queries
- Overrides
- Minecraft constants
- Chat and positions
- Structured data
- Script configuration
- Particles
Blocks and items
- Multiblocks
- Blocks
- Block state and placement
- Block shapes and rendering
- Block callbacks
- Block ticks and redstone
- Items
- Fluids
- Item callbacks
- Tools and armor
- Materials
- Textures
Entities
- Entities
- Entity access and movement
- Entity lifecycle and data
- Entity health and loot
- Entity inventories and relationships
- Projectiles and pickups
- Entity presentation and sounds
- Living entities and AI
- Entity parts and sensors
Assets and audio
- Assets
- Models and animations
- Built-in Minecraft models
- Model appearances
- Blockbench workflow
- Audio
- Texture-pack overrides
Events and world actions
World generation
World systems
Inventories and screens
Recipes