-
-
Notifications
You must be signed in to change notification settings - Fork 0
Concepts
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:
- A consumer registers an effect at a named step.
- WorldgenLib invokes all enabled effects in ascending order.
- 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.
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.
| 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 |
WorldgenLib uses the smallest context that fits each operation:
-
RegionContextcarries a map region and the current map for a GenMaps stage. -
ChunkContextcarries chunk-wide terrain data and request-local state. -
ColumnContextcarries mutable per-column spans inside the terrain loop. -
ColumnCarvingContextcarries block access for post-placement column work. -
MapGeneratorContextcarries 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.
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.
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.