Repository navigation
Scripting Overview
Packages can carry scripts written in Luau, a fast, typed dialect of Lua 5.1. The API follows
Multi Theft Auto's (elements, element data, events, addEventHandler, triggerClientEvent) with ideas from FiveM
(join deferrals, exports, latent events), so most of it will look familiar if you know either.
| Side | Runs | Declared in resource.toml
|
|---|---|---|
| server | in the dedicated server, for a server resource | [scripts] server = ["server/*.luau"] |
| client | in each player's game: a server resource's client scripts on that server, or a mod's in single player | [scripts] client = ["client/*.luau"] |
| shared | on both sides, loaded before each side's own scripts | [scripts] shared = ["shared/*.luau"] |
Server scripts never leave the server. A client script runs only on the player's own game and is never trusted by the server: anything it sends is checked there.
A gamemode package's server scripts also run in single player: the game starts a local script host for the gamemode when you ride it from the Maps page, so a gamemode plays the same alone and on a server.
- Each pattern names
.luaufiles; files run in pattern order, then by path. A file matched twice runs once. -
Every script has its own globals. A global one script sets is not seen by another script, even in the same
package. Share state through a module:
require("shared/state")runs that file once and gives every script the same value it returned. -
requiretakes a path from the package root without the extension. On the server every.luaufile of the package can be required; on a client only files the client receives (not[scripts] server, not[files] server_only). - Files ending in
.d.luauare type definitions, never run. -
resource.toml'sapi = 1is the API level the package needs. A game or server with a lower level refuses it.
Scripts get Luau's coroutine, table, string, utf8, bit32, math and buffer libraries; from os only
clock, time and date; from debug only traceback. There is no file, process or network access: io,
os.execute, getfenv and setfenv do not exist. loadstring compiles text into the
calling script's own environment. print goes to the package's output:
| Side | Where print and errors appear |
|---|---|
| server | the server's log: scripts: <package>: <line>, the whole line up to 4 096 bytes (a longer one is cut there and says how much was cut); control characters are shown escaped |
| client | the game's log (the terminal it was started from; game.log in your Project Avalanche folder when the launcher started it), and the script monitor (F9) |
A script that errors in a handler is noted with its traceback; the other handlers still run. A script that breaks a limit below stops its whole package, with the reason in the output.
Every call into a script is counted and cut off when it runs too long, so no script can freeze the game or the server.
| What | Client | Server |
|---|---|---|
| one call (an event handler, a timer, an export) | about 10 ms of work (250 000 checkpoints), at most 80 ms of CPU time | about 50 ms (1 250 000 checkpoints), at most 400 ms |
| one call with everything it calls | twice that | twice that |
| all scripts of a side per tick | 2 ms | 4 ms (work beyond it waits for the next tick) |
| one package per tick | 50 000 checkpoints; over that 30 ticks in a row stops it | 100 000 checkpoints; likewise |
| memory per side | 64 MiB | 256 MiB |
| What | Limit |
|---|---|
| script files per side and package | 256, each at most 1 MiB, 4 MiB in all |
| running packages | 256 |
| elements per package; tree depth | 4 096; 64 |
| element data per package; one value | 16 384 keys, 4 MiB; 64 KiB |
| event handlers / declared events / timers / commands / exports per package | 1 024 / 512 / 1 024 / 128 / 256 |
| names: event 128, element type 64, element id 128, export 64, command 32, data key 128 bytes | |
| timer interval; timer arguments | 50 ms to 24 hours; 16 |
| events nested; export calls nested | 16; 8 |
| a value sent between the server and a client (strings up to 64 KiB, tables 16 deep, 256 values a table) | a remote event's arguments 64 KiB; a latent event 16 MiB |
a local event's or an export's arguments; json.encode / json.decode
|
1 MiB; 1 MiB |
| storage per package | client 1 024 keys, 1 MiB; server 4 096 keys, 16 MiB; one value 64 KiB |
a list result (getElementsByType …) |
65 536 elements |
| a command line | 1 024 bytes, 32 arguments |
Arguments of events, exports, element data and storage are copied as values: nil, booleans, numbers, strings,
elements, and tables of those (keys and values). Functions, coroutines and buffers never cross; a table that refers
to itself is refused.
resource.toml's [settings] table holds values the scripts read with get(name):
[settings]
greeting = "Welcome to the mountain"local text = get("greeting")storage.set(key, value) and storage.get(key) keep values across restarts, per package:
| Where | File |
|---|---|
| a server resource |
<data folder>/script-data/<resource>/storage.bin on the server |
| a client script on a server |
ScriptData/<server key>/<resource>/ in the player's Project Avalanche folder |
| a mod's client script in single player | ScriptData/local/<package>/ |
| a gamemode's server script in single player | ScriptData/local-server/<package>/ |
The store is written at most once a second and when the package stops. A key is 1 to 64 characters of
A-Z a-z 0-9 _ . -.
-
Server: the console's
scriptsprints each package's time, memory, events, timers, data and refused messages. - Game: F9 shows the client scripts' monitor over the game.
The game's repository has the API's type definitions for the luau-lsp language server:
Engine/crates/ssx-script/defs/ssx-api1-server.d.luau and ssx-api1-client.d.luau. Point your editor's luau-lsp at
the one for the side you write.
- Server Script API and Client Script API: every function.
- Events and Messages: events, the server–client channel, element data, exports.
- Script Permissions: what an operator must allow.
- Script Examples.
Servers
- Hosting a Server
- Server Configuration
- Ports and Firewalls
- Server Console
- Operators and Remote Console
- Access Control List
- Bans and Mutes
- The Server List
- Query and LAN Discovery
- Server Resources
- Blocklists
- Maps and Gamemodes
- Logs and Metrics
- Running as a Service
- Running in Docker
- Joining a Server
Scripting
- Resource Packages
- Content IDs and Kinds
- Scripting Overview
- Server Script API
- Client Script API
- Events and Messages
- Script Permissions
- Script Examples
Modding