Skip to content

API Worldgen Local Structures

Piggo41 edited this page Oct 16, 2026 · 4 revisions

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.

betamoon.worldgen.structures:add(definition)

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 definitions

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 versus placement processors

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 processor order

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 definitions

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 and directional blocks

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.

  • reject is the safe default for an unknown block with nonzero metadata.
  • preserve keeps the exact numeric value, which may leave that block facing in its original direction.
  • custom directional blocks should declare metadataTransforms rather than relying on preserve.
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.

betamoon.worldgen.structures:export(world, minX, minY, minZ, maxX, maxY, maxZ, options)

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
    }
)

Export option definitions

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.

Structure document reference

Examples: local structure package, fit-only complete worldgen pack, sunken cellar excavation, and authored excavation plus foundation.

Clone this wiki locally