Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commitdd348ac6c3

README.md

voxelEngine

Public API for the voxel system. Single entry point for creating and editing voxel worlds and shapes. Tools and custom code call into here; nobody touches the VoxelWorld / VoxelShape components directly.

Two top-level concepts:

  • World — singleton entity carrying a chunked VoxelWorld grid. Created lazily on the first createWorld call, found by name later via world() / hasWorld(), destroyed with destroyWorld().
  • Shapes — per-entity dense or chunked VoxelShape grids. Spawned freely; each carries its own voxbin path on disk under Config.get("paths.shapes")/<entityId>.voxbin.

Templates are stored under Config.get("paths.templates")/<name>.voxbin and instantiated via fromTemplate. Captures (snapshots of a world region) land at Config.get("paths.captures")/<name>.voxbin.

Exports

Module-level:

  • M.world() -> Handle? — handle to the singleton VoxelWorld, or nil.
  • M.createWorld(opts: CreateWorldOpts?) -> Handle — create or reuse the singleton.
  • M.destroyWorld() — despawn the singleton world if it exists.
  • M.hasWorld() -> boolean — true when the singleton exists.
  • M.shape(name_or_id) -> Handle? — handle to an existing shape entity.
  • M.createShape(opts: CreateShapeOpts) -> Handle — spawn a new shape entity.
  • M.destroyShape(name_or_id) — despawn the shape entity if it exists.
  • M.fromTemplate(name: string, opts: FromTemplateOpts?) -> Handle — instantiate from paths.templates/<name>.voxbin. Supports live-link, detached, and memory-only modes.
  • M.saveAsTemplate(shape: Handle, name: string, opts: SaveAsTemplateOpts?) -> string — write a shape's grid as a named template.
  • M.listTemplates() -> { string } — enumerate template names (no extension).
  • M.deleteTemplate(name: string) — remove a template file.
  • M.copyTemplate(srcName: string, dstName: string) -> string — duplicate a template file.
  • M.captureArea(opts: CaptureAreaOpts) -> any — flatten a region of world + shapes into a dense voxbin record (and optionally save it).
  • M.scatter(templateName: string, opts: ScatterOpts) -> { Handle } — bulk-spawn instances across a region.
  • M.stamp(templateName: string, opts: StampOpts) -> Handle — single placement, either as a new entity (mode = "instance", default) or rasterised into the world grid (mode = "merge").
  • M.composite — re-export of the composite-prop module.
  • M._resolvePivot(value) -> { number, number, number }? — internal pivot helper, exposed for composite reuse.

Handle methods (returned by createWorld / createShape / fromTemplate / world / shape / scatter / stamp):

  • h:setBlock(x, y, z, name) / h:getBlock(x, y, z)
  • h:fillBox(min, max, name) / h:fillSphere(center, radius, name)
  • h:fillCylinder(p1, p2, radius, name) / h:fillLine(p1, p2, name)
  • h:clear() — clear every cell.
  • h:setPalette(palette) / h:addPaletteEntry(name, color)
  • h:bounds() -> Bounds? — inclusive bounds of every filled cell.
  • h:flush() — flush pending dirty-chunk remeshes.
  • h:save() — write the grid to the component's dataPath.
  • h:dirtyChunks() -> { any }
  • h:isLive() -> boolean / h:templatePath() -> string?
  • h:bake() -> Handle — break the live-link, copy into a private dataPath. Shape-only.
  • h:saveAsTemplate(name, opts) -> string
  • h:exists() -> boolean / h:destroy()
  • h:setPosition(x, y, z) -> Handle / h:getPosition() -> Vec3Map?
  • h:setRotation(r) -> Handle / h:getRotation() -> Vec3Map? (Euler radians, ZYX)
  • h:setParent(parentEntityId) -> Handle
  • h:copyRegion(min, max) -> any / h:pasteRegion(offset, regionData, opts)
  • h:mirror(axis) / h:translate(dx, dy, dz)
  • h:getNeighbors(x, y, z) -> any
  • h:queryRegion(min, max, opts) -> { any } / h:countByName(min, max) -> { [string]: number }
  • h:raycast(origin, dir, maxDist) -> any / h:sphereQuery(center, radius) -> { any } / h:lineQuery(p1, p2) -> { any }
  • h:clone(opts) -> Handle — shape-only. Detached duplicate.
  • h:snapToWorld(opts) -> Handle — quantise transform or shift voxel data to the world grid.

Types:

  • Vec3Map = { x: number?, y: number?, z: number? }
  • Vec3Array = { number }
  • Vec3Like = Vec3Map | Vec3Array
  • ColorMap = { r: number?, g: number?, b: number? }
  • ColorArray = { number }
  • ColorLike = ColorMap | ColorArray
  • PaletteEntry = { name: string, color: ColorLike, material: any?, atlas: any?, faces: any? }
  • Palette = { PaletteEntry } | { [string]: ColorLike }
  • Bounds = { min: Vec3Map, max: Vec3Map }
  • Handle = { entityId: any, componentName: string, [string]: any }
  • CreateWorldOpts / CreateShapeOpts / FromTemplateOpts / SaveAsTemplateOpts
  • CaptureAreaOpts / CaptureAreaBoxSelector / CaptureAreaSphereSelector
  • CloneOpts / SnapToWorldOpts
  • RegionSpec / ScatterOpts / StampOpts
  • QueryRegionOpts / PasteRegionOpts

Usage

local Voxel = require("@builtin::systems.voxelEngine")

-- Create the singleton world, write a couple of cells.
local world = Voxel.createWorld({
    size = { x = 64, y = 32, z = 64 },
    palette = { stone = { r = 0.5, g = 0.5, b = 0.5 } },
})
world:setBlock(0, 0, 0, "stone")
world:fillBox({ 1, 0, 0 }, { 3, 0, 3 }, "stone")

-- Spawn a shape from a template, live-linked to the template file.
local tree = Voxel.fromTemplate("tree", {
    position = { x = 10, y = 0, z = 5 },
})

-- Scatter 20 copies inside a region.
local hs = Voxel.scatter("tree", {
    region = { box = { min = { 0, 0, 0 }, max = { 50, 0, 50 } } },
    count = 20,
    snap = true,
})

-- Capture a region of world + shapes into a dense voxbin record.
local rec = Voxel.captureArea({
    box = { min = { 0, 0, 0 }, max = { 15, 15, 15 } },
})

Notes

  • Handles are thin wrappers over an entityId + a component name. Each method re-resolves the underlying component on every call, so the handle stays usable across hot-reload cycles.
  • All h:setBlock / h:fillBox / … calls forward to the component via colon-call (c:method(...)) — dot-call would drop self and the strict typed-function checker would read args from the wrong slots.
  • fromTemplate defaults to live = true + persist = true — live-linked instance that auto-bakes private edits to disk. Pass live = false for a detached copy with its own dataPath, or persist = false for a memory-only instance.
  • Voxel.scatter / Voxel.stamp (mode = "merge") obey the play-mode write gate enforced by assertModeAllowsWrite. In play mode, callers must toggle Config.set("allowPlayWrites", true) (or set the [voxel].allowPlayWrites WORLD_SETTINGS override) to unlock voxbin writes.
  • Voxel.stamp(mode = "merge") only supports yaw rotations of 0 / 90 / 180 / 270 degrees — voxel grids require axis-aligned stamps. Non-axis-aligned yaws raise.
  • The composite sub-module is reachable as Voxel.composite. It builds kitbashed .voxcomp props that re-resolve their children at instantiation time; fromTemplate transparently dispatches to it when the named template resolves to a .voxcomp manifest.