Skip to main content

Node

Node provides the runtime graph API for world/map objects, replicated player view data, client-only visuals, and client UI.

Planned Role In Maps And Editor Workflows​

Node is the runtime graph API for map/world content.

Use Node for:

  • placed static props
  • triggers
  • checkpoints
  • spawn markers
  • replicated map/world nodes
  • editor-authored world entities

Do not plan a separate Object API for the same domain unless there is a hard runtime boundary that Node cannot cover.

Recommended ownership split:

  • Map:
    • loads/unloads baked maps
    • owns baked static world content lifecycle
  • Node:
    • represents the static/dynamic world graph objects after load
  • Environment:
    • remains the runtime environment authority
  • Vehicle:
    • owns deterministic vehicle entities

This keeps the public API surface smaller and avoids overlapping object systems.

Error Handling Pattern​

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

Domain Model​

  • NodeSim: deterministic gameplay/simulation objects (server authoritative).
  • NodeSharedVisual: replicated visual objects approved by server.
  • NodePlayers: replicated player view model (read-only on client).
  • NodeClientVisual: client-only visual objects (not replicated).
  • NodeUI: client-only UI objects (not replicated).
  • Runtime-owned baseline world visuals (for example Systems/World/Always/OceanRoot/Ocean) are outside script-created node domains.

Access Matrix​

DomainServer ReadServer WriteClient ReadClient WriteReplicated
NodeSimYesYesYesNoYes
NodeSharedVisualYesYesYesNoYes
NodePlayersYesYesYesNoYes
NodeClientVisualNoNoYesYesNo
NodeUINoNoYesYesNo

Notes:

  • Client writes to server domains must go through Node.RequestSim(...).
  • Resource scripts can only write inside their own resource subtree.

Function List​

FunctionDescriptionScope
Node.GetRootGet restricted root handle for node domains.S
Node.GetRead one node by path or id.S
Node.ListList child nodes with optional filters.S
Node.CreateCreate a node in an allowed domain.S
Node.UpdatePatch mutable node fields.S
Node.DeleteDelete a node.S
Node.SubscribeSubscribe to node graph changes.S
Node.UnsubscribeRemove a subscription.S
Node.RequestSimClient request for server-side sim mutations.C
Node.GetSpawnPointsRead spawn point definitions.S

Event List​

EventDescriptionScope
node:createdFired after node creation.S
node:updatedFired after node update.S
node:deletedFired after node deletion.S
node:movedFired after node parent/path change.S

Path and Ownership Model​

Canonical roots:

  • /NodeSim/resources/{resourceName}/...
  • /NodeSharedVisual/resources/{resourceName}/...
  • /NodePlayers/{playerId}/...
  • /NodeClientVisual/resources/{resourceName}/...
  • /NodeUI/resources/{resourceName}/...

Ownership rules:

  • A resource can write only to /.../resources/{itsOwnResourceName}/....
  • Cross-resource writes return ERR_RESOURCE_SCOPE.
  • Client reads NodePlayers for remote-player visuals; this does not grant authority.
  • Runtime-managed systems may create internal nodes in NodeClientVisual; scripts should treat unknown runtime-owned nodes as read-only.

Identifier bridge:

  • NodePlayers is keyed by session playerId in path.
  • if your script starts with accountId or clientId, resolve current session via Connection.GetPlayer(target) first, then read /NodePlayers/{playerId}.

Node Data Contract​

Common node fields:

  • id (string)
  • path (string)
  • name (string)
  • domain (string)
  • resource (string or nil)
  • kind (string)
  • parentId (string or nil)
  • revision (number)
  • createdAt (number, ms epoch)
  • updatedAt (number, ms epoch)
  • tags (table or nil)

Spatial fields (when applicable):

  • transform.position (x, y, z)
  • transform.rotation (x, y, z)
  • transform.scale (x, y, z)

Player view nodes should expose:

  • playerId (session id)
  • clientId (stable install id)
  • accountId (persistent account id or nil)

Concurrency and Revision Model​

Write operations (Create/Update/Delete) support optimistic concurrency:

  • options.expectedRevision can be passed by caller.
  • mismatch returns ERR_REVISION_CONFLICT.

Use revision from the latest read before updating.

Functions​

Node.GetRoot​

S Shared (Client & Server)

local root, err = Node.GetRoot()

Returns:

  • root (table): NodeSim, NodeSharedVisual, NodePlayers, NodeClientVisual, NodeUI
  • err (nil | string)

Node.Get​

S Shared (Client & Server)

local node, err = Node.Get(pathOrId)

Parameters:

  • pathOrId (string)

Returns:

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

Node.List​

S Shared (Client & Server)

local nodes, err = Node.List(path, options)

Parameters:

  • path (string)
  • options (table, optional):
  • recursive (boolean, default false)
  • limit (number)
  • kind (string | table)
  • resource (string)

Returns:

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

Node.Create​

S Shared (Domain-Restricted)

local nodeId, err = Node.Create(domain, parentPath, kind, props, options)

Parameters:

  • domain (NodeSim | NodeSharedVisual | NodePlayers | NodeClientVisual | NodeUI)
  • parentPath (string)
  • kind (string)
  • props (table)
  • options (table, optional):
  • expectedRevision (number)

Returns:

  • nodeId (string | nil)
  • err (nil | string)

Node.Update​

S Shared (Domain-Restricted)

local err = Node.Update(pathOrId, patch, options)

Parameters:

  • pathOrId (string)
  • patch (table)
  • options (table, optional):
  • expectedRevision (number)

Returns:

  • err (nil | string)

Node.Delete​

S Shared (Domain-Restricted)

local err = Node.Delete(pathOrId, options)

Parameters:

  • pathOrId (string)
  • options (table, optional):
  • expectedRevision (number)

Returns:

  • err (nil | string)

Node.Subscribe​

S Shared (Client & Server)

local subId, err = Node.Subscribe(pathOrPattern, handler, options)

Parameters:

  • pathOrPattern (string)
  • handler (function): receives standard event envelope.
  • options (table, optional):
  • events (table): subset of node:created, node:updated, node:deleted, node:moved

Returns:

  • subId (string | nil)
  • err (nil | string)

Node.Unsubscribe​

S Shared (Client & Server)

local err = Node.Unsubscribe(subId)

Parameters:

  • subId (string)

Returns:

  • err (nil | string)

Node.RequestSim​

C Client Only

local requestId, err = Node.RequestSim(action, payload, options)

Parameters:

  • action (string): server-defined sim mutation action.
  • payload (table)
  • options (table, optional):
  • reliable (boolean, default true)
  • correlationId (string)

Returns:

  • requestId (string | nil)
  • err (nil | string)

Node.GetSpawnPoints​

S Shared (Client & Server)

local points, err = Node.GetSpawnPoints(options)

Parameters:

  • options (table, optional):
  • group (string)
  • resource (string)

Returns:

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

Events​

All node events use the standard event envelope:

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

node:created (Event Bus)​

Payload:

  • id, path, domain, resource, kind, revision

node:updated (Event Bus)​

Payload:

  • id, path, domain, patch, revision

node:deleted (Event Bus)​

Payload:

  • id, path, domain, revision

node:moved (Event Bus)​

Payload:

  • id, oldPath, newPath, oldParentId, newParentId, revision

Deterministic Policy​

  • NodeSim is deterministic simulation state.
  • Client direct writes to NodeSim are denied (ERR_PERMISSION_DENIED).
  • Server should apply NodeSim mutations in deterministic tick flow.
  • NodeSharedVisual, NodeClientVisual, and NodeUI are non-deterministic visual domains.
  • Environment for sky/weather/time world visuals.
  • Camera for camera lifecycle/attach/view-mode APIs (internally backed by client visual nodes).
  • UI for high-level client interface trees (internally backed by NodeUI).
  • Player for moderation and control operations.
  • Connection for online roster and identity lookup.
  • Auth for account identity/roles.

Error Codes​

  • ERR_INVALID
  • ERR_NOT_FOUND
  • ERR_PERMISSION_DENIED
  • ERR_RESOURCE_SCOPE
  • ERR_REVISION_CONFLICT
  • ERR_DETERMINISTIC_POLICY
  • ERR_INVALID_DOMAIN
  • ERR_INVALID_PATH

Quick Examples​

Server create deterministic obstacle:

local nodeId, err = Node.Create("NodeSim", "/NodeSim/resources/map_race01", "box_collider", {
name = "obstacle_01",
transform = {
position = { x = 120, y = 4, z = 30 },
rotation = { x = 0, y = 0, z = 0 },
scale = { x = 2, y = 2, z = 2 }
}
})

Client create local HUD widget:

local uiId, err = Node.Create("NodeUI", "/NodeUI/resources/my_hud", "button", {
name = "spectate_btn",
text = "Spectate"
})

Client request server-side sim mutation:

local requestId, err = Node.RequestSim("spawn_checkpoint", {
map = "race01",
checkpointId = "cp_12"
})

Resolve accountId -> NodePlayers path:

local player, err = Connection.GetPlayer("a_9d4d7c2f")
if err then return end

local node, nodeErr = Node.Get("/NodePlayers/" .. tostring(player.playerId))
if not nodeErr and node then
local pos = node.transform and node.transform.position
end