Skip to content

Concepts

Zaldaryon edited this page Aug 28, 2026 · 1 revision

Concepts

One pipeline, ordered effects

WorldgenLib owns a canonical implementation of the server-side world-generation passes. It keeps vanilla initialization available, then exposes ordered delegates around the work that consumers need to change.

The model has three rules:

  1. A consumer registers an effect at a named step.
  2. WorldgenLib invokes all enabled effects in ascending order.
  3. Each effect sees the state produced by the earlier effects at that step.

An empty hook list follows a fast path. A frozen list is sorted by (order, registration index), so equal order values still have a stable result.

Atomic hooks and terminal adapters

Use an atomic hook when an effect can be expressed as a local change to a vanilla stage. Examples include changing landform weights, adding vertical distortion, selecting fresh water, changing a threshold, or carving blocks after placement.

Use a terminal adapter only when the consumer owns a complete pass that cannot be split without changing its semantics. A terminal hook returns true after it handled the request. Returning false allows the next terminal hook and then the WorldgenLib pass to run.

Terminal adapters are compatibility valves. They prevent a migration from forcing a consumer to reintroduce a competing Harmony replacement, but they do not make two complete replacements commutative. Prefer atomic hooks whenever the algorithm permits it.

Four hosts

Host Vanilla pass Scope Main extension points
GenMapsHost Region map generation One map region Nine map steps, generator wrappers, padding, region finalize, full-region adapter
GenTerraHost Terrain generation One chunk column Steps 0, 2, 4, 5, 7, 10, terrain finalize, full-terrain adapter
GenTerraPostProcessHost Floating-node cleanup One chunk column Opt-out and cleanup-rule hooks
GenBlockLayersHost Terrain layer placement One chunk column Raise modifier, sea-level filter, full BlockLayers adapter

Context scope

WorldgenLib uses the smallest context that fits each operation:

  • RegionContext carries a map region and the current map for a GenMaps stage.
  • ChunkContext carries chunk-wide terrain data and request-local state.
  • ColumnContext carries mutable per-column spans inside the terrain loop.
  • ColumnCarvingContext carries block access for post-placement column work.
  • MapGeneratorContext carries the inputs for a map-layer factory wrapper.

ColumnContext and ColumnCarvingContext are ref struct values. They cannot be stored, boxed, or used across an await boundary. This is intentional: the hot path does not allocate a context object for every column.

Configuration versus execution

The server lifecycle has a hard boundary:

AssetsFinalize
    -> runtime seam validation and host construction
StartServerSide
    -> consumer registration
InitWorldGen
    -> vanilla state settles, host state builds, lists freeze
Generation callbacks
    -> hooks execute in deterministic order
Dispose
    -> WorldgenLib restores captured vanilla globals and releases state

Landform registration, region-map declarations, and hook registration belong before InitWorldGen. Runtime callbacks should only read or transform the context they receive.

Determinism

For the same seed, world configuration, and registration set, effect order is stable. Consumers must not use wall-clock values, external random sources, unordered iteration in a generation result, or shared mutable state across columns. If a consumer needs expensive or cross-column work, compute it at a chunk or region boundary and read it from a context.

Clone this wiki locally