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:

  1. Look up the ship’s system_id from the proto data (default "sol")
  2. Send only entities matching that system
  3. 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_systemsgalaxy: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_PARENTS starts as an empty object {}
  • updateBodyHierarchy(bodyData) rebuilds BODY_PARENTS from each body’s parent_body field on every state update
  • getPlanetOrder(bodyData) returns planet names sorted by distance from the parent star, replacing the hardcoded planetOrder array
  • getSystemName(systemId) resolves a display name from sharedConfig.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.


Back to top

Galaxy — Kubernetes-based multiplayer space game

This site uses Just the Docs, a documentation theme for Jekyll.