Zone resource generation
This page explains how the server keeps a zone's resources stocked. Both systems run continuously in the background while the zone is loaded; nothing a player does is required for them to tick.
The zone's resource configuration
Each zone is configured in the database with two independent lists:
- Ore configuration (
mineralconfigs) — one row per ore type present in the zone, with four knobs per type:Column Meaning maxnodesHow many nodes of this type the zone maintains maxtilespernodeMaximum number of tiles a single node can cover totalamountpernodeTotal material in a fresh node, distributed over its tiles minthresholdMinimum per-tile fill ratio (0–1); tiles below it after mining are dropped - Plant configuration (
zones.fertility+ a plant rule set) — the zone's plant coverage target (a percentage) and the list of plant species allowed to grow there (each species' behaviour is a rule file, documented in Plants).
Zones without an ore configuration (arenas, training zones, strongholds, some gamma zones) have no ore layers at all.
Ore nodes
flowchart TD
A["Zone loads: count existing nodes of each type"] --> B{"Below maxnodes?"}
B -->|no| Z["Layer idle"]
B -->|yes| C["Pick a random passable tile,\nfurther than 2× the exclusion radius\nfrom any node of the same type"]
C --> D["Random walk: flood outward with a\n4-tile brush until maxtilespernode\nvalid tiles form one connected blob"]
D --> E["Spread totalamountpernode over the blob:\ntile share = normalized noise × total,\n±10% jitter"]
E --> F["Node is live: mined tile by tile;\nbelow 1% of its total it is deleted\nand a fresh node is generated"]
How a node is placed
When a zone loads, each ore type's layer counts its existing nodes (persisted in the
mineralnodes table) and generates new ones until maxnodes is reached. A new node is
placed by a random walk:
- Pick a random passable tile.
- It must be far from the nearest existing node of the same type — the exclusion
radius is derived from
maxtilespernode(√(maxtilespernode/π) × 2, then the start must be at least twice that away), so nodes never merge into one giant deposit. - From the start tile, a walk randomly floods outward (a 4-tile brush at a time),
collecting up to
maxtilespernodevalid tiles into one connected blob. - The node's
totalamountpernodematerial is spread over the blob: each tile's share is its (normalized) noise value times the total, with a ±10% random jitter, so no two nodes of the same type look alike.
A tile is valid for a node only if it is inside the zone, not an island, not PBS-terraform-protected, and passable. Two rare types get keep-out zones around docking bases and teleports: epriton keeps a minimum distance, and flux ore keeps twice that distance — so flux ore is never found right next to a base.
How a node is consumed
- Mining removes material tile by tile.
- A node that falls below 1% of its configured total is deleted, and a fresh node
is generated (back to step 1) to keep the zone at
maxnodes. - Flux ore nodes additionally drive NPC spawning — nodes being mined (or removed) publish events that the NPC system listens to, which is why flux ore sites get attention.
Plants
The plant scan
The zone is divided into 32×32 tiles. A plant handler walks these tiles in order, processing one per tick, paced so a full pass over the zone takes about 8 hours (overridable per zone). Each 32×32 "cube" is processed by a fixed pipeline:
- Validate — drop invalid plants (wrong ground, dead, out of place).
- Grow — advance each plant through its growth stages (see
gathering for
growRateand fruiting). - Spawn — add new plants where the cube is under its fertility target.
- Damage walls — plants' blocking height decays over time.
- Kill by distance — enforce same-type spacing (
killDistance). - Renew material — a small amount of fruit material regenerates.
How a new plant is chosen
A tile can only sprout if the zone file gives it spawn potential (a per-tile byte baked into the zone's plant layer — 0 means the tile never sprouts). On a tick, for each eligible tile:
- Zone fertility check first: if the cube's blocking-plant coverage already meets
fertility%of its ground tiles, nothing new spawns there. - Per-tile chance: a random roll must beat the tile's spawn potential.
- Species selection:
- If the tile has no plant neighbours, the species is a weighted random draw
where each allowed species' weight is its
fertility(player-seeded species are excluded from natural spawns). - If it does, it's a coin flip: 50% the currently ruling neighbour species
(the most common one nearby), 50% a spreading draw weighted by
(neighbour count × spreading)for each species — this is what makes clusters expand in their own kind.
- If the tile has no plant neighbours, the species is a weighted random draw
where each allowed species' weight is its
- Caps and spacing: a species with a
maxAmountcap is skipped once the zone has enough of it, and a tile withinkillDistanceof another plant of the same type is skipped.
What this means for players
- Plant density is bounded by the zone's fertility — you will never see a zone with 100% plant coverage if its fertility is 20.
- Clusters are the norm: spreading makes each species expand its own patches, so a zone tends toward species territories rather than a salt-and-pepper mix.
killDistancespecies (e.g. certain high-value plants) are evenly spaced, which makes their locations predictable once you find one.- New nodes appear wherever the random walk lands — there is no fixed "ore spot" on a zone; scanning is required (see gathering).