Skip to content

Diagnostics and Troubleshooting

Zaldaryon edited this page Aug 28, 2026 · 1 revision

Diagnostics and troubleshooting

WorldgenLib reports the assembled hooks and step list so a server owner can check the active pipeline before generating a large world.

Startup report

After the server has initialized WorldgenLib, print the hook report from a consumer or a diagnostic command:

foreach (var entry in WorldgenLibAPI.GetHookReport())
{
    api.Logger.Notification(
        "WorldgenLib hook {0} at {1} owned by {2}",
        entry.Step,
        entry.Order,
        entry.ModId);
}

api.Logger.Notification(
    WorldgenLibAPI.GetStepRegistry().GetVersionReport());

The report is useful for checking that a consumer registered before the freeze, that its order is the intended value, and that a terminal adapter is not registered alongside an equivalent atomic effect.

Common failures

Symptom Likely cause Action
IsLoaded is false WorldgenLib is missing, client-side, or not initialized Declare the server dependency and register from StartServerSide
WorldgenLib is not initialized Registration or sampling happened too early Wait for StartServerSide or worldgen initialization as documented
Cannot register ... after initWorldGen A hook, landform, or map slot was registered late Move registration to startup
BlockLayers inline seam unavailable The Vintage Story IL shape is unsupported Use the terminal adapter if appropriate, or wait for a compatible build
GetIndex returns -1 The code is absent or not yet imported Check the canonical code and registration timing
Duplicate landform or map code Two consumers claimed the same identifier Namespace the code or coordinate ownership
Region map budget exceeded Declared storage exceeds the 4 MiB per-region budget Reduce dimensions, padding, or the number of slots
Hook disappears after an exception WorldgenLib disabled that mod ID in the affected list Fix the exception or non-finite result and restart the worldgen session
WorldgenLib hooks are present but inactive A blocking foreign takeover was detected Read the conflict entry and remove the duplicate owner or choose a policy
Sampler throws before worldgen TerrainSampler is not initialized yet Query only after the worldgen host has initialized
SetFluid writes at the wrong height Local Y was used instead of global Y Pass global Y and let ColumnCarvingContext choose the vertical chunk
Saved custom map is empty The coordinate-only compatibility overload was used Use GetMap(IMapRegion, ...) and SetMap(IMapRegion, ...)

Numeric and exception handling

Numeric hooks must return finite values. A non-finite raise or threshold result disables the owning mod's registrations in that list. A thrown exception has the same isolation boundary. The remaining hooks continue, but the server log is the evidence that the consumer is no longer active.

Do not catch and hide exceptions inside a consumer hook. Log the input coordinates, step, and consumer state, then allow WorldgenLib to apply its isolation policy.

When output looks wrong

Check the pipeline in this order:

  1. Confirm the server loaded exactly one canonical terrain and map owner.
  2. Print GetHookReport() and compare every step and order with the consumer's intended policy.
  3. Check for disabled registrations and the first warning in the server log.
  4. Verify map mutations occur at the correct map stage and call TerrainSampler.InvalidateRegion after changing sampled landform data.
  5. Verify per-column hooks do not share mutable state without synchronization.
  6. Reproduce with a fixed seed and a no-consumer world.
  7. Test negative coordinates and terrain that crosses multiple vertical chunks.

If the output depends on which chunk generated first, the consumer probably relies on callback arrival order or writes shared state from a parallel column hook. Move that work to a region or finalization boundary.

Clone this wiki locally