Skip to main content

Player

Player is a server-side Lua service for connected-player moderation/control operations.

Error Handling Pattern​

  • Success: err == nil
  • Failure: err contains an error code string

Scope Model​

  • Player is available on server runtime only.
  • There is no client Player table API.

Identifier Model​

  • Player targeting uses a unified selector:
  • number -> playerId (session id)
  • string prefixed c_ -> clientId
  • string prefixed a_ -> accountId
  • For persistent systems, use accountId first (fallback clientId), not session playerId.

playerId is not a long-term persistence key.

Function List​

FunctionDescriptionScope
Player.KickSends a kick notification to a player.S
Player.BanSends a ban notification to a player.S
Player.UnbanRemoves a persisted ban entry.S
Player.GetBansLists persisted bans.S

Event List​

EventDescriptionScope
player:connectedEvent-bus event emitted when a player session connects.S
player:disconnectedEvent-bus event emitted when a player session disconnects.S
player:updatedEvent-bus event emitted when runtime player identity fields change.S
player:kickedEvent-bus event emitted after Player.Kick(...).S
player:bannedEvent-bus event emitted after Player.Ban(...).S
player:unbannedEvent-bus event emitted after Player.Unban(...).S

Event Payload Contract​

Every player event handler receives the standard event envelope:

  • event.name
  • event.payload
  • event.source
  • event.target
  • event.timestamp
  • event.correlationId
  • event.version

event.payload fields by event:

EventPayload Fields
player:connectedplayerId, clientId, accountId, displayName, role, connectedAt, loggedIn
player:disconnectedplayerId, clientId, accountId, displayName, role, connectedAt, loggedIn, reason
player:updatedplayerId, clientId, accountId, displayName, role, connectedAt, loggedIn, reason
player:kickedplayerId, clientId, accountId, displayName, role, connectedAt, loggedIn, reason
player:bannedplayerId, clientId, accountId, displayName, role, connectedAt, loggedIn, reason
player:unbannedtargetKind, targetId, updatedBy

Functions​

Player.Kick​

S Server Only

local err = Player.Kick(target, reason)

Parameters:

  • target (number|string)
  • reason (string, optional)

target resolution rules:

  • number -> playerId (session id)
  • string prefixed c_ -> clientId
  • string prefixed a_ -> accountId
  • otherwise -> ERR_INVALID_TARGET

Behavior:

  • clientId / accountId targets must resolve to an online session.
  • If no online match exists, return ERR_NOT_ONLINE.
  • Client-side admin UIs cannot call Player.Kick directly; they must send a server-targeted event/command and let server Lua call Player.Kick.

Example:

local err = Player.Kick(12, "AFK")
if err then
print("Kick failed: " .. err)
end

Player.Ban​

S Server Only

local err = Player.Ban(target, reason)

Parameters:

  • target (number|string)
  • reason (string)

Notes:

  • Runtime sends a ban notification and disconnect reason.
  • Ban records are persisted in server SQLite storage (runtime/mtadm.db, bans table) using clientId, accountId, and IP when available.
  • Active client-id bans are enforced on reconnect.
  • target resolution rules are identical to Player.Kick.
  • Client-side admin UIs cannot call Player.Ban directly; they must send a server-targeted event/command and let server Lua call Player.Ban.

Example:

local err = Player.Ban("a_8c1d2e3f", "cheat_detected")
if err then
print("Ban failed: " .. err)
end

Player.Unban​

S Server Only

local err = Player.Unban(target)

Parameters:

  • target (table|string)

Supported target formats:

  • { targetKind = "account", targetId = "a_123" }
  • { targetKind = "client", targetId = "c_123" }
  • { targetKind = "ip", targetId = "127.0.0.1" }
  • "account:a_123"
  • "client:c_123"
  • "ip:127.0.0.1"

Example:

local err = Player.Unban({
targetKind = "account",
targetId = "a_8c1d2e3f"
})
if err then
print("Unban failed: " .. err)
end

Player.GetBans​

S Server Only

local bans, err = Player.GetBans(options)

Parameters:

  • options.limit (number, optional)

Returns:

  • bans (table)
  • err (string|nil)

Each ban row contains:

  • key
  • targetKind
  • targetId
  • reason
  • createdAt
  • updatedAt
  • updatedBy
  • bannedBy

Example:

local bans, err = Player.GetBans({ limit = 100 })
if not err then
for _, ban in ipairs(bans) do
print(ban.targetKind .. ":" .. ban.targetId .. " -> " .. ban.reason)
end
end
  • Role/account management: Auth
  • Runtime identity/roster lookup: Connection
  • Replicated player view data: Node (/NodePlayers, read model)

NodePlayers Relationship​

  • Player is for control/moderation actions (Kick, Ban).
  • NodePlayers is for replicated read state (position/visual state), not moderation authority.
  • Do not store moderation state in NodePlayers; persist moderation via storage/auth flows.

Events​

player:connected (Event Bus)​

S Server Only

AddEventHandler("player:connected", function(event)
print(
"Connected pid=" .. tostring(event.payload.playerId) ..
" cid=" .. tostring(event.payload.clientId) ..
" aid=" .. tostring(event.payload.accountId)
)
end)

player:disconnected (Event Bus)​

S Server Only

AddEventHandler("player:disconnected", function(event)
print(
"Disconnected pid=" .. tostring(event.payload.playerId) ..
" cid=" .. tostring(event.payload.clientId) ..
" aid=" .. tostring(event.payload.accountId) ..
" reason=" .. tostring(event.payload.reason)
)
end)

player:updated (Event Bus)​

S Server Only

AddEventHandler("player:updated", function(event)
print(
"Updated pid=" .. tostring(event.payload.playerId) ..
" role=" .. tostring(event.payload.role) ..
" loggedIn=" .. tostring(event.payload.loggedIn) ..
" reason=" .. tostring(event.payload.reason)
)
end)

player:kicked (Event Bus)​

S Server Only

AddEventHandler("player:kicked", function(event)
local playerId = event.payload.playerId
local clientId = event.payload.clientId
local accountId = event.payload.accountId
local reason = event.payload.reason
print(
"Player kicked: pid=" .. tostring(playerId) ..
" cid=" .. tostring(clientId) ..
" aid=" .. tostring(accountId) ..
" reason=" .. tostring(reason)
)
end)

player:banned (Event Bus)​

S Server Only

AddEventHandler("player:banned", function(event)
local playerId = event.payload.playerId
local clientId = event.payload.clientId
local accountId = event.payload.accountId
local reason = event.payload.reason
print(
"Player banned: pid=" .. tostring(playerId) ..
" cid=" .. tostring(clientId) ..
" aid=" .. tostring(accountId) ..
" reason=" .. tostring(reason)
)
end)

player:unbanned (Event Bus)​

S Server Only

AddEventHandler("player:unbanned", function(event)
print(
"Player unbanned: " ..
tostring(event.payload.targetKind) .. ":" ..
tostring(event.payload.targetId) ..
" by " .. tostring(event.payload.updatedBy)
)
end)

Function/Event Mapping​

FunctionEmitted Event
Player.Kick(target, reason)player:kicked
Player.Ban(target, reason)player:banned
Player.Unban(target)player:unbanned

Error Codes​

Player.Kick should return:

  • ERR_INVALID_TARGET
  • ERR_NOT_ONLINE
  • ERR_PERMISSION_DENIED
  • ERR_TRANSPORT_FAILED
  • ERR_NOT_CONNECTED

Player functions currently use direct runtime actions unless otherwise documented.

Player.Ban may additionally return:

  • ERR_STORAGE_UNAVAILABLE

Player.Unban / Player.GetBans may additionally return:

  • ERR_STORAGE_UNAVAILABLE
  • ERR_NOT_FOUND

Quick Example​

Kick and react using event bus:

AddEventHandler("player:kicked", function(event)
print("Audit: kicked aid=" .. tostring(event.payload.accountId) .. " pid=" .. tostring(event.payload.playerId))
end)

local err = Player.Kick("a_8c1d2e3f", "AFK")

Server moderation + player read-model correlation:

AddEventHandler("player:kicked", function(event)
local kickedPlayerId = event.payload.playerId

local node, err = Node.Get("/NodePlayers/" .. tostring(kickedPlayerId))
if not err and node then
-- correlate moderation event with latest replicated player view data
-- for audit/telemetry pipelines
end
end)