Skip to content

API Worldgen Structure Lua

Piggo41 edited this page Sep 30, 2026 · 1 revision

Lua structure authoring and builder

Lua API / World generation / Structure documents / Lua authoring

Lua uses the same data model as JSON. Use a plain table when the document is already easy to read as data; use the builder when incremental mutation, loops, or helper functions make intent clearer.

Choosing an authoring form

Form Best for
JSON asset Static content, schema assistance, sharing with external tools, and data-only packages.
Plain Lua table Compact generated documents and reusable Lua modules where direct table syntax stays readable.
Builder Incremental construction, loops, conditional authoring, and named helper functions.
Compiled handle Validating once and reusing an immutable compiled structure in one or more registrations.

structures:add snapshots Lua input. Mutating the original table or builder after registration does not change an already registered structure.

Plain Lua table

local document = {
    palette = {
        stone = { block = 4, tags = { "structural" } }
    },
    elements = {
        {
            type = "fill",
            from = { -2, 0, -2 },
            to = { 2, 0, 2 },
            state = "stone"
        }
    },
    processors = {}
}

local platform = betamoon.worldgen.structures:add {
    key = "mymod:platform",
    template = document
}

Lua may omit format; BetaMoon inserts betamoon_structure. If format is supplied, it must have that exact value.

betamoon.worldgen.structures:builder(initial)

Creates a mutable table-backed builder. initial is optional and is copied, so nested source tables can be reused without sharing later mutations.

local builder = betamoon.worldgen.structures:builder {
    bounds = { min = { -4, 0, -4 }, max = { 4, 8, 4 } }
}

builder:state("stone", {
    block = 4,
    tags = { "structural", "weatherable" }
})

for x = -3, 3 do
    builder:block {
        pos = { x, 0, 0 },
        state = "stone",
        tags = { "foundation" }
    }
end

builder:processor {
    type = "decay",
    key = "edge_damage",
    select = {
        tags = { "weatherable" },
        excludeTags = { "foundation" },
        minExposedFaces = 2
    },
    chance = 0.08
}

The builder remains an ordinary visible Lua table. Advanced code may inspect or edit builder.palette, builder.templates, builder.elements, builder.processors, and builder.bounds directly. Helper methods copy the supplied definition and return the builder for chaining.

Methods

Method Behavior
state(name, definition) Sets palette[name].
block, fill, shell, frame, line, staircase Appends the matching element type.
cylinder, ellipsoid, voxelMap Appends the matching shape; voxelMap writes type voxel_map.
clear, replaceState Appends clear or replace_state.
template / use Appends a template-use element. Define reusable templates through builder.templates.
array, repeatElement Appends array or repeat.
chance, choice Appends conditional composition.
loot, marker Appends loot or marker elements.
processor(definition) Appends a root document processor.
compile() Validates immediately and returns an immutable compiled structure handle.
clone() Returns an independent deep-copied builder.

Call methods with : so the builder is passed as the receiver.

Programmatic templates

local builder = betamoon.worldgen.structures:builder()
builder:state("stone", { block = 4 })

builder.templates.pillar = {
    elements = {
        {
            type = "fill",
            from = { 0, 0, 0 },
            to = { 0, 4, 0 },
            state = "material"
        }
    }
}

builder:array {
    template = "pillar",
    at = { -3, 0, -3 },
    count = { 2, 1, 2 },
    step = { 6, 0, 6 },
    states = { material = "stone" }
}

This retains table-like readability while allowing a Lua loop or helper to construct any nested list or state map.

Compiling and cloning

local validated = builder:compile()

local first = betamoon.worldgen.structures:add {
    key = "mymod:first_ruin",
    template = validated
}

local variant = builder:clone()
variant:state("stone", { block = 48 })

compile() is useful when one generated document is registered more than once or when validation should happen at a specific point in initialization. A compiled handle is immutable and is not a general table.

Snapshot rules

Lua structure data must be serializable as one unambiguous JSON-compatible tree:

  • maximum nesting depth: 48;
  • maximum total values: 150,000;
  • numeric values must be finite and within -1,000,000 through 1,000,000;
  • arrays must be dense, one-based sequences;
  • one table cannot mix array indexes and object keys;
  • keys must be strings for objects;
  • functions, userdata, threads, metatables as data, and table cycles are rejected.

Empty tables are interpreted from their known field context—for example, an empty elements list or empty object where the document schema permits it.

Next: structure inventory loot.

Clone this wiki locally