Repository navigation
API Worldgen Local Structures
Lua API / World generation / Local structures
A local structure registers one bounded structure document as a reusable feature. It can be scheduled by a placement, used as a regional piece, selected by a structure-backed tree, or placed directly from an authoritative callback.
Loads and validates the document and returns a feature reference. Keys normalize to namespace:structure/path;
get returns nil when absent and getRequired raises an error.
local shrine = betamoon.worldgen.structures:add {
key = "mymod:shrine",
rotation = "random_horizontal",
mirror = "random",
terrain = {
mode = "foundation",
surface = "solid_surface",
maxSlope = 3,
foundation = {
footprint = { source = "base_bounds", shape = "rounded_bounds", cornerRadius = 2 },
edge = { type = "stepped", stepEvery = 1, maxExpansion = 1 },
material = "minecraft:cobblestone",
maxDepth = 6
}
},
processors = {
includeAir = false,
tileCollision = "reject",
unknownMetadata = "reject"
}
}| Field | Default / behavior |
|---|---|
key |
Required stable structure key. |
path |
assets/<namespace>/worldgen/structures/<key-path>.json. A custom value must itself begin with assets/, for example assets/mymod/worldgen/structures/special/shrine.json. |
template |
Inline plain Lua document, builder, or compiled handle. Mutually exclusive with path. |
rotation |
none; also clockwise_90, clockwise_180, counterclockwise_90, or random_horizontal/random. |
mirror |
none; also left_right, front_back, or random. |
processors |
Optional placement-time world interaction policies described below. |
terrain |
Exact placement when omitted; otherwise a terrain fitting policy. |
Structure files are gameplay data inside the directory or ZIP mod. They are not visual model assets and are not
replaced through texture-pack bm_assets/. JSON is strict UTF-8, unknown fields are rejected, and one file may be at
most 4 MiB. Local plans are bounded to 8192 block changes within radius 32 and never load neighboring chunks.
| Document processors | Placement processors |
|---|---|
Stored in the document's root processors array. |
Supplied to structures:add { processors = ... }. |
| Edit symbolic named states before palette variants are selected. | Decide how final blocks interact with the world. |
| Provide selectors, patterns, replacement, decay, erosion, and deposit. | Provide air inclusion, coarse decay, block substitution, collision policies, and metadata transforms. |
| Travel with the JSON or Lua document. | Belong to this registered use of the document. |
structures:add.processors.decay remains supported as coarse placement-time per-block decay. Prefer a document
decay or erode processor when selection by tags, height, exposure, or spatial pattern matters.
Placement selects a weighted palette variant, handles authored air, applies coarse decay and block substitutions, validates the existing world target, transforms metadata, and then initializes typed tile data.
processors = {
includeAir = true,
decay = 0.05,
replace = {
{ from = 4, to = 48 }
},
replaceOnly = { 0, 2, 3, 12, 13 },
tileCollision = "preserve",
unknownMetadata = "reject"
}| Field | Behavior |
|---|---|
includeAir |
False by default. When true, authored palette air clears an otherwise allowed world target. clear geometry is different: it removes symbolic cells before placement. |
decay |
Deterministic 0–1 probability of omitting each final authored block. It has no selector or spatial correlation. |
replace |
List of { from = block, to = block } substitutions applied to final structure blocks. |
replaceOnly |
Existing world blocks that may be changed. Encountering another block rejects the complete plan. |
tileCollision |
reject rejects the plan on an existing tile entity. preserve skips that one block position; it does not copy or merge the existing tile. |
unknownMetadata |
reject safely rejects unknown nonzero directional metadata during a transform. preserve keeps the number unchanged. |
metadataTransforms |
Custom directional metadata adapters for blocks not covered by built-in adapters. |
All checks remain atomic. A preserved tile position can still make a dependent loot target invalid, in which case the complete local transaction is rejected.
unknownMetadata is consulted only when rotation or mirroring is non-identity. Metadata zero is safe when no adapter
exists. Built-in adapters cover stairs, doors, rails, torches, ladders, levers, buttons, beds, furnaces, wall and
standing signs, dispensers, and pumpkins.
-
rejectis the safe default for an unknown block with nonzero metadata. -
preservekeeps the exact numeric value, which may leave that block facing in its original direction. - custom directional blocks should declare
metadataTransformsrather than relying onpreserve.
metadataTransforms = {
{
block = customMachine,
clockwise = { 1, 2, 3, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
leftRight = { 0, 3, 2, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
frontBack = { 2, 1, 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }
}
}Each supplied list maps input metadata indexes 0–15 to output metadata. Mirror mapping runs before repeated clockwise quarter-turn mapping. An omitted operation list acts as identity for that operation.
Captures a loaded cuboid from an authoritative callback and returns readable betamoon_structure JSON. It does not
write a file.
local json = betamoon.worldgen.structures:export(
ctx.world,
100, 60, 100,
108, 68, 108,
{
origin = { x = 104, y = 60, z = 104 },
includeAir = false
}
)| Field | Default / behavior |
|---|---|
origin |
{ x = minX, y = minY, z = minZ }; must be inside the selection. |
includeAir |
False; when true, air cells are emitted explicitly. |
The corners must already be ordered, Y must be 0–127, and X/Z extent may be at most 65 cells. The complete selected volume—not only emitted non-air blocks—may contain at most 8192 cells. Every intersecting chunk must already be loaded. The exporter captures block IDs, metadata, and typed BetaMoon tile data, but not arbitrary native or foreign-mod tile NBT. It emits simple block elements as an editable starting point.
- Document basics and palette
- Geometry elements
- Templates and conditional composition
- Processors and selectors
- Lua authoring and builder
- Structure inventory loot
- Terrain placement
Examples: local structure package, fit-only complete worldgen pack, 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