Bundle IO¶
Bundle code runs in a sandbox, there is no direct access to the operating system of the machine it runs on. Everything a bundle exchanges with the world outside its component happens through explicit IO channels provided by the realm. Two channels exist today:
- Console output - Text your code writes to stdout/stderr, captured into the client or server console and logs
- File access through the VFS - A host folder that gets mounted virtually into the sandbox of the server-side component
Console output works in both realms, the VFS is currently limited to the server-side.
Console output¶
Anything your component writes to the console is captured by the script host and
routed into its log. Console.WriteLine and Console.Error.WriteLine
work from both the server-side and the client-side component.
Each captured line is logged under a module tag made of the script:
prefix and your bundle's name (the bundle folder name):
Console.WriteLine($"Player {playerName} joined from {userid}");
Console.Error.WriteLine("Something went wrong while saving");
produces:
[script:example-bundle] Player Alex joined from 987654
[script:example-bundle] Something went wrong while saving
- The line appears in the hosts log file and console output. In the console, the module tag is colorized. The color is derived from the tag, so every line of the same bundle shares one color
- The trailing line break is stripped. Log entries are always single-line
entries with the tag prepended. Prefer whole messages via
WriteLineover building output from manyWritecalls - Every line is written to the console and flushed to the log file immediately
The script:<bundle name> tag is what you search for when filtering a
log file for one bundle's output.
Warning
Logging comes at a cost. Currently the log is flushed immediately, so that crashes will indicate what happened just before. This also means that logging in hot loops can degrade performance
VFS¶
The VFS is the file area of a bundle on the server. When enabled,
the script host takes the bundle's vfs/ folder (the one next to config.toml)
and mounts it into the sandbox of the server-side component as the file
system root. Server code then reads and writes real files in that folder
with ordinary .NET file APIs, using relative paths:
// Server side. Relative paths resolve against the sandbox root, which is
// the bundle's vfs folder on disk.
const string BansFile = "bans.json";
string LoadBans()
{
return File.Exists(BansFile) ? File.ReadAllText(BansFile) : "[]";
}
void SaveBans(string data)
{
File.WriteAllText(BansFile, data);
}
Subfolders work the same way:
Enabling and location¶
- Turn it on with
enable_vfs = truein the[Scripting]section of the manifest (see Bundle Config). Without it the server component has no file system - The realm creates the
vfs/folder automatically when the bundle starts if it does not exist yet - On the server's disk the folder lives inside the bundle's folder under
the server's
data/ugcdirectory. For a bundle at the top level that isdata/ugc/<bundle name>/vfs/. Server owners can inspect it, back it up, and pre-seed it with files while the server is stopped - Each bundle gets its own
vfs/folder. A bundle only sees its own vfs. File system access never reaches outside the mounted folder
What it is for¶
The VFS is where server-side code keeps state that has to survive on the server. Runtime configuration read at startup, persisted data such as ban lists, saved tracks and structured log output the bundle may want to write itself. The folder is not streamed to clients. A bundle restart does not clear the files inside the folder.
Scope and limits¶
- The VFS belongs to the server realm. Client-side components currently have no file system mounted
- Writes are real disk writes on the server's machine. Write when state changes or at sensible intervals, not every tick, and keep an eye on how much data you accumulate