API Gateway Multi-System Support
Overview
The API gateway filters state broadcasts so players only receive entities in their current star system. It also exposes system metadata via REST and WebSocket endpoints, and tracks which system each player’s active ship is in.
With only Sol existing today, behavior is identical to the single-system baseline — this is pure infrastructure for multi-system support.
Per-System State Filtering
Broadcast Loop
In handle_tick_completed, after fetching all entities from the physics
service, the gateway groups them by system_id before iterating over
connections:
bodies_by_system = defaultdict(list)
stations_by_system = defaultdict(list)
jumpgates_by_system = defaultdict(list)
ships_by_system = defaultdict(list)
For each connection:
- Look up the ship’s
system_idfrom the proto data (default"sol") - Send only entities matching that system
- The player’s own ship is always included regardless of system
Backward Compatibility
When system_id is empty or "sol", the player receives all Sol entities —
identical to the pre-multi-system behavior.
New Endpoints
REST: GET /api/admin/systems
Admin-only endpoint that calls the galaxy service’s ListSystems gRPC method.
Returns:
{
"systems": [
{
"id": "sol",
"name": "Sol",
"star_body": "Sun",
"position": {"x": 0.0, "y": 0.0, "z": 0.0}
}
]
}
WebSocket: request_systems → galaxy:systems
Client sends {"type": "request_systems"}. Server responds with:
{
"type": "galaxy:systems",
"systems": [
{
"id": "sol",
"name": "Sol",
"star_body": "Sun",
"position": {"x": 0.0, "y": 0.0, "z": 0.0}
}
]
}
Player System Tracking
Welcome Message
The welcome message includes system_id — read from Redis
ship:{ship_id} → system_id at connection time (default "sol").
Fleet List
Each ship in the fleet_list response includes system_id from Redis
(default "sol").
Galaxy gRPC Client
The API gateway connects to the galaxy service at GALAXY_GRPC_HOST
(default galaxy:50051). The GrpcClients class manages a
GalaxyStub alongside existing physics/players/tick-engine stubs.
Dynamic Body Config (#732)
Body broadcast includes parent_body
Each body in the WebSocket state broadcast includes a parent_body field
derived from the shared BODY_PARENTS config and body type:
| Body type | parent_body value |
|---|---|
| Star | null |
| Planet | Star body name (e.g., "Sun") — resolved from SYSTEMS[system_id].star_body |
| Moon | Parent planet name (e.g., "Earth") — from BODY_PARENTS shared config |
Source: ws_state_broadcast.py body dict construction.
Client dynamic body hierarchy
bodyConfig.js no longer hardcodes the planet list in BODY_PARENTS.
Instead:
BODY_PARENTSstarts as an empty object{}updateBodyHierarchy(bodyData)rebuildsBODY_PARENTSfrom each body’sparent_bodyfield on every state updategetPlanetOrder(bodyData)returns planet names sorted by distance from the parent star, replacing the hardcodedplanetOrderarraygetSystemName(systemId)resolves a display name fromsharedConfig.SYSTEMS
System HUD indicator
A <span id="status-system"> in the status bar shows the current system name
(e.g., “Sol”) in gold color (#ffdd44). Updated from the welcome message’s
system_id via getSystemName().
Configuration
GALAXY_GRPC_HOST is already defined in k8s/base/configmaps.yaml
as part of the galaxy-config ConfigMap.