What scripts can and cannot do
Scripts run inside a restricted Lua environment with hard execution limits. This page states exactly what that means, including the parts that will occasionally be inconvenient.
Why there is a sandbox
A script you install from the marketplace is code written by a stranger, running on your machine, inside your game. The sandbox exists so that the worst a bad script can do is be a bad module: it cannot read your files, open a network connection, start a process, read another script, or reach into FluxWare past the functions documented here.
The limits below are not configurable and there is no way for a script to ask for more. That is the point of them.
There is also no way around them by arriving another way. Scripts come from your account's library and the client will not load Lua from anywhere else, so every public script has been through review. There is no second channel that skips it.
What Lua you get
Lua 5.2 (LuaJ 3.0.1). These standard libraries are available in full:
- base
- table
- string
- math
- bit32
Everything FluxWare adds on top is in the reference: the namespaces in the sidebar, plus the global module{} constructor.
What is removed
Each of these is absent from a script's environment. Referring to one gets you nil, not an error, so guard code that checks for them will simply take the other branch.
| Removed | Why |
|---|---|
| luajava | Reaches arbitrary Java by name, which would step straight outside everything else on this page. |
| io | No filesystem access of any kind. |
| os | Process and clock access. util.time() covers the only safe part. |
| package | No require. A script is one file; there is nothing to require. |
| coroutine | A LuaJ coroutine is a real Java thread and carries its own debug-hook state, so its body would run unbudgeted, on a new thread, inside a game frame. |
| load | Dynamic chunks, including binary ones that skip the parser entirely. |
| loadfile | Filesystem. |
| dofile | Filesystem. |
| debug | Installed internally to drive the instruction budget, then removed so a script cannot clear its own hook. |
| collectgarbage | Lets a script stall the client on demand. |
| string.dump | Emits binary chunks. |
Execution limits
Callbacks run on the game thread, in the middle of a tick or a frame. A script that loops forever would not be slow, it would be a frozen client. So every callback runs under an allowance and is stopped when it runs out.
| instructionsPerCallback | 200,000 |
| instructionsPerRenderCallback | 50,000 |
| instructionsForScriptBody | 2,000,000 |
| sourceBytes | 262,144 |
| errorsBeforeAutoDisable | 3 |
| errorWindowSeconds | 10 |
Exceeding an instruction budget stops the callback. pcall cannot catch it: the abort is deliberately not a Lua error, because a script that could catch its own budget violation inside a loop would hang the client.
In practice you will not meet these limits by accident. They are sized so that an honest overlay or a per-tick calculation has room to spare, and a runaway loop hits the wall in a fraction of a frame.
Scripts and bans
Worth saying plainly: the sandbox protects your machine, not your account. A script that sends chat, swings, or moves your player in a pattern a server considers suspicious can get you banned there, exactly as a badly configured built-in module can. Nothing in this environment prevents that, because from the server's point of view a script is just the client behaving.
Read what you install. The marketplace shows a script's full source before you install it, and that is there to be used. Review catches what a reviewer can see; it cannot tell whether a perfectly ordinary-looking combat script is one your server will tolerate.