Server Registry
A live list of every server running your game. Call RegisterServer once at startup — the module maintains a heartbeat and removes the entry automatically when the server closes or crashes.
Cross.RegisterServer()
Register this server in the shared registry. Optionally attach any metadata table — player count, game mode, map, etc. — which is visible to GetServers() on other servers.
Starts a 30-second heartbeat to keep the entry alive (entries expire after 90 seconds). Also updates the player count automatically on PlayerAdded / PlayerRemoving. Registers a game:BindToClose handler to remove the entry on graceful shutdown.
local Cross = RoExpress.Cross
-- call once at the top of a server Script
Cross.RegisterServer({
mode = "pvp",
map = "Forest",
ranked = true,
})
Cross.GetServers()
Returns all currently registered servers as a table of ServerEntry objects. Entries that have not been refreshed within 90 seconds are expired automatically by MemoryStore.
ServerEntry
| Field | Type | Description |
|---|---|---|
id | string | Server's JobId (unique per server instance) |
place | number | PlaceId the server is running |
players | number | Current player count, refreshed on join/leave |
meta | table | Metadata passed to RegisterServer |
ts | number | os.time() of the last heartbeat |
local servers = Cross.GetServers()
print(#servers, "servers online")
for _, s in servers do
print(s.id, "| players:", s.players, "| map:", s.meta.map)
end
Cross.UnregisterServer()
Immediately remove this server from the registry and stop the heartbeat. Useful for maintenance mode or before a forced restart. The entry also removes itself automatically on server close.
-- put the server into maintenance mode
Cross.UnregisterServer()
Cross.Publish("server.maintenance", { id = Cross.ServerId() })
-- kick all players after a delay...
Cross.ServerId()
Returns this server's unique identifier — game.JobId in a live server, a generated GUID in Studio. Stable for the lifetime of the server process.
print("This server:", Cross.ServerId())
-- exclude self when routing messages to other servers
local others = {}
for _, s in Cross.GetServers() do
if s.id ~= Cross.ServerId() then
table.insert(others, s)
end
end
Pattern: matchmaking server selection
local TeleportService = game:GetService("TeleportService")
local Cross = RoExpress.Cross
local function FindBestServer(mode: string)
local servers = Cross.GetServers()
local best
for _, s in servers do
if s.meta.mode == mode and s.players < 20 then
if not best or s.players > best.players then
best = s -- pick least-empty server with room
end
end
end
return best
end
local function JoinOrCreate(player: Player, mode: string)
local server = FindBestServer(mode)
if server then
TeleportService:TeleportToPlaceInstance(game.PlaceId, server.id, player)
else
TeleportService:TeleportAsync(game.PlaceId, { player })
end
end
UnregisterServer, its registry entry expires after 90 seconds. GetServers() called after that will not include the crashed server.See also
← Cross · Messaging | real-time events across servers · Shared Memory | persistent key-value state