Skip to content

API Worldgen Structure Processors

Piggo41 edited this page Sep 30, 2026 · 1 revision

Structure processors and selectors

Lua API / World generation / Structure documents / Processors

Document processors transform the resolved symbolic structure before palette variants are selected and before any world blocks are inspected. Use them for material themes, weathering, decay, erosion, and attached surface details.

Processing order and snapshots

{
"processors": [
  {
    "type": "replace",
    "key": "mossy_weathering",
    "select": { "tags": ["weatherable"] },
    "chance": 0.65,
    "pattern": { "type": "noise", "scale": 3, "threshold": 0.42 },
    "with": "mossy_stone"
  },
  {
    "type": "decay",
    "key": "missing_exposed_stones",
    "select": {
      "tags": ["weatherable"],
      "excludeTags": ["foundation"],
      "minExposedFaces": 2
    },
    "chance": 0.08
  }
]
}

Processors run in declaration order, and each sees the symbolic result left by earlier processors:

  • recolor, replace, and decay calculate eligibility from one snapshot before applying their changes.
  • erode takes a new snapshot for every iteration, so newly exposed cells can participate in the next pass.
  • deposit reads one snapshot and resolves competing additions deterministically before writing them.
  • no document processor reads surrounding world terrain or existing world tile entities.

Processor definitions

recolor

{
  "type": "recolor",
  "key": "reinforced_base",
  "select": { "tags": ["foundation"] },
  "map": {
    "stone": "reinforced_stone",
    "mossy_stone": "reinforced_mossy"
  }
}

recolor is deterministic and accepts exactly one of with or a nonempty map. It does not accept chance or pattern. With map, selected states absent from the map remain unchanged.

replace

{
  "type": "replace",
  "key": "cracked_walls",
  "select": { "states": ["wall"], "exposed": true },
  "chance": 0.25,
  "with": [
    { "state": "mossy_wall", "weight": 4 },
    { "state": "cracked_wall", "weight": 1 }
  ]
}

replace writes one state or independently selects from a weighted state list at each eligible coordinate. Target selection uses a random stream separate from eligibility, so changing target weights does not change which cells were selected.

decay

{
  "type": "decay",
  "key": "broken_upper_wall",
  "select": { "tags": ["wall"], "height": { "min": 3 } },
  "chance": 0.12
}

decay removes authored cells. It does not place air, so the existing world block at that coordinate remains untouched during placement. Cells removed by one decay pass do not expose and select additional cells during that same pass.

erode

{
  "type": "erode",
  "key": "rounded_damage",
  "select": { "tags": ["weatherable"], "minExposedFaces": 1 },
  "iterations": 2,
  "chance": 0.18
}

erode removes the complete selected set together, then recalculates exposure for the next pass. iterations defaults to 1 and accepts 1–16.

deposit

{
  "type": "deposit",
  "key": "wall_growth",
  "select": {
    "tags": ["wall"],
    "faces": ["north", "east", "south", "west"],
    "exposed": true
  },
  "chance": 0.15,
  "with": "vine",
  "distance": 1,
  "onConflict": "skip"
}

Deposit considers every eligible exposed face. It writes at exactly distance cells outward and does not fill cells between source and target. A horizontal target receives its depositing face as its authored orientation for metadata transformation.

onConflict applies when the destination already contains a symbolic cell:

Value Behavior
skip Leave the occupied target unchanged. This is the default.
error Reject the resolved structure placement.
replace Replace the occupied target unless it is protected.

Several sources targeting one empty coordinate are resolved deterministically. A protected cell may act as a deposit source because deposit does not modify that source. A protected target is skipped unless allowProtected = true.

Selector fields

{
"select": {
  "states": ["wall", "pillar"],
  "excludeStates": ["reinforced_wall"],
  "tags": ["weatherable", "exterior"],
  "match": "all",
  "excludeTags": ["foundation", "protected_detail"],
  "height": { "min": 2, "max": 8 },
  "minExposedFaces": 1,
  "nearMarker": { "name": "entrance", "distance": 4 },
  "excludeMarkers": ["terrain_support"]
}
}
Field Behavior
states Include the listed symbolic states. Omitted means any state.
excludeStates Independently excludes listed states.
tags Include cells with matching effective palette or element tags.
match any by default; all requires every positive tag. It does not change exclusions.
excludeTags Independently excludes any cell with one of these effective tags, even when tags is omitted.
bounds Inclusive local { min, max } selection box.
height Inclusive local Y { min?, max? }, each from -127 through 127.
faces Requires at least one listed exposed face. For deposit, it also limits deposit directions.
exposed true requires at least one exposed face; false requires none.
minExposedFaces, maxExposedFaces Inclusive exposure count from 0 through 6.
nearMarker Requires a marker name within Manhattan distance 0–32; optional value must also match.
excludeMarkers Excludes cells occupied by one of the listed marker names.

All supplied selector tests are combined: state, tag, bounds, height, exposure, marker proximity, and exclusions must all pass. Exposure and faces inspect current symbolic neighbors, not world air or terrain.

Patterns

Patterns are an additional eligibility gate. When both chance and pattern are present, both must pass.

Pattern Fields Behavior
independent None Adds no spatial correlation. chance remains the per-cell probability.
noise scale = 3, threshold = 0.5 Produces smooth 3D regions. A higher threshold selects less volume.
clusters radius = 2, density = 0.2, falloff = 0.65 Seeds bounded clusters, then thins cells progressively toward each radius.
{
"pattern": {
  "type": "clusters",
  "radius": 3,
  "density": 0.25,
  "falloff": 0.7
}
}

Protected geometry

Unless allowProtected = true, processors do not modify cells that:

  • have an effective protected tag;
  • resolve through a palette state whose possible variants include a tile-entity block or typed tile data;
  • are targeted by a tile_data/data marker;
  • are targeted by a structure loot element;
  • carry a connector marker;
  • carry a terrain_support marker.

The palette check protects the symbolic cell when any weighted variant requires a tile entity, so protection does not depend on which variant would later be selected. These semantic protections apply without requiring authors to add the protected tag. Use that tag for additional load-bearing or gameplay-significant geometry.

allowProtected is an explicit advanced escape hatch and applies to both tagged and automatically protected cells; selectors should still be narrow. If an allowed processor removes or replaces an inventory block while a loot element remains at that coordinate, structure planning rejects the incompatible result rather than placing a partial structure.

Processor key values must be unique stable lowercase identifiers. The same world seed and placement reproduce the same processor output regardless of chunk generation order.

Next: Lua structure authoring and builder.

Clone this wiki locally