Reset Terrain Live (Multiplayer)¶
Runtime approach for resetting modified voxels back to base terrain during a live multiplayer session. Reach for this recipe when a mod wants to wrap a selective terrain reset inside a lore-based event (reclamation event, visual effects, chat narration) rather than shutting the server down and editing the save offline.
When to use¶
- A live multiplayer session wants to reclaim terrain over time, in place, without taking the save offline.
- A mod wants to pair terrain reset with screen shake, dust particles, rumble sounds, or chat narration.
- The work can be spread across many ticks to avoid frame-rate hits.
For a one-shot offline reset against a closed .save archive, see ResetTerrainOffline.md instead.
Prerequisites¶
- Server-authoritative code path;
VoxelOctree.SetDensityruns on the server and the server propagates changes to clients through the normal voxel sync mechanism. - A source of truth for "which voxels should be reset": a queue of world positions, typically produced by a scan phase that walks
VoxelTerrain.Octreeand finds modified nodes outside a computed keep set.
Key runtime approach¶
For each voxel to reset:
- Convert world position to octree space.
- Read base-terrain density:
VoxelTerrain.ReadOnlyOctree.Get(octreePos)returnsNodeInfowith.densityand.nodeType. - Write it back:
VoxelTerrain.Octree.SetDensity(worldPos, baseDensity, ...). - This overwrites the delta with the base value. On next save, the node collapses (or at least is no longer meaningfully modified).
Process a few hundred voxels per tick to avoid lag. Sort the work queue by distance from base center (furthest first) for a dramatic "closing in" visual effect.
Verification¶
- Snapshot
VoxelTerrain.Octreestate around a reset voxel before and after theSetDensitycall: the delta should match the base-terrain density read fromVoxelTerrain.ReadOnlyOctree. - Save the world and reload it; confirm the reset region's terrain.dat shrinks and the reset voxels no longer appear as modified leaves.
- In a multiplayer session, confirm clients see the terrain update in their local view within the normal voxel sync window.
Pitfalls¶
- Batch work across ticks: processing the whole queue in a single tick spikes frame time. A few hundred voxels per tick is a reasonable default.
- Do not skip the
ReadOnlyOctree.Get(octreePos)step and write a constant density; different voxel columns have different base densities (stone vs rock vs regolith) and a constant would show through as visible striping. - Save / reload behavior depends on the node being written back to base density exactly. Near-base values that differ by float precision may still serialize as modified leaves.
Verification history¶
- 2026-04-20: page created from the Research migration; verbatim content lifted from F0242 (
Plans/SaveFixPrototype/plan.md:288-299).
Open questions¶
- Network sync: does
SetDensitypropagate changes to multiplayer clients automatically, or is there a separate network notification needed? Trace the call chain in the decompiledVoxelOctree.SetDensity(). - Mesh rebuild: does
SetDensitytrigger chunk mesh regeneration internally, or must the mod call a separate dirty / rebuild method? - Room access: how to get the list of
Roomobjects and theirGridsat runtime? Find the room manager singleton (likely onWorldManageror similar).