Lua API reference (node)
Generated from sdk/api.toml by sdk/tools/apigen.py docs. Do not edit; edit the schema.
This is the API a resource is written against. It lives in sdk/lua/prelude.lua, which the server runs into every resource’s Lua state on top of node.raw – the 1:1 mirror of the C ABI (Raw Lua reference (node.raw.*)), still there as the escape hatch. Signatures read node.ns.name(params) -> result; Player/Vehicle are objects (methods with :); a ? marks an optional parameter or a result that can be nil. A data argument that accepts a table is JSON-encoded for you; a payload documented as a table was JSON-decoded for you.
Guides: Getting started · Events · Concurrency · Wire events and clients · Recipes · Conventions
Contents
Заголовок раздела «Contents»- Top level: events, sending, timers, coroutines –
on,off,send,broadcast,after,every,cancel,defer,async,sleep,wait,yield,await,job,log - node.players – the roster –
get,all,count,ids,find - Player objects –
isConnected,refresh,kick,ban,verify,setStrict,send,sendModule,setRole,setGroup,vehicles,position,focus,headPose,camera,inputs,seat,unseat,swapWith,resync,tell - node.vehicles – the registry –
get,all,count,spawn,deleteAll,byTag,byTags,transforms - Vehicle objects –
exists,refresh,delete,transform,controls,inputs,electrics,powertrain,engine,controllers,couplers,nodes,breakGroups,paints,config,damage,sync,occupants,tag,setTag,removeTag,lock,unlock,lockState,setCoupler,trigger,resync,seat,setGroup - node.server – identity, limits, time, metrics –
name,setName,map,version,port,maxPlayers,setMaxPlayers,maxCars,setMaxCars,uptime,time,unixTime,metrics,snapshot,nodeGrabEnabled - node.bans –
add,remove,has,all - node.storage – persistent key/value –
get,set,delete - node.fs – files inside the resource folder –
read,write,writeAsync,list - node.http –
get,post,request,put,patch,delete,head,fetch - node.pg – PostgreSQL –
enabled,ready,query,exec,tx - node.json –
encode,decode - node.crypto –
sha256,hmac,randomBytes,randomHex - node.log –
warn,error,tag,custom,raw,sink,title - node.bus – between resources –
emit,on,off - node.modules – the binary channel –
on,off,send - node.relay – who sees what –
filter,unfilter,invalidate - node.resources and node.config –
reload,manifest - node.chat –
say,tell - node.commands –
add,remove
Top level: events, sending, timers, coroutines
Заголовок раздела «Top level: events, sending, timers, coroutines»What every resource uses every day sits directly on node: subscribing to events, sending to clients, timers, and the coroutine helpers. Handlers receive OBJECTS – a Player, a Vehicle – where the raw API has ids, and decoded tables where a payload is documented as JSON.
node.on(name, fn)
Заголовок раздела «node.on(name, fn)»Raw: node.raw.on
Subscribes fn to an event. The name decides what fn receives: engine events pass a Player or a Vehicle (or nothing for serverTick/serverShutdown); notifications and cancellable requests pass (player, vehicle, payload) with the payload decoded when it is JSON on the wire (the vehicle is left out where none is involved: playerConnectRequest, playerVerifyReported); any other name is a wire event from the client half and passes (player, data) with data as the string the client sent. A cancellable handler returns false[, reason] to deny. The events reference lists every name with its exact arguments. Several handlers per name are fine, across resources too; subscribing the same function twice replaces the first. A deprecated name (playerJoin, onPlayerConnectRequest, canRelay, …; the Formerly line of each event) subscribes to the same event as its canonical name and logs one warning per resource per old name (once per load: the once-table lives in the resource’s state, so a reload warns again) – so the same function under both spellings is one subscription, two different functions are two handlers.
node.off(name, fn?) -> number
Заголовок раздела «node.off(name, fn?) -> number»Raw: node.raw.off
Unsubscribes this resource’s handlers for the name – all of them, or only fn – and returns how many were removed. fn is the function that was given to node.on, matched by identity from any context, including coroutines (node.async, pg transaction bodies). A deprecated name is mapped like in node.on, so either spelling unsubscribes what either spelling subscribed.
node.send(target, event, data?) -> boolean
Заголовок раздела «node.send(target, event, data?) -> boolean»Raw: node.raw.emitClient
Sends a wire event to one player. target is a Player or an id; data is a table (JSON-encoded for you) or a string. false when the player is not connected. player:send is the same call.
node.broadcast(event, data?, except?) -> boolean
Заголовок раздела «node.broadcast(event, data?, except?) -> boolean»Raw: node.raw.emitAll, emitOthers
Sends a wire event to every connected player – or to everyone except one (a Player or an id), which is the shape of a relay: the excepted player counts as the sender for the relay filter and visibility groups. data is a table or a string.
node.after(ms, fn) -> number
Заголовок раздела «node.after(ms, fn) -> number»Raw: node.raw.setTimeout
Runs fn once after ms milliseconds on the worker thread; returns a timer id for node.cancel.
node.every(ms, fn) -> number
Заголовок раздела «node.every(ms, fn) -> number»Raw: node.raw.setInterval
Runs fn every ms milliseconds on the worker thread until cancelled; returns a timer id. A slow fn delays the next run; runs do not stack.
node.cancel(timerId)
Заголовок раздела «node.cancel(timerId)»Raw: node.raw.clearTimer
Cancels a timer from after or every. Safe for an id that already fired.
node.defer(fn)
Заголовок раздела «node.defer(fn)»Raw: node.raw.setImmediate
Runs fn after the current batch of handlers has finished – the way to act once every other handler of the event you are in has seen it.
node.async(fn, ...) -> number
Заголовок раздела «node.async(fn, ...) -> number»Raw: node.raw.async
Runs fn(…) as a cooperative coroutine on the worker and returns its task id. Inside it node.sleep, node.wait, node.await, node.yield and node.http.fetch suspend the coroutine while everything else keeps running.
node.sleep(ms)
Заголовок раздела «node.sleep(ms)»Raw: node.raw.sleep
Suspends the current coroutine for ms milliseconds. Only inside node.async.
node.wait(msOrPredicate, intervalMs?)
Заголовок раздела «node.wait(msOrPredicate, intervalMs?)»Raw: node.raw.wait
A number sleeps; a function suspends the coroutine until it returns truthy, polled every intervalMs (default 50). Only inside node.async.
node.yield()
Заголовок раздела «node.yield()»Raw: node.raw.yield
Gives the worker back for one turn inside a long loop that must run on it. Fairness, not parallelism. Only inside node.async.
node.await(workFn, args?) -> any, string?
Заголовок раздела «node.await(workFn, args?) -> any, string?»Raw: node.raw.await
Runs a SELF-CONTAINED function (no upvalues, no node, JSON-serialisable args and result) on a background pool thread and suspends the coroutine until it returns; gives back the result, or nil plus an error. Only inside node.async.
node.job(workFn, args?, doneFn) -> boolean
Заголовок раздела «node.job(workFn, args?, doneFn) -> boolean»Raw: node.raw.job
The callback form of node.await: workFn runs on the pool, doneFn(result, err) on the worker. false when workFn could not be dumped.
node.log(msg, ...)
Заголовок раздела «node.log(msg, ...)»Raw: node.raw.log
Prints msg to the server console under this resource’s name. Extra arguments are string.format arguments: node.log("%s joined", player.name). The table also carries the levels: node.log.warn, node.log.error, and the raw forms below.
node.config : table
Заголовок раздела «node.config : table»The [config] table of this resource’s resource.toml, as written (strings, numbers, booleans, arrays, nested tables); an empty table when there is none. Read once at load; node.resources.manifest().config re-reads the file.
node.raw : table
Заголовок раздела «node.raw : table»The 1:1 mirror of the C ABI: one function per C entry, ids in, tables out (Raw Lua reference (node.raw.*)). Everything above is built on it; reach for it when you need exactly the C behaviour.
node.players – the roster
Заголовок раздела «node.players – the roster»Look players up and iterate them. get returns a Player object for any id (cheap: nothing is fetched until a field is read), so it is fine to call in a 60 Hz handler.
node.players.get(id) -> Player?
Заголовок раздела «node.players.get(id) -> Player?»The Player with this id – a Player or a number-like table. Cheap: nothing is fetched until a field is read, so it is fine inside a 60 Hz handler. nil for a negative or non-numeric id; an unknown id gives a Player whose isConnected() is false.
node.players.all() -> array<Player>
Заголовок раздела «node.players.all() -> array<Player>»Raw: node.raw.getPlayers
Every connected player, as Players. Ascending by id.
node.players.count() -> number
Заголовок раздела «node.players.count() -> number»Raw: node.raw.getPlayerCount
How many players are connected.
node.players.ids() -> array<number>
Заголовок раздела «node.players.ids() -> array<number>»Raw: node.raw.getPlayers
The connected player ids.
node.players.find(name) -> Player?
Заголовок раздела «node.players.find(name) -> Player?»The connected player with this display name, case-insensitively; nil when none.
Player objects
Заголовок раздела «Player objects»A Player is a table with id and a metatable. Reading any other field fetches the player’s record once and caches it on the object (refresh() drops the cache); methods act by id, so an object outlives the record it was made from – player:isConnected() tells you whether it still refers to someone. Two Players are == when their ids match; tostring(player) is Player#<id> <name>.
player.id : number
Заголовок раздела «player.id : number»The player id – small, assigned at connect and REUSED after a disconnect. Key durable data by name or ip, not by id.
player.name : string?
Заголовок раздела «player.name : string?»The display name. Still known inside a playerLeft handler (the prelude remembers it), nil for an id that was never seen.
player.ip : string?
Заголовок раздела «player.ip : string?»The remote IP as text; what an IP ban keys on. For a verified account, accountId is the better key – it does not change with the player’s network.
player.port : number?
Заголовок раздела «player.port : number?»The remote TCP port.
player.connectedSeconds : number?
Заголовок раздела «player.connectedSeconds : number?»Seconds since the connection was accepted.
player.synced : boolean?
Заголовок раздела «player.synced : boolean?»true once the player finished joining (received the world).
player.udpConnected : boolean?
Заголовок раздела «player.udpConnected : boolean?»true while the UDP channel is bound; false means positions fall back to TCP.
player.pingSeconds : number?
Заголовок раздела «player.pingSeconds : number?»Seconds since the last keepalive: a freshness metric (0-1 healthy), not a round-trip time.
player.role : string?
Заголовок раздела «player.role : string?»The role a plugin assigned with setRole (“” when none). Per session.
player.group : number?
Заголовок раздела «player.group : number?»The visibility group; 0 is the shared world.
player.vehicle : Vehicle?
Заголовок раздела «player.vehicle : Vehicle?»The vehicle the player occupies in any seat, or nil on foot. vehicleId is the same as a number (-1 on foot).
player.seatRole : string?
Заголовок раздела «player.seatRole : string?»“driver”, “passenger” or “none”.
player.vehicleCount : number?
Заголовок раздела «player.vehicleCount : number?»How many vehicles the player drives or spawned.
player.unicycle : number?
Заголовок раздела «player.unicycle : number?»The global id of the walking avatar, -1 when seated.
player.verified : boolean?
Заголовок раздела «player.verified : boolean?»true when the join ticket was redeemed with the directory (wire v17): the name is then the account’s username or the guest name the directory minted, and somebody other than the player vouched for it. false on a server with no [Directory], for a join that brought no ticket, and for one admitted through RedeemFailOpen.
player.guest : boolean?
Заголовок раздела «player.guest : boolean?»true when there is no account behind the name: a Test Drive session, or nothing verified at all. verified and not guest is “a signed-in account”.
player.accountId : number?
Заголовок раздела «player.accountId : number?»The directory’s account id, nil for a guest. Stable across sessions and addresses – the key to persist anything about a player by, and what node.bans.add(accountId) bans.
player.accountRoles : string?
Заголовок раздела «player.accountRoles : string?»The directory’s role string for the account (“ADM” for a directory admin; “” for everyone else and for guests). Distinct from role, which is this server’s own per-session role.
player.identifiers : array<string>?
Заголовок раздела «player.identifiers : array<string>?»What the directory knows the player by: “nodemp:<id>”, “discord:<id>”, “ip:<addr>”. Empty for an unverified player.
player:isConnected() -> boolean
Заголовок раздела «player:isConnected() -> boolean»Raw: node.raw.isPlayerConnected
true while a player with this id is connected. Ids are reused, so this cannot say it is the SAME player you saw earlier.
player:refresh() -> Player
Заголовок раздела «player:refresh() -> Player»Drops the cached record so the next field read fetches it again. Returns the player for chaining.
player:kick(reason?) -> boolean
Заголовок раздела «player:kick(reason?) -> boolean»Raw: node.raw.kickPlayer
Disconnects the player, showing the reason. false for an unknown id.
player:ban(reason?) -> boolean
Заголовок раздела «player:ban(reason?) -> boolean»Raw: node.raw.banPlayer
Bans the player and kicks it with the reason: its account when one was verified (the ban follows the account to any address) and its IP always. Persisted in bans.json.
player:verify(level) -> boolean?, string?
Заголовок раздела «player:verify(level) -> boolean?, string?»Raw: node.raw.verifyPlayer
Asks the player’s launcher helper to check the game install again, now, at level "size" (file lengths), "scripts" (plus a hash of the game’s lua/ and ui/), "full" (hash everything – slow, an audit) or "strict" (the archive tables of contents against the server’s reference manifest, the whole game root, the user folder). The answer arrives as the playerVerifyReported event, after the server applied its own verdict (a “differs” or “failed” report kicks the player when [General] VerifyGame is not off). Returns true when the request went out, or nil and a reason: "unknown player"; "unsupported" – that level is not available for this player (its launcher is too old for it, or strict is not on offer because this server has no reference manifest); "pending" – a request to this player is still counted as in flight (the server accepts one per player per 60 s; the check every join runs does not count, so a player:verify from a playerJoined handler goes out at once). Any other level raises Player:verify: unknown level '...' at the caller’s line.
player:setStrict(on) -> boolean?, string?
Заголовок раздела «player:setStrict(on) -> boolean?, string?»Raw: node.raw.setPlayerStrict
Marks the session strict (on true) or lifts the mark (false or nil; any value other than false/nil counts as on – including 0). The server then refuses Vehicle::Camera frames FROM the player that target a vehicle it does not occupy – they are not relayed, so a strict client cannot follow other people’s cars with its camera; frames from other players to it are unaffected. A refused report still fires playerCameraChanged, with denied = true in player:camera(). Server-side only: tell the client about its strict mode yourself (the session config). Per session, cleared at disconnect. Returns true, or nil and "unknown player".
player:send(event, data?) -> boolean
Заголовок раздела «player:send(event, data?) -> boolean»Raw: node.raw.emitClient
Sends a wire event to this player; data is a table (JSON-encoded) or a string.
player:sendModule(channel, data) -> boolean
Заголовок раздела «player:sendModule(channel, data) -> boolean»Raw: node.raw.sendModule
Sends raw bytes to this player on a u32 module channel.
player:setRole(role) -> boolean
Заголовок раздела «player:setRole(role) -> boolean»Raw: node.raw.setPlayerRole
Assigns the per-session role string (“” clears). The client shows it as a tag beside the name.
player:setGroup(group)
Заголовок раздела «player:setGroup(group)»Raw: node.raw.setPlayerGroup
Puts the player in a visibility group; 0 is the shared world. Move its vehicles too (vehicle:setGroup).
player:vehicles() -> array<Vehicle>
Заголовок раздела «player:vehicles() -> array<Vehicle>»Raw: node.raw.getPlayerVehicles
The vehicles the player drives or spawned, as Vehicles.
player:position() -> record{x,y,z}?
Заголовок раздела «player:position() -> record{x,y,z}?»Raw: node.raw.getPlayerPosition
The last known position, from the occupied vehicle or the walking avatar; nil before the first snapshot.
player:focus() -> record{pos,ageSeconds}?
Заголовок раздела «player:focus() -> record{pos,ageSeconds}?»Raw: node.raw.getPlayerFocus
The point the relay’s distance filter uses for this player: the camera when a head pose streams, else the driven vehicle.
player:headPose() -> record{pos,rot,freeCamera,ageSeconds}?
Заголовок раздела «player:headPose() -> record{pos,rot,freeCamera,ageSeconds}?»Raw: node.raw.getPlayerHeadPose
The last camera/head pose (about 10 Hz); nil until one arrived.
player:camera() -> record{vehicle,ageSeconds,denied?}?
Заголовок раздела «player:camera() -> record{vehicle,ageSeconds,denied?}?»Raw: node.raw.getPlayerCamera
Which vehicle the camera is on – its own or the one spectated; vehicle is -1 for none. In a strict session (setStrict) a report the server refused to relay – its target is a vehicle the player does not occupy – carries denied = true; the field is absent otherwise.
player:inputs() -> record{vehicle,controls,controlsAgeSeconds,axes,axesAgeSeconds}?
Заголовок раздела «player:inputs() -> record{vehicle,controls,controlsAgeSeconds,axes,axesAgeSeconds}?»Raw: node.raw.getPlayerInputs
Everything the player is pressing: the driven vehicle, the five controls and gear from the 60 Hz snapshot, the extra axes, each with its age. nil unless the player drives.
player:seat(vehicle, role?) -> boolean
Заголовок раздела «player:seat(vehicle, role?) -> boolean»Raw: node.raw.seatPlayer
Seats the player in the vehicle (a Vehicle or a gid) as “driver” (default) or “passenger”, bypassing locks; a previous driver becomes a passenger.
player:unseat() -> boolean
Заголовок раздела «player:unseat() -> boolean»Raw: node.raw.unseatPlayer
Puts the player on foot. false when it already is.
player:swapWith(other) -> boolean
Заголовок раздела «player:swapWith(other) -> boolean»Raw: node.raw.swapPlayers
Exchanges seats – role and vehicle – with another Player (or id), across the whole driver/passenger/on-foot matrix.
player:resync() -> number
Заголовок раздела «player:resync() -> number»Raw: node.raw.resyncPlayer
Re-sends every vehicle’s spawn and cached state to this player; returns how many bundles went out.
player:tell(text, ...)
Заголовок раздела «player:tell(text, ...)»Says a system line in this player’s chat (via the chat resource; silent without it). Extra arguments are format arguments.
node.vehicles – the registry
Заголовок раздела «node.vehicles – the registry»Look vehicles up and iterate them. Unicycles – the walking avatars – are vehicles to the server; all() leaves them out unless asked, get returns them like any other.
node.vehicles.get(id) -> Vehicle?
Заголовок раздела «node.vehicles.get(id) -> Vehicle?»The Vehicle with this global id, cheap like players.get. nil for a negative or non-numeric id; an unknown id gives a Vehicle whose exists() is false.
node.vehicles.all(includeUnicycles?) -> array<Vehicle>
Заголовок раздела «node.vehicles.all(includeUnicycles?) -> array<Vehicle>»Raw: node.raw.getVehicles
Every vehicle in the registry as Vehicles with their records already loaded. Walking avatars (unicycles) are left out unless includeUnicycles is true.
node.vehicles.count() -> number
Заголовок раздела «node.vehicles.count() -> number»Raw: node.raw.getVehicleCount
How many vehicles the registry holds, unicycles included.
node.vehicles.spawn(config, ownerName?) -> Vehicle?
Заголовок раздела «node.vehicles.spawn(config, ownerName?) -> Vehicle?»Raw: node.raw.spawnVehicle
Spawns an ownerless vehicle from a config (a table or JSON text in the client SpawnReq schema: jbm, vcf, pos, rot, …) and hands its simulation to the best available client. nil when nobody can host it.
node.vehicles.deleteAll() -> number
Заголовок раздела «node.vehicles.deleteAll() -> number»Raw: node.raw.deleteAllVehicles
Deletes every vehicle; returns how many.
node.vehicles.byTag(key, value?) -> array<Vehicle>
Заголовок раздела «node.vehicles.byTag(key, value?) -> array<Vehicle>»Raw: node.raw.getVehiclesByTag
Vehicles carrying the tag key – any value, or exactly value.
node.vehicles.byTags(pairs) -> array<Vehicle>
Заголовок раздела «node.vehicles.byTags(pairs) -> array<Vehicle>»Raw: node.raw.getVehiclesByTags
Vehicles whose tags match EVERY key = value pair of the table (AND).
node.vehicles.transforms() -> array<record{id,pos,rot,vel,angVel,time,ping,seq,paused,transitioning,teleport,velocityStep,hasControls,ageSeconds}>
Заголовок раздела «node.vehicles.transforms() -> array<record{id,pos,rot,vel,angVel,time,ping,seq,paused,transitioning,teleport,velocityStep,hasControls,ageSeconds}>»Raw: node.raw.getVehicleTransforms
The positions table: every vehicle’s last snapshot in one array under one lock – the read for a radar polling every tick.
Vehicle objects
Заголовок раздела «Vehicle objects»A Vehicle is a table with id and a metatable, lazy like a Player: the registry record is fetched on the first field read and cached until refresh(). Ids that name players come as Players (driver, spawner, authority, passengers) with the raw ids beside them (driverId, …). Everything that streams – transform, controls, electrics – is a method, because it is a fresh read each time.
vehicle.id : number
Заголовок раздела «vehicle.id : number»The global id, unique for the life of the server.
vehicle.name : string?
Заголовок раздела «vehicle.name : string?»The owner label the spawn carried (the spawner’s display name for a player’s car, the ownerName given to vehicles.spawn).
vehicle.spawner : Player?
Заголовок раздела «vehicle.spawner : Player?»The Player that spawned it, nil for a server-spawned one. spawnerId is the id (-1).
vehicle.driver : Player?
Заголовок раздела «vehicle.driver : Player?»The Player at the wheel, nil when empty. driverId is the id (-1).
vehicle.authority : Player?
Заголовок раздела «vehicle.authority : Player?»The Player simulating it (not necessarily the spawner). authorityId is the id.
vehicle.passengers : array<Player>
Заголовок раздела «vehicle.passengers : array<Player>»The passengers as Players. passengerIds are the ids.
vehicle.isUnicycle : boolean?
Заголовок раздела «vehicle.isUnicycle : boolean?»true for a walking avatar.
vehicle.idleSeconds : number?
Заголовок раздела «vehicle.idleSeconds : number?»How long nobody has driven it; 0 while driven.
vehicle.spawnerOnline : boolean?
Заголовок раздела «vehicle.spawnerOnline : boolean?»Whether the spawning player is still connected.
vehicle.lockMode : string?
Заголовок раздела «vehicle.lockMode : string?»“unlocked”, “locked” or “driver-only”. lockWhitelist are the player ids always allowed in.
vehicle.configHash : number?
Заголовок раздела «vehicle.configHash : number?»FNV-1a-32 of the cached config – what clients echo so a desynced config is detectable.
vehicle.damageCounter : number?
Заголовок раздела «vehicle.damageCounter : number?»The authority-reported damage version. damageBlobCounter and damageBlobSize describe the stored blob (0 = pristine).
vehicle.tags : table?
Заголовок раздела «vehicle.tags : table?»The tags as key -> value.
vehicle.group : number?
Заголовок раздела «vehicle.group : number?»The visibility group; 0 is the shared world.
vehicle:exists() -> boolean
Заголовок раздела «vehicle:exists() -> boolean»true while the registry has this id.
vehicle:refresh() -> Vehicle
Заголовок раздела «vehicle:refresh() -> Vehicle»Drops the cached record. Returns the vehicle for chaining.
vehicle:delete() -> boolean
Заголовок раздела «vehicle:delete() -> boolean»Raw: node.raw.deleteVehicle
Deletes the vehicle for everyone; vehicleDeleted follows.
vehicle:transform() -> record{pos,rot,vel,angVel,time,ping,seq,paused,transitioning,teleport,velocityStep,hasControls,ageSeconds}?
Заголовок раздела «vehicle:transform() -> record{pos,rot,vel,angVel,time,ping,seq,paused,transitioning,teleport,velocityStep,hasControls,ageSeconds}?»Raw: node.raw.getVehicleTransform
The last kinematic snapshot; nil before the first. A few ticks old by construction.
vehicle:controls() -> record{steering,throttle,brake,clutch,parkingBrake,gear}?
Заголовок раздела «vehicle:controls() -> record{steering,throttle,brake,clutch,parkingBrake,gear}?»Raw: node.raw.getVehicleControls
The driving inputs from the last snapshot; nil while no driver has sent one.
vehicle:inputs() -> record{axes,ageSeconds}?
Заголовок раздела «vehicle:inputs() -> record{axes,ageSeconds}?»Raw: node.raw.getVehicleInputs
The driver’s extra (modded) input axes, merged from the delta stream.
vehicle:electrics() -> table?
Заголовок раздела «vehicle:electrics() -> table?»Raw: node.raw.getVehicleElectrics
The merged electrics (lights, signals, gauges).
vehicle:powertrain() -> table?
Заголовок раздела «vehicle:powertrain() -> table?»Raw: node.raw.getVehiclePowertrain
The merged powertrain device state.
vehicle:engine() -> table?
Заголовок раздела «vehicle:engine() -> table?»Raw: node.raw.getVehicleEngine
The merged engine state.
vehicle:controllers() -> table?
Заголовок раздела «vehicle:controllers() -> table?»Raw: node.raw.getVehicleControllers
The merged controller calls, “controller|function” -> call.
vehicle:couplers() -> array?
Заголовок раздела «vehicle:couplers() -> array?»Raw: node.raw.getVehicleCouplers
The merged coupler/door state.
vehicle:nodes() -> table?
Заголовок раздела «vehicle:nodes() -> table?»Raw: node.raw.getVehicleNodes
The last node-position (deformation) packet, as sent.
vehicle:breakGroups() -> array<string>?
Заголовок раздела «vehicle:breakGroups() -> array<string>?»Raw: node.raw.getVehicleBreakGroups
The break groups reported broken.
vehicle:paints() -> array?
Заголовок раздела «vehicle:paints() -> array?»Raw: node.raw.getVehiclePaints
The paint layers from the cached config.
vehicle:config() -> table?
Заголовок раздела «vehicle:config() -> table?»Raw: node.raw.getVehicleConfig
The cached spawn/edit config – what a joiner receives.
vehicle:damage() -> record{counter,blobCounter,size,blob}?
Заголовок раздела «vehicle:damage() -> record{counter,blobCounter,size,blob}?»Raw: node.raw.getVehicleDamage
Damage telemetry with the raw blob (a binary string, nil when pristine).
vehicle:sync() -> record{authority,authorityAgeSeconds,seatEpoch,spawnedAgeSeconds,idleSeconds,configChangedAgeSeconds,hasPos,posAgeSeconds,posSeq}?
Заголовок раздела «vehicle:sync() -> record{authority,authorityAgeSeconds,seatEpoch,spawnedAgeSeconds,idleSeconds,configChangedAgeSeconds,hasPos,posAgeSeconds,posSeq}?»Raw: node.raw.getVehicleSync
How alive the sync is: the authority and its heartbeat age, seat epoch, ages. The record for ‘why is this car frozen’.
vehicle:occupants() -> array<record{player,role}>
Заголовок раздела «vehicle:occupants() -> array<record{player,role}>»Raw: node.raw.getVehicleOccupants
Who is in it, driver first: { player = Player, role = "driver" | "passenger" }.
vehicle:tag(key) -> string?
Заголовок раздела «vehicle:tag(key) -> string?»Raw: node.raw.getVehicleTag
One tag’s value.
vehicle:setTag(key, value) -> boolean
Заголовок раздела «vehicle:setTag(key, value) -> boolean»Raw: node.raw.setVehicleTag
Sets a tag (key 1-64 bytes, value 1-256, 32 keys per vehicle; over-limit is rejected). Broadcast to clients; vehicleTagsChanged fires.
vehicle:removeTag(key) -> boolean
Заголовок раздела «vehicle:removeTag(key) -> boolean»Raw: node.raw.removeVehicleTag
Removes a tag; false when it was not there.
vehicle:lock(mode?, whitelist?) -> boolean
Заголовок раздела «vehicle:lock(mode?, whitelist?) -> boolean»Raw: node.raw.setVehicleLock
Locks the vehicle against NEW seat claims: mode “locked” (default), “driver-only” or “unlocked”; whitelist is an array of Players or ids always allowed (up to 32). Nobody seated is evicted; server-driven seating bypasses locks.
vehicle:unlock() -> boolean
Заголовок раздела «vehicle:unlock() -> boolean»Raw: node.raw.setVehicleLock
lock("unlocked").
vehicle:lockState() -> record{mode,whitelist}?
Заголовок раздела «vehicle:lockState() -> record{mode,whitelist}?»Raw: node.raw.getVehicleLock
The current lock.
vehicle:setCoupler(name, open?) -> boolean
Заголовок раздела «vehicle:setCoupler(name, open?) -> boolean»Raw: node.raw.setVehicleCoupler
Opens (default) or closes the named coupler group on every client and caches it.
vehicle:trigger(call) -> boolean
Заголовок раздела «vehicle:trigger(call) -> boolean»Raw: node.raw.triggerVehicle
Has the sync authority execute one controller call – a table or JSON {controllerName, functionName, ...}. Never asks vehicleTriggerRequest: the server does not veto itself.
vehicle:resync(to?) -> boolean
Заголовок раздела «vehicle:resync(to?) -> boolean»Raw: node.raw.resyncVehicle
Re-sends the spawn and cached state to one Player (or id), or to everyone.
vehicle:seat(player, role?) -> boolean
Заголовок раздела «vehicle:seat(player, role?) -> boolean»Raw: node.raw.seatPlayer
Seats a Player (or id) in this vehicle; player:seat(vehicle) is the same call.
vehicle:setGroup(group)
Заголовок раздела «vehicle:setGroup(group)»Raw: node.raw.setVehicleGroup
Puts the vehicle in a visibility group. A packet about a vehicle belongs to the vehicle’s group, not its driver’s.
node.server – identity, limits, time, metrics
Заголовок раздела «node.server – identity, limits, time, metrics»The server’s own facts and knobs.
node.server.name() -> string
Заголовок раздела «node.server.name() -> string»Raw: node.raw.getServerName
The server’s name.
node.server.setName(name) -> boolean
Заголовок раздела «node.server.setName(name) -> boolean»Raw: node.raw.setServerName
Changes the reported name.
node.server.map() -> string
Заголовок раздела «node.server.map() -> string»Raw: node.raw.getMap
The map, as the client-facing level path.
node.server.version() -> string
Заголовок раздела «node.server.version() -> string»Raw: node.raw.getServerVersion
The server’s version string.
node.server.port() -> number
Заголовок раздела «node.server.port() -> number»Raw: node.raw.getPort
The port (TCP and UDP).
node.server.maxPlayers() -> number
Заголовок раздела «node.server.maxPlayers() -> number»Raw: node.raw.getMaxPlayers
The player limit in force.
node.server.setMaxPlayers(n) -> boolean
Заголовок раздела «node.server.setMaxPlayers(n) -> boolean»Raw: node.raw.setMaxPlayers
Changes the player limit; enforced on the next connect, nobody is kicked.
node.server.maxCars() -> number
Заголовок раздела «node.server.maxCars() -> number»Raw: node.raw.getMaxCars
The per-player vehicle limit in force.
node.server.setMaxCars(n) -> boolean
Заголовок раздела «node.server.setMaxCars(n) -> boolean»Raw: node.raw.setMaxCars
Changes the per-player vehicle limit; enforced on the next spawn.
node.server.uptime() -> number
Заголовок раздела «node.server.uptime() -> number»Raw: node.raw.getServerUptime
Seconds since start (monotonic, fractional).
node.server.time() -> number
Заголовок раздела «node.server.time() -> number»Raw: node.raw.getTime
Unix time with fractions.
node.server.unixTime() -> number
Заголовок раздела «node.server.unixTime() -> number»Raw: node.raw.getUnixTime
Unix time in whole seconds.
node.server.metrics() -> table
Заголовок раздела «node.server.metrics() -> table»Raw: node.raw.getMetrics
Live metrics: players, vehicles, uptime, net counters, connection limiter, plugin queue.
node.server.snapshot() -> record{time,players,vehicles}
Заголовок раздела «node.server.snapshot() -> record{time,players,vehicles}»Raw: node.raw.getWorldSnapshot
One bulk read of the world: players with position and seat, vehicles with pos/rot/vel.
node.server.nodeGrabEnabled() -> boolean
Заголовок раздела «node.server.nodeGrabEnabled() -> boolean»Raw: node.raw.isNodeGrabEnabled
Whether the experimental node grabber is enabled in server.toml.
node.bans
Заголовок раздела «node.bans»IP bans, persisted in bans.json. Player:ban() is the one that also kicks.
node.bans.add(who, reason?) -> boolean
Заголовок раздела «node.bans.add(who, reason?) -> boolean»Raw: node.raw.banIp
Bans for future connects. who is an IP string (banIp), a directory account id number (banAccount, wire v17: the ban follows the account to any address) or a Player (banPlayer: account when verified, IP always, and the player is kicked). Persisted in bans.json. An existing session stays for the first two forms.
node.bans.remove(who) -> boolean
Заголовок раздела «node.bans.remove(who) -> boolean»Raw: node.raw.unbanIp
Lifts a ban: an IP string, or an account id number. False when it was not banned.
node.bans.has(who) -> boolean
Заголовок раздела «node.bans.has(who) -> boolean»Raw: node.raw.isBanned
Whether an IP string, an account id number, or a Player (its account when verified, else its IP) is banned.
node.bans.all() -> array<record{ip,account,reason,at,name}>
Заголовок раздела «node.bans.all() -> array<record{ip,account,reason,at,name}>»Raw: node.raw.getBans
Every ban: IP bans carry ip, account bans carry account (the directory’s id).
node.storage – persistent key/value
Заголовок раздела «node.storage – persistent key/value»A per-resource JSON store (storage/<resource>.json), flushed atomically on every write.
node.storage.get(key, default?) -> any
Заголовок раздела «node.storage.get(key, default?) -> any»Raw: node.raw.storageGet
The stored value, or default when the key is absent.
node.storage.set(key, value) -> boolean
Заголовок раздела «node.storage.set(key, value) -> boolean»Raw: node.raw.storageSet
Stores any JSON-serialisable value; flushed atomically.
node.storage.delete(key) -> boolean
Заголовок раздела «node.storage.delete(key) -> boolean»Raw: node.raw.storageDelete
Removes a key; false when absent.
node.fs – files inside the resource folder
Заголовок раздела «node.fs – files inside the resource folder»Files inside the resource’s own folder; paths that escape it are rejected.
node.fs.read(path) -> string?
Заголовок раздела «node.fs.read(path) -> string?»Raw: node.raw.readFile
Reads a file inside the resource folder; nil when missing or outside it.
node.fs.write(path, data) -> boolean
Заголовок раздела «node.fs.write(path, data) -> boolean»Raw: node.raw.writeFile
Writes a file inside the resource folder, creating folders. Synchronous.
node.fs.writeAsync(path, data, cb?) -> boolean
Заголовок раздела «node.fs.writeAsync(path, data, cb?) -> boolean»Raw: node.raw.writeFileAsync
Writes off the worker; cb(ok) runs on the worker when done. true means accepted.
node.fs.list(path?) -> array<record{name,dir,size}>?
Заголовок раздела «node.fs.list(path?) -> array<record{name,dir,size}>?»Raw: node.raw.listFiles
Lists a folder inside the resource folder (the root when omitted).
node.http
Заголовок раздела «node.http»Asynchronous HTTP. Callbacks run on the worker; fetch is the coroutine form for use inside node.async.
node.http.get(url, headers?, cb) -> boolean
Заголовок раздела «node.http.get(url, headers?, cb) -> boolean»Raw: node.raw.httpGet
GET; cb(status, body, headers) on the worker: status is the HTTP status code, or -1 with the error text in body when the request failed (could not resolve or connect, TLS handshake or certificate verification, timeout, malformed or oversized response). Returns false when the request could not be queued – cb then never runs. About 15 s timeout, 8 MB body. TLS peer verification is off unless the hoster set [Http] CaFile (then every https request is verified against that bundle and a failure is a -1).
node.http.post(url, body, headers?, cb) -> boolean
Заголовок раздела «node.http.post(url, body, headers?, cb) -> boolean»Raw: node.raw.httpPost
POST; body is a table (JSON-encoded) or a string. cb and the return value are as for get: status -1 with the error text in body when the request failed, false when it could not be queued.
node.http.request(method, url, opts?, cb) -> boolean
Заголовок раздела «node.http.request(method, url, opts?, cb) -> boolean»Raw: node.raw.httpRequest
Any method (server 1.2.0): node.http.request("PUT", url, { headers = h, body = t }, cb). method is a token of letters A-Z only, at most 16 – "GET", "POST", "PUT", "PATCH", "DELETE", "HEAD" or a custom one the service understands; the prelude upper-cases it for you, anything else comes back as status -1 with body “invalid HTTP method”; opts.headers is a table of header -> value, opts.body a table (JSON-encoded) or a string, both optional (opts itself may be nil). cb(status, body, headers) and the return value are exactly as for get: the HTTP status code, or -1 with the error text in body when the request failed; false when the request could not be queued (cb then never runs). A HEAD answer carries status and headers and an empty body. put, patch, delete and head are this with the method fixed.
node.http.put(url, body?, headers?, cb) -> boolean
Заголовок раздела «node.http.put(url, body?, headers?, cb) -> boolean»Raw: node.raw.httpRequest
PUT; body is a table (JSON-encoded), a string, or nil for none. cb and the return value are as for get.
node.http.patch(url, body?, headers?, cb) -> boolean
Заголовок раздела «node.http.patch(url, body?, headers?, cb) -> boolean»Raw: node.raw.httpRequest
PATCH; body is a table (JSON-encoded), a string, or nil for none. cb and the return value are as for get.
node.http.delete(url, body?, headers?, cb) -> boolean
Заголовок раздела «node.http.delete(url, body?, headers?, cb) -> boolean»Raw: node.raw.httpRequest
DELETE; the body is optional (most services want none: node.http.delete(url, nil, headers, cb) or node.http.delete(url, cb)). cb and the return value are as for get.
node.http.head(url, headers?, cb) -> boolean
Заголовок раздела «node.http.head(url, headers?, cb) -> boolean»Raw: node.raw.httpRequest
HEAD; cb(status, “”, headers) – the status and the response headers, never a body. The return value is as for get.
node.http.fetch(url, opts?) -> number, string, table
Заголовок раздела «node.http.fetch(url, opts?) -> number, string, table»The coroutine form, inside node.async only: local status, body, headers = node.http.fetch(url, { method = "DELETE", body = t, headers = h }). opts.method is any method request accepts (default GET; before 1.2.0 anything but POST was sent as GET). status is the HTTP status code, or -1 with the error text in body when the request failed; it is 0, with body “request not queued”, only when the request could not be queued at all (the background pool is full or shutting down).
node.pg – PostgreSQL
Заголовок раздела «node.pg – PostgreSQL»Asynchronous, pooled PostgreSQL over the connection string in [Database] Url (enabled() is false without one). Every call has two forms: with a callback, which runs on the worker when the statement completes, or without one inside node.async, where it suspends the coroutine and returns the result – local result, err = node.pg.query(sql, params). Statements are parameterised ($1..$n, node.pg.NULL for NULL), rows come back keyed by column name, errors are tables with the SQLSTATE or an internal code in code. tx runs a function on one reserved connection between BEGIN and COMMIT/ROLLBACK.
node.pg.enabled() -> boolean
Заголовок раздела «node.pg.enabled() -> boolean»Raw: node.raw.pgEnabled
true when the server was configured with a database ([Database] Url in server.toml, or NODE_DATABASE_URL). false means every node.pg call answers err.code == "pg_disabled"; check it once at load and degrade gracefully instead of assuming a database.
node.pg.ready() -> boolean
Заголовок раздела «node.pg.ready() -> boolean»Raw: node.raw.pgReady
true while at least one pool connection is established. The pool connects in the background and reconnects on its own (0.5 s to 30 s backoff); the server starts without the database, and until this turns true statements fail at once with err.code == "08001" rather than waiting.
node.pg.NULL : userdata
Заголовок раздела «node.pg.NULL : userdata»The NULL parameter. A Lua nil inside the params array ends the array – { 1, nil, "x" } sends one parameter – so write { 1, node.pg.NULL, "x" } for every NULL. One opaque value per server, recognised by identity; it belongs only inside a params array. Coming back the other way, a NULL cell is simply absent from its row (row.col == nil).
node.pg.query(sql, params?, cb?) -> record{rows,count,columns}?, record{code,message,detail,hint,constraint,table}?
Заголовок раздела «node.pg.query(sql, params?, cb?) -> record{rows,count,columns}?, record{code,message,detail,hint,constraint,table}?»Raw: node.raw.pgQuery
Runs one parameterised statement on the pool. sql uses $1..$n; params is the array of values, in order: node.pg.NULL -> NULL (a nil would end the array), boolean, integer, float, string as text (a NUL inside is not supported – send bytea as hex through decode($1, 'hex')), a table as JSON (for json/jsonb columns); the type is inferred by the server. A statement without parameters may leave params out: node.pg.query(sql, cb). Never concatenate values into sql. Two forms. With cb, the callback form: returns nothing and cb(result, err) runs on the worker when the statement completes. Without cb, inside node.async, the suspending form: the coroutine suspends and local result, err = node.pg.query(sql, params) gets the same two values; outside a coroutine it raises “node.pg.query: callback required outside node.async” (like node.sleep). result = { rows = { { col = value, ... }, ... }, count = <rows returned, or affected for a statement without rows>, columns = { "col", ... } }. Rows are keyed by column name (alias duplicate names; columns keeps the order); values follow the column type – bool -> boolean, int2/int4/int8 -> integer (64-bit), float4/float8 -> number, numeric -> string (exact; keep money in integer minor units), text/varchar/uuid/timestamp/date/time/interval -> string (Postgres’ text form), json/jsonb -> string (node.json.decode it), bytea -> string of raw bytes, arrays and anything else -> Postgres’ text form; a NULL cell is absent (nil). err = { code, message, detail?, hint?, constraint?, table? } with the SQLSTATE in code ("23505" unique violation, with constraint; "42601" syntax; "57014" statement timeout, [Database] QueryTimeoutMs; "08001" no connection; "08006" connection lost) or an internal code: pg_disabled (no [Database] Url), pg_queue_full (1000 statements pending), pg_result_cap (more than [Database] MaxRows rows; the result is dropped), pg_params (a value inside params the driver cannot send – a function, a coroutine, a userdata other than node.pg.NULL, a string with a NUL, a table JSON cannot encode – or more than 1000 of them), pg_reload (never delivered: a resource unloaded while a statement is in flight never sees its callback; the code exists so the list is complete). A params that is not a table at all – or a sql that is not a string, or a cb that is not a function – is a programming error and raises at the caller’s line instead of reaching cb. Every statement here is its own transaction; see tx for several on one connection – a node.pg.query inside a tx function is NOT part of that transaction.
node.pg.exec(sql, params?, cb?) -> number?, record{code,message,detail,hint,constraint,table}?
Заголовок раздела «node.pg.exec(sql, params?, cb?) -> number?, record{code,message,detail,hint,constraint,table}?»Raw: node.raw.pgQuery
query for statements whose rows you do not want: no row is materialised and the answer is the count – rows affected by an INSERT/UPDATE/DELETE, rows a SELECT would have returned. cb(count, err) in the callback form; local count, err = node.pg.exec(sql, params) inside node.async. Same params, errors and rules as query.
node.pg.tx(fn, cb?) -> any..., record{code,message,detail,hint,constraint,table}?
Заголовок раздела «node.pg.tx(fn, cb?) -> any..., record{code,message,detail,hint,constraint,table}?»A transaction. fn(tx) runs as a coroutine on ONE pool connection reserved for it – its own node.async task in the callback form, the caller’s coroutine in the suspending form: BEGIN, then everything fn does through tx, then COMMIT when fn returns normally, ROLLBACK when fn raises or calls tx:rollback(). Inside fn use the suspending forms only: local result, err = tx:query(sql, params?) and local count, err = tx:exec(sql, params?) – the same contract as node.pg.query/exec without a callback, on the reserved connection; tx:rollback(reason?) raises out of fn and rolls back. A plain node.pg.query inside fn goes to ANOTHER connection and is NOT part of the transaction. After a failed statement Postgres refuses every further statement of the transaction (25P02) until it is rolled back – check err and tx:rollback() or raise. Outcome: fn returned normally and COMMIT succeeded -> the return values of fn; COMMIT failed -> nil, err (a SQLSTATE; Postgres rolled back); fn raised -> ROLLBACK and nil, { code = "rollback", message = <the error text, or the .message of a raised table>, cause = <the value fn raised> } (so error(err) with the err of a failed tx:query keeps its SQLSTATE in cause.code); tx:rollback(reason) -> ROLLBACK and nil, { code = "rollback", message = reason }; the transaction outlived [Database] TxTimeoutMs (default 30 s) -> the server rolled it back already and the next tx call or the COMMIT answers { code = "tx_timeout" }; BEGIN itself failed -> nil, err (08001, pg_disabled, pg_queue_full). With cb, cb(…) receives exactly those values on the worker (cb(<returns of fn>) or cb(nil, err)); without cb, inside node.async, local a, b = node.pg.tx(fn) suspends the caller and returns them; outside a coroutine the suspending form raises “node.pg.tx: callback required outside node.async”. Keep transactions short: the connection is unavailable to everyone else while fn runs, and a node.sleep inside fn holds it too. Unloading the resource rolls back its open transactions and drops their callbacks.
node.json
Заголовок раздела «node.json»JSON in and out. Most of the API encodes for you (a table given to send, broadcast, bus.emit, storage.set is encoded); these are for everything else.
node.json.encode(value) -> string
Заголовок раздела «node.json.encode(value) -> string»Raw: node.raw.jsonEncode
Encodes a Lua value as JSON.
node.json.decode(text) -> any?
Заголовок раздела «node.json.decode(text) -> any?»Raw: node.raw.jsonDecode
Decodes JSON text; nil on a parse error.
node.crypto
Заголовок раздела «node.crypto»Digests and randomness.
node.crypto.sha256(data) -> string
Заголовок раздела «node.crypto.sha256(data) -> string»Raw: node.raw.sha256
SHA-256 as 64 hex characters.
node.crypto.hmac(key, data) -> string
Заголовок раздела «node.crypto.hmac(key, data) -> string»Raw: node.raw.hmac
HMAC-SHA256 as hex.
node.crypto.randomBytes(n) -> string?
Заголовок раздела «node.crypto.randomBytes(n) -> string?»Raw: node.raw.randomBytes
n cryptographically random bytes as a binary string (1..65536).
node.crypto.randomHex(n?) -> string?
Заголовок раздела «node.crypto.randomHex(n?) -> string?»n random bytes (default 16) as hex – a token.
node.log
Заголовок раздела «node.log»node.log(msg, ...) prints under the resource’s tag with string.format arguments; the table also carries the levels and the raw forms.
node.log.warn(msg, ...)
Заголовок раздела «node.log.warn(msg, ...)»Raw: node.raw.logWarn
Logs at the warning level under this resource’s name; format arguments accepted.
node.log.error(msg, ...)
Заголовок раздела «node.log.error(msg, ...)»Raw: node.raw.logError
Logs at the error level under this resource’s name.
node.log.tag(tag, msg, ...)
Заголовок раздела «node.log.tag(tag, msg, ...)»Raw: node.raw.logTag
Logs under one of the server’s own tags (Core, Net, Res, Mods, Module, Join, Leave, Kick, Veh, Warn, Error, Debug).
node.log.custom(tag, rgb, msg, ...)
Заголовок раздела «node.log.custom(tag, rgb, msg, ...)»Raw: node.raw.logCustom
Logs under a tag of your own in a 0xRRGGBB colour.
node.log.raw(text)
Заголовок раздела «node.log.raw(text)»Raw: node.raw.logRaw
Writes text to the console as-is, no timestamp or tag.
node.log.sink(fn)
Заголовок раздела «node.log.sink(fn)»Raw: node.raw.setLogSink
Observes every server log line as fn(tag, level, msg) on the worker; nil clears. Cannot suppress lines.
node.log.title(title)
Заголовок раздела «node.log.title(title)»Raw: node.raw.setConsoleTitle
Sets the console window title.
node.bus – between resources
Заголовок раздела «node.bus – between resources»Publish/subscribe between resources on this server (and native modules). Asynchronous, delivered to the sender too.
node.bus.emit(name, data?)
Заголовок раздела «node.bus.emit(name, data?)»Raw: node.raw.emitResource
Publishes to every resource and native module subscribed to name (the sender included), asynchronously on the worker. data is a table (JSON-encoded) or a string.
node.bus.on(name, fn)
Заголовок раздела «node.bus.on(name, fn)»Raw: node.raw.onResource
Subscribes fn(sourceResourceName, data) to bus messages under name; a native module appears as “native”.
node.bus.off(name, fn?) -> number
Заголовок раздела «node.bus.off(name, fn?) -> number»Raw: node.raw.offResource
Unsubscribes this resource’s bus handlers for name – all of them, or only fn, matched by identity from any context, including coroutines.
node.modules – the binary channel
Заголовок раздела «node.modules – the binary channel»Raw bytes on a numbered channel, for native modules and their client halves.
node.modules.on(channel, fn)
Заголовок раздела «node.modules.on(channel, fn)»Raw: node.raw.onModule
Subscribes fn(player, data) to raw bytes clients send on a u32 channel.
node.modules.off(channel, fn?) -> number
Заголовок раздела «node.modules.off(channel, fn?) -> number»Raw: node.raw.offModule
Unsubscribes this resource’s handlers for the channel – all of them, or only fn, matched by identity from any context, including coroutines.
node.modules.send(target, channel, data) -> boolean
Заголовок раздела «node.modules.send(target, channel, data) -> boolean»Raw: node.raw.sendModule
Sends raw bytes to a Player (or id), or to everyone with target “all” or nil.
node.relay – who sees what
Заголовок раздела «node.relay – who sees what»The packet filter and its cache. Visibility groups (Player:setGroup, Vehicle:setGroup) are the cheap alternative for room-style rules.
node.relay.filter(fn)
Заголовок раздела «node.relay.filter(fn)»Raw: node.raw.on
Installs a relayRequest hook (the same thing as node.on("relayRequest", fn)): fn(fromPid, toPid, category, subtype, globalId) returns false to hide a packet from that recipient. Runs with ids on the hot path; verdicts are cached until invalidate. Prefer visibility groups for room-style rules.
node.relay.unfilter(fn?) -> number
Заголовок раздела «node.relay.unfilter(fn?) -> number»Raw: node.raw.off
Removes this resource’s hooks, or only fn.
node.relay.invalidate()
Заголовок раздела «node.relay.invalidate()»Raw: node.raw.invalidateRelayCache
Drops every cached verdict so the hooks are consulted again. Call it whenever the data a hook reads has changed.
node.resources and node.config
Заголовок раздела «node.resources and node.config»The resource’s own manifest and settings, and reloading resources by name.
node.resources.reload(name) -> boolean
Заголовок раздела «node.resources.reload(name) -> boolean»Raw: node.raw.reloadResource
Queues a reload of a resource by name – registrations, timers and coroutines dropped, the folder loaded again. true means accepted. A resource may reload itself.
node.resources.manifest() -> record{name,version,type,server,client,config}?
Заголовок раздела «node.resources.manifest() -> record{name,version,type,server,client,config}?»Raw: node.raw.getManifest
This resource’s resource.toml as a table, re-read from disk.
node.chat
Заголовок раздела «node.chat»Speak into the chat as the server. Needs the chat resource (it owns the screen side); silent without it.
node.chat.say(text, ...)
Заголовок раздела «node.chat.say(text, ...)»Says a system line in everyone’s chat (via the chat resource). Format arguments accepted.
node.chat.tell(target, text, ...)
Заголовок раздела «node.chat.tell(target, text, ...)»Says a system line in one player’s chat; target is a Player or an id.
node.commands
Заголовок раздела «node.commands»Chat commands: a line starting with / reaches the handler registered for its first word, with the sender as a Player. Needs the chat resource.
node.commands.add(name, fn, opts?)
Заголовок раздела «node.commands.add(name, fn, opts?)»Registers a chat command: a line /name ... typed by any player calls fn(player, args, raw) with the sender as a Player, the words after the name as an array and the whole line. opts.role restricts it to players whose role equals it; others are told they may not. Names are case-insensitive. Needs the chat resource, which publishes the lines.
node.commands.remove(name)
Заголовок раздела «node.commands.remove(name)»Unregisters a command.
