Builtin Library
README.md
captureArea
Area capture for the voxelEngine — flatten a region of the world plus
any intersecting VoxelShape entities into a single dense voxbin
record. The public entry point is Voxel.captureArea(opts) in
voxelEngine.module/init.luau; this module owns the implementation.
Capture always produces a DENSE record regardless of the source — they
are snapshots, not streaming worlds. That lets a consumer load the
capture via fromTemplate (live or baked) without needing chunked
decode plumbing. The dense size cap (Grid.MAX_DENSE_VOXELS) is
enforced up-front so pathologically large regions fail loudly instead
of OOMing the VM.
Palette merge: the returned palette is the union of every source
palette filtered down to entries that actually appear in the captured
cells. Entries are keyed by (name, color). Same name with a different
color is suffixed with the owning shape's entityId ("grass#ent_42")
so both stay distinct. The world's palette always wins for a given
name.
Exports
M.capture(opts: CaptureOpts?) -> CaptureRecord | CaptureResult— perform the capture. Whenopts.saveAsis set the function returns{ record, path }; otherwise it returns the record directly.
Types:
Vec3 = { x: number, y: number, z: number }BoxSelector = { min: { number }, max: { number } }SphereSelector = { center: { number }, radius: number }CaptureOpts = { box?, sphere?, includeWorld?, includeShapes?, wholeShapes?, shapeFilter?, blockSize?, saveAs? }CaptureRecord = { kind, chunked, hasCustomData, size, blockSize, palette, grid }CaptureResult = { record: CaptureRecord, path: string }
Usage
local CaptureArea = require("@builtin::systems.voxelEngine.voxelEngine.captureArea")
-- Box selector:
local rec = CaptureArea.capture({
box = { min = { 0, 0, 0 }, max = { 16, 16, 16 } },
})
-- Sphere selector + save:
local saved = CaptureArea.capture({
sphere = { center = { 0, 0, 0 }, radius = 8 },
saveAs = "demo_snap",
})
Notes
- Exactly one of
box/spheremust be set; passing both (or neither) is a hard error. includeWorlddefaults to true;includeShapesdefaults to true;wholeShapesdefaults to false (shapes get clipped to the capture AABB unless this is on).shapeFilter(ent, id) -> booleanlets callers reject specific shapes. Filter errors are treated as rejection so a broken filter never silently includes shapes you meant to exclude.blockSizeresolution order: caller-provided >VoxelWorld.blockSizefirst included shape's
blockSize>Config("defaultBlockSize").- The play-mode write gate refuses
saveAsunlessConfig.set("allowPlayWrites", true)or the[voxel]world settings override is on. - Capture records carry
kind = "capture"; consumers that distinguish shapes from captures (e.g.Voxel.fromTemplate) read this field.