Skip to content

Network protocol

Network sends tables between main.lua and server.lua. Define a small protocol instead of accumulating unrelated fields.

Network:SendTable({
kind = "settings",
enabled = true,
threshold = 30
})

The receiver dispatches by message type first:

Network:OnTableReceived(function(data)
if data.kind == "settings" then
-- Apply settings
elseif data.kind == "request_state" then
-- Send state
end
end)

A useful naming scheme:

  • set_settings: client supplies settings;
  • request_state: client requests a snapshot;
  • state: server sends authoritative state;
  • event: server reports something that happened.

SendTable() returns nil, not a response. A response is a separate incoming message.

Send strings, numbers, booleans, nested tables, and sequential tables. Break structures into numbers:

local function PackVector3(value)
return {
x = value.x,
y = value.y,
z = value.z
}
end

Vector3, Agent, Texture, functions, and nil fields are not preserved.

The sandbox does not expose type, so use safe conversions and explicit comparisons:

local function ApplySettings(data)
local threshold = tonumber(data.threshold)
if threshold ~= nil then
threshold = math.max(1, math.min(100, threshold))
State.threshold = threshold
end
State.enabled = data.enabled == true
end

Never use a client number as an index, distance, or duration without bounds.

Send when state changes:

local LastHealth = nil
local function SendHealthIfChanged(health)
if health == LastHealth then
return
end
LastHealth = health
Network:SendTable({
kind = "health_state",
health = health
})
end

Both sides should recover regardless of startup order:

  1. the server starts with safe defaults;
  2. the client registers its receiver;
  3. the client sends settings;
  4. the client requests state;
  5. the server responds with a full snapshot.

See the complete Reflex module for the full pattern.