In-world Luau scripting for prims: host, editor, and the vf* command set #38

Open
opened 2026-08-10 19:26:56 +00:00 by jeroen · 0 comments
Owner

Problem

Prims are static. There is no way to make one respond to a touch, move itself,
or say anything — the sim owns prim state (crates/simulator/src/state.rs) and
nothing can change it except a client edit.

Doing this needs three things settled: an engine whose runaway scripts can be
descheduled rather than killed, a per-region capacity budget so one author
cannot exhaust a region, and an editor — a script with no console is a text box
that swallows its own compile errors.

Approach

  • crates/simulator/src/scripting.rs — one sandboxed Luau VM per scripted prim
    on a dedicated OS thread, talking to the tick loop over channels. Scheduling is
    a per-region fuel bank spent round-robin, with set_interrupt returning
    VmState::Yield so an over-budget slice suspends and resumes (:445 strips
    require/loadstring; :505 sets the memory ceiling from the interpreter's
    measured baseline).
  • Schema V7: max_prims / max_scripts per region, and a prim_scripts table —
    source is not a PrimDto column, or every snapshot would carry it 20x/s.
  • crates/core/src/script_api.rs:99 — the 25-call catalogue, shared so the
    server implements and the editor documents one list.
  • crates/viberfox/src/systems/gui/script_editor.rs:229 — the panel, with the
    reference at :167 rendered from that catalogue.
  • Six new wire messages (protocol 13).

Acceptance criteria

  • A script survives a server restart and resumes without opening the editor.
  • while true do end suspends and stays resumable; neighbours still run.
  • A script cannot reach the filesystem, another prim, or the host.
  • A memory hog faults itself alone, with a readable error.
  • Compile errors reach the editor console naming chunk and line.
  • Touch fires on_touch; vfSay reaches local chat by distance.
  • Region capacity is pushed on connect and on every change.
  • The editor's reference cannot drift from the installed API (tested).

Verification

cargo test -p viberfox_simulator (31 unit + 8 integration over loopback TCP),
cargo test -p viberfox_core, cargo test -p viberfox, cargo check --workspace --all-targets, cargo fmt --check. All green.

Needs a workstation: the editor panel and its reference UI have never been
rendered — this container has no GPU. No cargo shots preset covers a panel.

Out of scope

  • Making vfSetPos durable horizontally. x/z re-derives from the geo anchor and
    the projection is client-side (prim_geo::place_geo_prims), so horizontal
    motion lasts until the map re-anchors. Fixing it changes every prim edit.
  • Inter-prim messaging, listeners, inventory, prim creation from a script.
  • A shared VM. One state per prim is ~386 KiB, so a 200-script region is ~75 MiB
    — fine now, and the number to revisit for thousands.

PR: https://code.garage44.eu/jeroen/viberfox/compare/main...feat/prim-scripting-luau


Branch: feat/prim-scripting-luau

## Problem Prims are static. There is no way to make one respond to a touch, move itself, or say anything — the sim owns prim state (`crates/simulator/src/state.rs`) and nothing can change it except a client edit. Doing this needs three things settled: an engine whose runaway scripts can be *descheduled* rather than killed, a per-region capacity budget so one author cannot exhaust a region, and an editor — a script with no console is a text box that swallows its own compile errors. ## Approach - `crates/simulator/src/scripting.rs` — one sandboxed Luau VM per scripted prim on a dedicated OS thread, talking to the tick loop over channels. Scheduling is a per-region fuel bank spent round-robin, with `set_interrupt` returning `VmState::Yield` so an over-budget slice suspends and resumes (`:445` strips `require`/`loadstring`; `:505` sets the memory ceiling from the interpreter's measured baseline). - Schema V7: `max_prims` / `max_scripts` per region, and a `prim_scripts` table — source is *not* a `PrimDto` column, or every snapshot would carry it 20x/s. - `crates/core/src/script_api.rs:99` — the 25-call catalogue, shared so the server implements and the editor documents one list. - `crates/viberfox/src/systems/gui/script_editor.rs:229` — the panel, with the reference at `:167` rendered from that catalogue. - Six new wire messages (protocol 13). ## Acceptance criteria - [x] A script survives a server restart and resumes without opening the editor. - [x] `while true do end` suspends and stays resumable; neighbours still run. - [x] A script cannot reach the filesystem, another prim, or the host. - [x] A memory hog faults itself alone, with a readable error. - [x] Compile errors reach the editor console naming chunk and line. - [x] Touch fires `on_touch`; `vfSay` reaches local chat by distance. - [x] Region capacity is pushed on connect and on every change. - [x] The editor's reference cannot drift from the installed API (tested). ## Verification `cargo test -p viberfox_simulator` (31 unit + 8 integration over loopback TCP), `cargo test -p viberfox_core`, `cargo test -p viberfox`, `cargo check --workspace --all-targets`, `cargo fmt --check`. All green. **Needs a workstation:** the editor panel and its reference UI have never been rendered — this container has no GPU. No `cargo shots` preset covers a panel. ## Out of scope - Making `vfSetPos` durable horizontally. x/z re-derives from the geo anchor and the projection is client-side (`prim_geo::place_geo_prims`), so horizontal motion lasts until the map re-anchors. Fixing it changes *every* prim edit. - Inter-prim messaging, listeners, inventory, prim creation from a script. - A shared VM. One state per prim is ~386 KiB, so a 200-script region is ~75 MiB — fine now, and the number to revisit for thousands. --- PR: https://code.garage44.eu/jeroen/viberfox/compare/main...feat/prim-scripting-luau --- Branch: `feat/prim-scripting-luau`
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jeroen/cartopolis#38
No description provided.