Skip to content

Core runtime API ​

Lua uses nil, boolean, number, string, function, and table. Signatures in this reference put optional arguments in brackets. A call that violates its type, range, permission, phase, or resource budget raises a Lua error unless stated otherwise.

Runtime identity ​

ValueTypeMeaning
samp.api.versionstringActive Plugin API version, currently "1.1".
samp.plugin.idstringStable ID from the installed manifest.
samp.plugin.versionstringInstalled plugin version.

samp.api.has(name [, minimumVersion]) ​

Returns boolean. name is a capability string up to 128 bytes. minimumVersion, when present, is a numeric API version such as "1.1". The result is true only when both the capability and version are supported. Use this for optional behavior, not as a replacement for manifest permissions.

Logging ​

lua
samp.log.debug(message)
samp.log.info(message)
samp.log.warn(message)
samp.log.error(message)

message is a string of at most 2,048 bytes. The host attaches the plugin ID and selected severity. The functions return nothing.

Subscriptions ​

samp.events.on(name, callback [, options]) ​

Registers callback(event) and returns a subscription handle:

lua
local subscription = samp.events.on("player.spawned", callback, {
    priority = 100,
    once = true
})
subscription:unsubscribe()
ArgumentTypeRules
namestringNon-empty, at most 96 bytes.
callbackfunctionReceives one event table.
options.priorityintegerOptional, -1000..1000, default 0; higher runs first.
options.oncebooleanOptional, default false; removes the subscription after its first dispatch.

A plugin may hold at most 256 subscriptions. Event-specific permissions are checked when subscribing. unsubscribe() is idempotent and returns nothing. See Event payloads.

Modules ​

require(name) ​

Loads modules/<name>.lua and returns the module result. Dots map to directories: require("ui.colors") loads modules/ui/colors.lua.

name is at most 128 bytes and may contain letters, digits, _, and .; leading, trailing, or repeated dots are rejected. Modules are cached by name. If a module returns nil, callers receive true. Plugins cannot load native modules or files outside their own modules/ directory.

Timers and managed tasks ​

samp.timer.after(delayMs, callback) ​

Schedules a one-shot callback and returns { cancel = function }. delayMs is an integer from 0 to 86,400,000. A plugin may have at most 256 timers. cancel() is idempotent.

samp.task.spawn(callback) ​

Starts a managed coroutine and returns { cancel = function }. A plugin may have at most 256 tasks. The callback has no arguments. Cancelling is idempotent; cancelling the currently executing task stops it safely.

samp.task.sleep(delayMs) ​

Suspends the current managed task for 0..86,400,000 milliseconds. It returns no value and raises an error outside a task created by samp.task.spawn. Ordinary event callbacks and mutable interception callbacks cannot yield.

Private storage ​

All storage calls require plugin.storage. Values are private to the plugin ID.

lua
local value = samp.storage.get(key [, default])
samp.storage.set(key, value)
samp.storage.remove(key)
ItemContract
key1–64 ASCII characters; starts with a letter or digit; remaining characters may also use _, -, ..
valuestring, boolean, or finite number.
Missing keyget returns the supplied default, or nil.
String sizeAt most 16 KiB per value.
Plugin quotaAt most 128 entries and 1 MiB encoded data.

set and remove return nothing. Removing a missing key succeeds. The current session uses an in-memory cache; disk writes are handled by a bounded asynchronous queue. A plugin may queue at most 64 distinct-key writes, and unload waits for that plugin's pending writes. Temporary and backup files allow the host to recover a value after an interrupted write.

Formatting ​

samp.format.number(value [, precision]) ​

Returns a locale-independent decimal string. value must be finite and have absolute value at most 9,000,000,000,000. precision is an integer 0..6, default 0. The result is rounded to the requested fixed precision.

Game state ​

samp.game.state() ​

Requires game.state.read and returns:

FieldTypeMeaning
sessionIdintegerCurrent runtime session identity.
playerGenerationintegerCurrent local-player generation.
readybooleanGame services are available.
pausedbooleanThe game is paused.
multiplayerbooleanA multiplayer runtime exists.
localPlayerAvailablebooleanA local-player Handle can currently be acquired.
interiorintegerActive interior ID, or 0 when unavailable.

The table is a snapshot; call again for fresh state.

Current server ​

samp.server.current() ​

Requires server.state.read. Returns nil without a multiplayer runtime; otherwise returns:

FieldTypeMeaning
sessionIdintegerSession to which this snapshot belongs.
addressstringServer host or IP.
portintegerServer port.
namestringUTF-8 server name; may be empty before it is known.
statestringwaiting, connecting, connected, joining, restarting, or unknown.
connectedbooleanFully connected.
connectingbooleanConnection or join is in progress.
lanbooleanLAN mode flag.

World, checkpoint, and camera snapshots ​

samp.world.time() ​

Requires game.state.read. Returns { hour, minute } when the game clock is available and valid, otherwise nil. The value is a snapshot of the current game clock; it is not a promise that the server will apply a setting on the next frame.

samp.world.weather() ​

Requires game.state.read. Returns { weather, holdTime } or nil when the network world settings are unavailable. holdTime reports whether the server has locked world time.

samp.checkpoint.state() ​

Requires game.state.read. Returns { normal, race }, where each present checkpoint contains its position and shape-specific fields (extent for a normal checkpoint, or radius and raceType for a race checkpoint). Missing checkpoints are nil.

samp.camera.state() ​

Requires game.state.read. Returns nil when the camera is unavailable; otherwise it returns a snapshot:

lua
{
    position = Vector3,
    direction = Vector3,
    up = Vector3,
    mode = integer,
    fov = number
}

The snapshot is read-only. Camera control is exposed separately through the managed camera.follow effect.

Network statistics ​

samp.network.stats() ​

Requires network.stats.read and returns a read-only transport snapshot:

lua
{
    queuedPackets = integer,
    queueHighWatermark = integer,
    receivedPackets = integer,
    receivedBytes = integer,
    sentPackets = integer,
    sentBytes = integer,
    droppedRealtime = integer,
    rejectedMalformed = integer,
    maxDispatchAgeMs = integer,
    droppedInspectionEvents = integer,
    interceptionBypasses = integer
}

droppedRealtime is local client queue pressure, not an Internet packet-loss measurement. Network event payloads are bounded and are delivered on the next managed frame; they cannot be used to synchronously rewrite packet contents.

Audio ​

samp.audio.play(url), samp.audio.stop(), and samp.audio.state() ​

These functions require audio.playback. A successful play gives the calling plugin ownership of the current stream; a later play replaces it. Plugins can stop only the stream they currently own, and unload automatically stops streams owned by that plugin.

lua
samp.audio.play("https://example.com/stream.ogg")
local state = samp.audio.state()
if state and state.playing then
    samp.audio.stop()
end

state() returns { playing, owned, url }.

Chat, commands, and clipboard ​

samp.chat.notify(message [, color]) ​

Requires ui.chat. Shows a local-only notification and never sends a server message. color is an optional ARGB integer; messages must be valid UTF-8 and are limited to 1,024 bytes.

samp.chat.send(message) and samp.command.send(command) ​

Require chat.send. Requests use the same bounded queue as user input and are still passed through the corresponding outgoing interception events. Chat text must not start with /; commands must start with / and contain another character. NUL, CR, and LF are rejected.

samp.clipboard.get() and samp.clipboard.set(text) ​

get() requires ui.clipboard.read; set() requires ui.clipboard.write. Reads return the current UTF-8 clipboard snapshot or nil when unavailable. Writes are delivered asynchronously to the UI thread; each value is limited to 16 KiB.