Skip to content

Server Script API

Liam Robinson edited this page Nov 8, 2026 · 1 revision

Server Script API

Every function a server script has (API level 1). Signatures are in Luau's type syntax; ? marks an optional argument or a result that may be nil. A wrong argument raises an error that names the function and the argument. Each call also needs its right in the server's ACL; the defaults allow every call except the seven marked privileged.

Scripts read what the server saw at the last tick and queue orders; no call waits on the server, and no call moves a rider: the riding is the players' and the server's checks', never a script's.

Globals

Name What
root the root element; a handler on it hears every element's events
resourceRoot this resource's own root element
source in a handler: the element the event was raised on
this in a handler: the element the handler is attached to
eventName in a handler: the event's name
client in a handler of a remote event: the player whose game sent it; otherwise nil
exports exports(name, fn) offers a function; exports.res:fn(...) calls one (Events and Messages)

Resource, timers, commands, settings

Function What
getResourceName(): string this resource's name
setTimer(fn, interval: number, times: number, ...): Timer calls fn(...) every interval ms (50 ms to 24 h), times times; 0 = until killed
killTimer(timer): boolean, isTimer(value): boolean stops one of this resource's timers; tells whether a value is a live timer
addCommandHandler(name, handler): boolean a console command: a-z 0-9 _, at most 32 characters. The handler gets (player, command, ...args); player is nil from the console or the remote console
removeCommandHandler(name, handler?): boolean removes one handler, or all of the name
get(name): NetValue a value of [settings] in resource.toml
json.encode(value): string, json.decode(text): NetValue JSON, at most 1 MiB
storage.get(key): NetValue, storage.set(key, value) the resource's lasting store (Scripting Overview); nil deletes

Elements

Everything a script can point at is an element in one tree: the root, each resource's root, the players, the instances, the riders, markers, and elements scripts make.

Function What
createElement(type, id?): Element an element of your own type (A-Z a-z 0-9 _ -, at most 64) below resourceRoot. Types the game makes (player, rider, instance, marker …) are refused
destroyElement(element): boolean destroys one of your elements and everything below it
isElement(value): boolean whether a value is an element that still exists
getElementType(element): string, getElementID(element): string, setElementID(element, id): boolean type and id (set: your own elements)
getElementByID(id, index?): Element? the first (or index-th) element with that id
getElementParent(element): Element?, setElementParent(element, parent): boolean the parent (set: your own elements, below your root)
getElementChildren(element, type?): {Element}, getElementsByType(type, startAt?): {Element} children; all elements of a type
getRootElement(): Element, getResourceRootElement(): Element root, resourceRoot
setElementOwner(element, player?): boolean, getElementOwner(element): Element? lets a player's game use your element as an event's source and write its opened data keys

Element data

Function What
setElementData(element, key, value, sync?): boolean sets a value; sync is "broadcast" (default: every player's game), "subscribers" or "local" (never sent). nil removes it
getElementData(element, key): NetValue, hasElementData(element, key): boolean, removeElementData(element, key): boolean read, test, remove
setElementDataClientWritable(element, key, writable): boolean lets the owning player's game write that key (at most 64 keys per element)
addElementDataSubscriber(element, key, player): boolean, removeElementDataSubscriber(...) who receives a "subscribers" key

Events

Function What
addEvent(name, remote?): boolean declares an event; remote = true lets players' games raise it for this resource
addEventHandler(name, element, handler, propagate?): boolean handles an event on an element (and, with propagate, the default, on its parents and children)
removeEventHandler(name, element, handler): boolean
triggerEvent(name, source, ...): boolean raises an event here; false if a handler cancelled it
cancelEvent(): boolean, wasEventCancelled(): boolean in a handler: cancel; after triggerEvent: was it cancelled
triggerClientEvent(sendTo, name, source, ...): boolean raises a remote event in players' games: sendTo is root (everyone), an instance, a player, or a list of them
triggerLatentClientEvent(sendTo, name, bandwidth, source, ...): LatentHandle the same for up to 16 MiB, sent at bandwidth bytes a second (500 to 1 000 000)
getLatentEventStatus(handle): {total, sent, percent}?, cancelLatentEvent(handle): boolean, getLatentEventHandles(): {LatentHandle} follow, stop and list this resource's latent sends

The events themselves are on Events and Messages.

Players, instances, riders

Function What
getPlayers(): {Element} the connected players
getPlayerName(player): string?
getPlayerRider(player): Element?, getRiderPlayer(rider): Element? a player's rider once placed, and back
getPlayerInstance(player): Element? the instance (room) a player is in
getInstances(): {Element}, getInstance(instance): InstanceInfo? the instances; {id, mode, drop, state, round, clock}: drop is ssx:drop/<name> or the map's id, state lobby, loading, countdown, running or results, clock the round's ms
getStandings(instance): {ServerStanding} the round's order: {rider?, name, place, state, clock, points, split?}, state racing, finished, failed, left or invalidated
getRiders(instance?): {Element} all riders, or one instance's
getRiderState(rider): ServerRiderState? {name, number, progress, status, ping, position?, velocity?, speed?, split?, clock?, points?, finished} as the server last saw it
endRound(instance, reason?): boolean ends the round in its countdown or under way, as its time limit would; false when there is no such round

Markers and triggers

Function What
createMarker(id, position, options?): Element a marker of a marker content id (Content IDs and Kinds), drawn in every player's game. options: heading (degrees), size (0.1 to 100 m), color, visible, instance (only that instance's riders see and hit it)
createCheckpoint(id, position, index, options?): Element the same, numbered: a rider passing it raises onRiderCheckpoint
createTrigger(position, radius, instance?): Element an invisible upright cylinder; a rider crossing into it raises onMarkerHit on it
setMarkerPosition(marker, position), getMarkerPosition(marker): Vec3, setMarkerColor(marker, color), setMarkerVisible(marker, visible) change your own markers

A rider hits a marker along its path between two server ticks, so a fast rider cannot pass through one.

Sounds and notices

Function What
playSoundFor(to, id, position?): boolean plays a sound id in the games of to (root, instances, players), at a point if given
showNotice(to, title, text, seconds?): boolean shows the HUD's message panel to to

Joins

See Events and Messages for onPlayerConnecting.

Function What
deferJoin(join): boolean holds the join until this resource decides (at most 120 s)
acceptJoin(join): boolean releases this resource's hold. The player is let in when every resource that held the join accepted it
refuseJoin(join, reason): boolean refuses; the player sees the reason
updateJoin(join, text): boolean the line the player's connecting screen shows while held (at most 256 bytes)

Privileged calls

Each needs its right granted by the operator (Script Permissions). They return true, or false and the reason; the order is carried out after the tick.

Function What
kickPlayer(player, reason?): (boolean, string?) ends the player's connection
banPlayer(player, seconds?, reason?): (boolean, string?) bans the player's id and address (seconds 1 to 100 years; none: forever)
mutePlayer(player, seconds?, reason?): (boolean, string?) mutes the player's chat
startResource(name), stopResource(name), restartResource(name): (boolean, string?) as the console's commands
executeCommand(line): (boolean, string?) runs a console line; needs the line's command.<word> right too

Per tick at most one kick, ban and mute per player and 16 resource or command orders.

Function What
hasObjectPermissionTo(object, right): boolean whether a player or a resource's root holds a right, e.g. before acting for a player in your own admin commands

Types

type Vec3 = { x: number, y: number, z: number }
type NetValue = nil | boolean | number | string | Element | { [any]: any }

Positions are metres in the world's axes (y up). Colours are 0xAARRGGBB numbers.

Clone this wiki locally