Repository navigation
Server Resources
A resource is a package the server runs and sends to its players: scripts, maps, gamemodes, textures, sounds and
any other content a mod can hold. Players' games download a server's resources when they join and
use them only on that server. A resource is the same kind of package as a mod, with a resource.toml at its root
(Resource Packages).
Put each resource in the resources folder of the data folder, as a folder or a .zip:
| Linux | Windows | |
|---|---|---|
| a folder | data/resources/welcome/resource.toml |
data\resources\welcome\resource.toml |
| a zip | data/resources/welcome.zip |
data\resources\welcome.zip |
The folder or zip name is the resource's name and must match name in its resource.toml. Another folder:
[resources] folder in server.toml.
Name the resources to start in server.toml, in order:
[resources]
start = ["welcome"]A resource's requirements ([dependencies] require) start before it. A resource in start that cannot be read or
checked stops the server from starting, with the reason.
When a resource starts, the server:
- reads it with the same strict checks a player's install uses: the manifest, every file it names, every kind's limits (Mod Limits);
- refuses it if it holds something a server may not send: shaders (GPU code), Flash movies (
.swf,.gfx), or a file whose bytes are a file of the game's disc; - refuses it if a blocklist names one of its files;
- copies it to
resource-state/installed/. The copy is what runs: editing the source has no effect untilrestart; - runs its server scripts and offers every other file to the players.
What players receive: every file of the package except the files matched by [scripts] server and
[files] server_only. Server scripts never leave the server.
| Command | What it does |
|---|---|
start <name> |
starts a resource (its requirements first) |
stop <name> |
stops it, and every running resource that requires it |
restart <name> |
reads it again from the folder and restarts it; if the new copy fails its checks, the running one stays |
ensure <name> |
starts it, or restarts it if it runs |
refresh |
lists the resources whose files changed on disk |
scripts |
the server scripts' monitor (time, memory, events, timers per resource) |
The commands are queued (at most 64 waiting) and run one at a time. Players who are connected follow every change: their games download what changed and drop a stopped resource. A change a player's game cannot follow (a download that fails, a level whose content now differs) ends that player's session with the reason.
The welcome resource greets each player, counts the visits across restarts, has a console command and draws a
line on the players' screens. Its files:
welcome/
resource.toml
server/main.luau
client/hud.luau
lib/visits.luau
resource.toml:
[resource]
name = "welcome"
version = "1.0.0"
title = "Welcome"
authors = ["Your Name"]
description = "Greets every player, counts the visits and shows a line on screen."
api = 1
type = "script"
[scripts]
server = ["server/*.luau"]
client = ["client/*.luau"]
[files]
server_only = ["lib/**"] # the visit counter never leaves the server
[settings]
greeting = "Welcome to the mountain"lib/visits.luau, a module the server script loads with require:
-- A module: every script that requires it gets the same table.
local visits = {}
function visits.add(): number
local total = (storage.get("total") or 0) + 1
storage.set("total", total)
return total
end
function visits.total(): number
return storage.get("total") or 0
end
return visitsserver/main.luau:
local visits = require("lib/visits")
-- clients may raise this event (remote = true); only this resource takes it
addEvent("welcome:hello", true)
addEventHandler("onResourceStart", resourceRoot, function()
print("welcome: started; " .. visits.total() .. " visits so far")
end)
addEventHandler("onPlayerJoin", root, function()
local name = getPlayerName(source) or "rider"
local number = visits.add()
print("welcome: " .. name .. " joined, visit " .. number)
showNotice(source, get("greeting"), name .. ", you are visitor number " .. number, 6)
end)
addEventHandler("onPlayerQuit", root, function(reason)
print("welcome: " .. (getPlayerName(source) or "rider") .. " left (" .. reason .. ")")
end)
addEventHandler("welcome:hello", root, function(text)
-- `client` is the player whose game sent the event
print("welcome: " .. (getPlayerName(client) or "rider") .. " says " .. tostring(text))
triggerClientEvent(client, "welcome:reply", root, "Hello back from the server")
end)
-- a console command: type `visits` in the server's console
addCommandHandler("visits", function(player, command)
print("welcome: " .. visits.total() .. " visits in all")
end)client/hud.luau:
local line = "Welcome!"
addEvent("welcome:reply", true)
addEventHandler("welcome:reply", root, function(text)
line = text
end)
addEventHandler("onClientResourceStart", resourceRoot, function()
-- a client's event names its own player as the source
if localPlayer then
triggerServerEvent("welcome:hello", localPlayer, "hi")
end
end)
addEventHandler("onClientRender", root, function()
draw.rect(20, 640, 420, 44, tocolor(0, 0, 0, 160))
draw.text(line, 34, 650, tocolor(255, 255, 255), { size = 20, shadow = true })
end)With start = ["welcome"], a player joining and leaving, and visits typed in the console, the log shows (the
time stamps left out):
INFO avalanche_server::resources: resources: started welcome 1.0.0
INFO avalanche_server::resources: resources: welcome: its server scripts started
INFO avalanche_server::scripts::world: scripts: welcome: welcome: started; 0 visits so far
INFO avalanche_server::scripts::world: scripts: welcome: welcome: Snow Fox joined, visit 1
INFO avalanche_server::scripts::world: scripts: welcome: welcome: Snow Fox left (left)
INFO avalanche_server::scripts::world: scripts: ran visits
INFO avalanche_server::scripts::world: scripts: welcome: welcome: 1 visits in all
After a restart of the server the first line reads started; 1 visits so far: the count is kept in
script-data/welcome/storage.bin in the data folder. The scripting pages explain every call used here
(Scripting Overview).
Players download a resource's files from the server's TCP port. To take that load off the server, put the files on a web server and name it:
[resources]
files_url = ["https://files.example.org/avalanche/"]A mirror is a plain folder of files named by their content hash (64 hex digits, BLAKE3), the same names they have in
the server's resource-state/store/ folder: copy that folder's files whose names are 64 hex digits to the mirror
after every resource change. A player's game tries the mirrors in order, then the server itself. A file whose bytes
do not match its hash is thrown away and reported to the server (logged), and the next source is used.
Rules for a mirror address: http:// or https://, a host, an optional port and a path; no user name, query, %
escape or ./.. segment; at most 256 characters and 4 mirrors. A listed server's mirror at a private or local
address is not used by players (their games do not probe their own network for a server).
| What | Limit |
|---|---|
| resources per server | 256 |
| files across the server's resources | 65 536 |
| bytes across the server's resources | 8 GiB |
| the resources' manifest players download first | 8 MiB |
| one resource | the package limits on Mod Limits |
Players set the most they download for one server in the game's Options (2 GiB by default) and see the size before they agree (Joining a Server). Downloads are kept in a cache shared by all servers (8 GiB by default, the least recently used removed first), so a second visit downloads only what changed.
How players' own mods behave on your server is set in [mods]; see
Client Mods on Servers.
- A resource with shaders or Flash movies cannot be sent by a server.
- There is no tool in the release that copies the files to a mirror for you; copy the store's files by hand.
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