feat(scripting): boot a side-aware lua vm with documented bindings and pack loading #11
No reviewers
Labels
No labels
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
scope/assets
scope/client
scope/networking
scope/renderer
scope/scripting
scope/server
scope/shared
scope/workspace
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Synvael/synvael!11
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/scripting-vm"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What does this PR do?
I replaced the placeholder
scriptingcrate with a working Lua runtime that the base game and mods will load through.ScriptVm(vm.rs) owns onemlua::Luastate for one world session and oneSide,ServerorClient. It opens the safe standard libraries minuspackage, creates the globalsynvaeltable, and starts in a load phase thatScriptVm::finish_loadends. All state lives in theLuastate, so dropping the VM leaves nothing behind for the next session.api::func(api.rs) is the builder every Lua-exposed function goes through. It takes.doc(),.param(),.returns(),.since(),.server_only()and.load_only(), andbuildinstalls the function at its dotted path undersynvaelwhile recording aFunctionDocon the VM.buildfails withScriptError::MissingDocwhen.doc()or.since()is missing, and withInvalidPathorPathTakenfor bad or occupied paths. A server-only function is not installed on a client VM, but its doc is recorded on both sides. A load-only function raises a Lua error afterfinish_load.load_pack(pack.rs) runs<pack_root>/scripts/init.luaas the pack's only entry point and treats a missing file as a pack with no Lua tier. It installs a replacementrequirethat resolves<pack_id>.a.bto<pack_root>/scripts/<pack_id>/a/b.lua, caches results per VM, rejects module names that start with another pack's id, and only accepts text chunks.require("synvael")returns the API table.synvael.log.info,.warnand.error(log.rs) forward totracingwith the loading pack's id in apackfield. The globalprintis the same function assynvael.log.info.ScriptError(error.rs) is the crate'sthiserrorerror type.assets/scripts/core.luatoassets/scripts/init.luaso the base game pack follows the same entry point rule.docs/scripting.mdfor the VM lifecycle, the builder, side gating, pack loading and logging, and indexed both indocs/README.md.Why is this change necessary?
ADR-0006 puts the base game on the same Lua API that mods use, and nothing could run a script yet. The crate held a placeholder
addfunction. Content registration, side-gated APIs and the modding tier all need a VM with a defined lifecycle and one way to expose functions before any of them can start.The dialect had to be settled first because every published mod is written against it. ADR-0016 picks PUC Lua 5.4 over Luau for instruction-count hooks (per-mod CPU budgets), native integers, and the existing LuaCATS type pipeline.
Routing every binding through the builder keeps the API reference generated from the same place the functions are installed, so a function cannot reach Lua undocumented.
Scope of Changes
scripting, workspace, assets
Testing
Automated, all run on the branch head:
cargo check -p scripting: passed.cargo test -p scripting: 12 passed, 0 failed. The tests cover side gating and doc recording on both sides, the missing doc and path errors, load-only functions failing afterfinish_load, pack-rootedrequirewith caching and cross-pack rejection, a pack withoutinit.lua, script errors propagating out ofload_pack, a dropped VM leaving no globals, docs or cached modules for the next one, andprintbeingsynvael.log.info.cargo clippy --all-targets --all-features -- -D warnings: passed.cargo fmt --all -- --check: passed.stylua --check assets/scripts/ mods/andselene assets/scripts/ mods/: passed, 0 errors and 0 warnings.No manual or in-game verification. Neither
clientnorserverdepends onscriptingyet, so there is no running game path that creates a VM.Additional Context
The scripting surface is public modding contract from here on: the
synvaelroot table,requirenaming,scripts/init.luaas the entry point, andsynvael.log.The trust boundary is only structural so far. Server-only functions are absent on the client,
packageis not loaded and bytecode is rejected, butdebugandloadare still available, there is no per-pack environment and no CPU budget. Outsideload_packthepacklog field is empty until per-pack environments exist.mluais built without itssendfeature, soScriptVmis!Sendand stays on the thread that created it.The last commit drops the
docs/README.mdrule requiring every subsystem note to name its design topic.docs/scripting.mdis the first note written without that line.Related Issues
None.
Checklist
dev(or a feature branch offdev) and my PR targetsdev.///doc comments for Rust) where necessary.