15d35f6f1f
Engine no longer mints its own game UUID. The orchestrator (backend)
generates the game UUID at game-create time and passes it in the
admin/init request body as the required `gameId` field, so the value
that names the engine container and host bind-mount directory also
ends up inside the engine's state.json.
The engine rejects the zero UUID with 400 and any init that conflicts
with an existing state.json with 409 (a second init on the same gameId
is also a conflict; full idempotency is not part of the contract).
Updates rest.InitRequest, openapi.yaml (schema + 409 response),
controller.GenerateGame/NewGame/buildGameOnMap signatures, the engine
HTTP handler/executor, the backend runtime worker, and the relevant
unit and contract tests. Documentation in game/README.md,
docs/ARCHITECTURE.md, backend/README.md, and backend/docs/{runtime,flows}.md
is updated in the same patch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1376 lines
44 KiB
YAML
1376 lines
44 KiB
YAML
openapi: 3.0.3
|
||
info:
|
||
title: Galaxy Game Service REST API
|
||
version: v1
|
||
description: |
|
||
This specification documents the REST contract of `galaxy/game`.
|
||
|
||
The service hosts a single game instance and exposes endpoints for game
|
||
initialization, turn advancement, game-state queries, player reports, and
|
||
batched player command execution.
|
||
|
||
Transport rules:
|
||
- request bodies are JSON
|
||
- `PUT /api/v1/command` is rate-limited to one concurrent execution;
|
||
requests that cannot acquire the execution slot within 100 ms receive
|
||
`504 Gateway Timeout`
|
||
- `501 Not Implemented` is returned without a body when the game has not
|
||
been initialized
|
||
- request-binding validation errors return `400` with `{"error": "message"}`
|
||
- structural input errors and game-state rejections that escape to
|
||
HTTP return `400` with `{"generic_error": "message", "code": integer}`;
|
||
the `code` carries the engine's `GenericError` code (see
|
||
`pkg/error/generic.go` — shelf `2xxx` for structural input and
|
||
`3xxx` for game-state rejection)
|
||
- on `PUT /api/v1/order`, game-state rejections do not become HTTP
|
||
errors; the engine returns `202 Accepted` with the full
|
||
`UserGamesOrder` body and reports the failure on the offending
|
||
command via `cmdApplied=false` and `cmdErrorCode=<integer>`
|
||
- internal engine failures return `500` with
|
||
`{"generic_error": "message", "code": integer}` (code on shelf `1xxx`)
|
||
or `{"error": "message"}` for unclassified failures
|
||
servers:
|
||
- url: http://localhost:8080
|
||
description: Default local listener for Game Service.
|
||
tags:
|
||
- name: GameLifecycle
|
||
description: Game initialization, state retrieval, and turn advancement.
|
||
- name: PlayerActions
|
||
description: Player command execution, order validation, and turn-report retrieval.
|
||
- name: Health
|
||
description: Technical liveness probes used by Runtime Manager and operator tooling.
|
||
paths:
|
||
/api/v1/admin/status:
|
||
get:
|
||
tags:
|
||
- GameLifecycle
|
||
operationId: adminGetGameStatus
|
||
summary: Get the current game state
|
||
description: |
|
||
Returns the current game state including turn number, stage, and a
|
||
summary of all players. Returns `501` if the game has not yet been
|
||
initialized. Routed only from the trusted network segment that
|
||
connects `Game Master` to the engine container.
|
||
responses:
|
||
"200":
|
||
description: Current game state.
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/StateResponse"
|
||
"501":
|
||
description: Game has not been initialized yet.
|
||
"500":
|
||
$ref: "#/components/responses/InternalError"
|
||
/api/v1/admin/init:
|
||
post:
|
||
tags:
|
||
- GameLifecycle
|
||
operationId: adminInitGame
|
||
summary: Initialize a new game
|
||
description: |
|
||
Generates a new game instance with the supplied canonical
|
||
`gameId` and list of races. Requires at least 10 race entries.
|
||
The engine refuses to overwrite an already-initialised storage
|
||
directory (responds with 409). Routed only from the trusted
|
||
network segment that connects `Game Master` to the engine
|
||
container.
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/InitRequest"
|
||
responses:
|
||
"201":
|
||
description: Game initialized successfully.
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/StateResponse"
|
||
"400":
|
||
$ref: "#/components/responses/ValidationError"
|
||
"409":
|
||
$ref: "#/components/responses/ConflictError"
|
||
"500":
|
||
$ref: "#/components/responses/InternalError"
|
||
/api/v1/admin/race/banish:
|
||
post:
|
||
tags:
|
||
- GameLifecycle
|
||
operationId: adminBanishRace
|
||
summary: Deactivate a race after a permanent platform-level removal
|
||
description: |
|
||
Deactivates the named race in the running engine. Called by `Game
|
||
Master` after a Lobby-driven permanent membership removal. Routed
|
||
only from the trusted network segment that connects `Game Master`
|
||
to the engine container.
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/BanishRequest"
|
||
responses:
|
||
"204":
|
||
description: Race deactivated; no response body.
|
||
"400":
|
||
$ref: "#/components/responses/ValidationError"
|
||
"500":
|
||
$ref: "#/components/responses/InternalError"
|
||
/api/v1/report:
|
||
get:
|
||
tags:
|
||
- PlayerActions
|
||
operationId: getReport
|
||
summary: Get a player turn report
|
||
description: |
|
||
Returns the full game report for the specified player and turn.
|
||
`player` must be a non-blank race name. `turn` defaults to `0`.
|
||
parameters:
|
||
- $ref: "#/components/parameters/PlayerParam"
|
||
- $ref: "#/components/parameters/TurnParam"
|
||
responses:
|
||
"200":
|
||
description: Player turn report.
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/Report"
|
||
"400":
|
||
$ref: "#/components/responses/ValidationError"
|
||
"500":
|
||
$ref: "#/components/responses/InternalError"
|
||
/api/v1/command:
|
||
put:
|
||
tags:
|
||
- PlayerActions
|
||
operationId: executeCommands
|
||
summary: Execute a batch of player commands
|
||
description: |
|
||
Applies one or more game commands for the specified actor. Serialized
|
||
to one concurrent execution; requests that cannot acquire the execution
|
||
slot within 100 ms return `504 Gateway Timeout`. Returns `202 Accepted`
|
||
with no body on success. Reserved for future use; player order
|
||
submissions go through `/api/v1/order`.
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/CommandRequest"
|
||
responses:
|
||
"202":
|
||
description: All commands accepted.
|
||
"400":
|
||
$ref: "#/components/responses/ValidationError"
|
||
"504":
|
||
description: Command execution slot not acquired within 100 ms.
|
||
"500":
|
||
$ref: "#/components/responses/InternalError"
|
||
/api/v1/order:
|
||
put:
|
||
tags:
|
||
- PlayerActions
|
||
operationId: validateOrder
|
||
summary: Validate and store a player order without executing it
|
||
description: |
|
||
Validates and stores the game commands without executing them. The
|
||
engine applies each command in submission order against a transient
|
||
view of the game state, records the per-command outcome on the
|
||
command's meta, and persists the resulting `UserGamesOrder` so
|
||
clients can reload the same per-command verdict via
|
||
`GET /api/v1/order`.
|
||
|
||
On success returns `202 Accepted` with the stored order; the
|
||
engine-assigned `updatedAt` timestamp is used by clients to detect
|
||
stale submissions. Game-state rejections (e.g. a "produce ship of
|
||
class X" command after class X was removed) are reported per
|
||
command via `cmdApplied=false` and `cmdErrorCode=<integer>` inside
|
||
the same `202` response — they do **not** become a `400` or `500`
|
||
on the whole order. Order-level structural rejections (e.g. a
|
||
`quit` command that is not the last command in the order) return
|
||
`400`.
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/CommandRequest"
|
||
responses:
|
||
"202":
|
||
description: |
|
||
Order is stored. Each entry of `cmd` carries `cmdApplied` and
|
||
`cmdErrorCode` describing the per-command outcome; the order
|
||
is considered stored even when some commands were rejected.
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/UserGamesOrder"
|
||
"400":
|
||
$ref: "#/components/responses/ValidationError"
|
||
"500":
|
||
$ref: "#/components/responses/InternalError"
|
||
get:
|
||
tags:
|
||
- PlayerActions
|
||
operationId: getOrder
|
||
summary: Fetch the stored order for a player and turn
|
||
description: |
|
||
Returns the order previously stored by `PUT /api/v1/order` for the
|
||
specified player and turn. Responds `204 No Content` when no order
|
||
has been stored for that turn.
|
||
parameters:
|
||
- $ref: "#/components/parameters/PlayerParam"
|
||
- $ref: "#/components/parameters/TurnParam"
|
||
responses:
|
||
"200":
|
||
description: Stored player order for the requested turn.
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/UserGamesOrder"
|
||
"204":
|
||
description: No order has been stored for this player on this turn.
|
||
"400":
|
||
$ref: "#/components/responses/ValidationError"
|
||
"500":
|
||
$ref: "#/components/responses/InternalError"
|
||
/api/v1/battle/{turn}/{uuid}:
|
||
get:
|
||
tags:
|
||
- PlayerActions
|
||
operationId: getBattle
|
||
summary: Fetch a single battle report
|
||
description: |
|
||
Returns the full `BattleReport` for the supplied `turn` and battle
|
||
identifier. The `turn` segment must be a non-negative integer; the
|
||
`uuid` segment must be a valid RFC 4122 UUID. Responds with
|
||
`404 Not Found` when no battle is stored for the supplied pair.
|
||
parameters:
|
||
- $ref: "#/components/parameters/BattleTurnParam"
|
||
- $ref: "#/components/parameters/BattleIDParam"
|
||
responses:
|
||
"200":
|
||
description: Battle report for the supplied turn and identifier.
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/BattleReport"
|
||
"400":
|
||
$ref: "#/components/responses/ValidationError"
|
||
"404":
|
||
description: No battle exists for the supplied turn and identifier.
|
||
"500":
|
||
$ref: "#/components/responses/InternalError"
|
||
/api/v1/admin/turn:
|
||
put:
|
||
tags:
|
||
- GameLifecycle
|
||
operationId: adminGenerateTurn
|
||
summary: Advance the game to the next turn
|
||
description: |
|
||
Processes the current turn and generates the next one. Returns the
|
||
updated game state. Routed only from the trusted network segment
|
||
that connects `Game Master` to the engine container.
|
||
responses:
|
||
"200":
|
||
description: Updated game state after turn generation.
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/StateResponse"
|
||
"500":
|
||
$ref: "#/components/responses/InternalError"
|
||
/healthz:
|
||
get:
|
||
tags:
|
||
- Health
|
||
operationId: healthz
|
||
summary: Engine liveness probe
|
||
description: |
|
||
Returns `{"status":"ok"}` with HTTP `200` whenever the HTTP server
|
||
is serving requests, regardless of whether the engine has been
|
||
initialised through `POST /api/v1/admin/init`. Used by `Runtime
|
||
Manager` to probe a freshly started container before `init` runs.
|
||
Carries no game-state semantics; use `GET /api/v1/admin/status`
|
||
for game-state inspection.
|
||
responses:
|
||
"200":
|
||
description: Engine HTTP server is up.
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/HealthzResponse"
|
||
components:
|
||
parameters:
|
||
PlayerParam:
|
||
name: player
|
||
in: query
|
||
required: true
|
||
description: Race name of the player requesting the report. Must be non-blank.
|
||
schema:
|
||
type: string
|
||
minLength: 1
|
||
TurnParam:
|
||
name: turn
|
||
in: query
|
||
required: false
|
||
description: Turn number to load the report for. Defaults to 0.
|
||
schema:
|
||
type: integer
|
||
minimum: 0
|
||
default: 0
|
||
BattleTurnParam:
|
||
name: turn
|
||
in: path
|
||
required: true
|
||
description: Turn number the battle was generated on.
|
||
schema:
|
||
type: integer
|
||
minimum: 0
|
||
BattleIDParam:
|
||
name: uuid
|
||
in: path
|
||
required: true
|
||
description: Battle identifier (RFC 4122 UUID).
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
schemas:
|
||
HealthzResponse:
|
||
type: object
|
||
description: Engine liveness probe response payload.
|
||
required:
|
||
- status
|
||
properties:
|
||
status:
|
||
type: string
|
||
description: Always "ok" while the engine HTTP server is serving requests.
|
||
enum:
|
||
- ok
|
||
StateResponse:
|
||
type: object
|
||
description: Summary game state returned after initialization and at each turn boundary.
|
||
required:
|
||
- id
|
||
- turn
|
||
- stage
|
||
- player
|
||
- finished
|
||
properties:
|
||
id:
|
||
type: string
|
||
format: uuid
|
||
description: Unique identifier of this game instance.
|
||
turn:
|
||
type: integer
|
||
minimum: 0
|
||
description: Current turn number.
|
||
stage:
|
||
type: integer
|
||
minimum: 0
|
||
description: Current stage within the turn for games that support state modification.
|
||
player:
|
||
type: array
|
||
description: Summary state for each player participating in the game.
|
||
items:
|
||
$ref: "#/components/schemas/PlayerState"
|
||
finished:
|
||
type: boolean
|
||
description: |
|
||
True exactly once on the turn-generation response that ends the
|
||
game; otherwise false. Server default: false. `Game Master`
|
||
uses this flag as the sole signal to run the platform finish
|
||
flow. The conditional logic that flips it to true lives in
|
||
the engine's domain code and is owned by the engine
|
||
maintainers.
|
||
PlayerState:
|
||
type: object
|
||
description: Brief player state returned as part of the game state response.
|
||
required:
|
||
- id
|
||
- raceName
|
||
- planets
|
||
- population
|
||
- extinct
|
||
properties:
|
||
id:
|
||
type: string
|
||
format: uuid
|
||
description: Unique player identifier within this game.
|
||
raceName:
|
||
type: string
|
||
description: Name of the player's race.
|
||
planets:
|
||
type: integer
|
||
minimum: 0
|
||
description: Number of planets currently owned by the player.
|
||
population:
|
||
type: number
|
||
description: Total population summed across all player planets.
|
||
extinct:
|
||
type: boolean
|
||
description: True when the race has been eliminated or voluntarily quit.
|
||
InitRequest:
|
||
type: object
|
||
description: |
|
||
Initialization request specifying the canonical game identity
|
||
and the race list for a new game. `gameId` is generated by the
|
||
orchestrator (the platform's backend) before the engine
|
||
container is launched; the engine rejects the zero UUID and
|
||
any value that conflicts with an existing `state.json` on
|
||
disk.
|
||
required:
|
||
- gameId
|
||
- races
|
||
properties:
|
||
gameId:
|
||
type: string
|
||
format: uuid
|
||
description: |
|
||
Canonical game identity supplied by the orchestrator. Must
|
||
be a non-zero UUID.
|
||
races:
|
||
type: array
|
||
description: List of participating races. Minimum 10 entries required.
|
||
minItems: 10
|
||
items:
|
||
$ref: "#/components/schemas/InitRace"
|
||
InitRace:
|
||
type: object
|
||
description: A single race entry in an initialization request.
|
||
required:
|
||
- raceName
|
||
properties:
|
||
raceName:
|
||
type: string
|
||
description: Name of the race. Must be non-blank and satisfy the entity-name format.
|
||
minLength: 1
|
||
BanishRequest:
|
||
type: object
|
||
description: |
|
||
Request body for the admin banish endpoint. `race_name` must
|
||
identify an existing race in the engine roster.
|
||
required:
|
||
- race_name
|
||
properties:
|
||
race_name:
|
||
type: string
|
||
description: Name of the race to banish. Must be non-blank.
|
||
minLength: 1
|
||
CommandRequest:
|
||
type: object
|
||
description: |
|
||
Batch command payload. `actor` identifies the race submitting the commands.
|
||
Each element of `cmd` is a polymorphic command object discriminated by the
|
||
`@type` field. At least one command is required.
|
||
required:
|
||
- actor
|
||
- cmd
|
||
properties:
|
||
actor:
|
||
type: string
|
||
description: Race name of the actor submitting the commands. Must be non-blank.
|
||
minLength: 1
|
||
cmd:
|
||
type: array
|
||
description: One or more commands to execute in order.
|
||
minItems: 1
|
||
items:
|
||
$ref: "#/components/schemas/Command"
|
||
UserGamesOrder:
|
||
type: object
|
||
description: |
|
||
Stored player order. Returned by `PUT /api/v1/order` after successful
|
||
validation and by `GET /api/v1/order` when fetching a previously stored
|
||
batch. `cmd` mirrors the command list submitted by the player; entries
|
||
carry per-command result fields (`cmdApplied`, `cmdErrorCode`) once the
|
||
order has been processed during turn generation.
|
||
required:
|
||
- game_id
|
||
- updatedAt
|
||
- cmd
|
||
properties:
|
||
game_id:
|
||
type: string
|
||
format: uuid
|
||
description: Identifier of the game this order belongs to.
|
||
updatedAt:
|
||
type: integer
|
||
format: int64
|
||
description: Engine-assigned UTC millisecond timestamp of the last write.
|
||
cmd:
|
||
type: array
|
||
description: Commands stored as part of this order, in submission order.
|
||
items:
|
||
$ref: "#/components/schemas/Command"
|
||
Command:
|
||
type: object
|
||
description: |
|
||
Polymorphic game command. The `@type` field identifies the variant.
|
||
Each variant extends the base fields with additional type-specific
|
||
parameters documented in `pkg/model/order/order.go`.
|
||
required:
|
||
- "@type"
|
||
- cmdId
|
||
properties:
|
||
"@type":
|
||
$ref: "#/components/schemas/CommandType"
|
||
cmdId:
|
||
type: string
|
||
format: uuid
|
||
description: Unique command identifier (RFC 4122 UUID).
|
||
cmdApplied:
|
||
type: boolean
|
||
description: |
|
||
Per-command outcome. Set by the engine in every response that
|
||
carries a stored or freshly-validated order (`PUT /api/v1/order`
|
||
and `GET /api/v1/order`): `true` when the command was applied
|
||
against the engine state during validation or turn generation,
|
||
`false` when it was rejected (see `cmdErrorCode`). Omitted on
|
||
requests.
|
||
cmdErrorCode:
|
||
type: integer
|
||
description: |
|
||
Per-command error code. Set by the engine alongside `cmdApplied`:
|
||
`0` when the command was applied, a non-zero `GenericError`
|
||
code (shelves `2xxx`/`3xxx` in `pkg/error/generic.go`) when
|
||
the command was rejected. Omitted on requests.
|
||
cmdErrorMessage:
|
||
type: string
|
||
description: |
|
||
Per-command rejection reason, formatted by the engine's
|
||
`GenericError.Error()` (e.g.
|
||
`Entity does not exists: ship type "Drone"`). Set alongside
|
||
`cmdApplied=false`/`cmdErrorCode!=0`, omitted when the
|
||
command was applied. Provided so clients can surface the
|
||
specific reason without keeping their own code → text
|
||
catalog in sync with the engine.
|
||
CommandType:
|
||
type: string
|
||
description: Discriminator identifying the game command variant carried in a `cmd` element.
|
||
enum:
|
||
- raceQuit
|
||
- raceVote
|
||
- raceRelation
|
||
- shipClassCreate
|
||
- shipClassMerge
|
||
- shipClassRemove
|
||
- shipGroupBreak
|
||
- shipGroupLoad
|
||
- shipGroupUnload
|
||
- shipGroupSend
|
||
- shipGroupUpgrade
|
||
- shipGroupMerge
|
||
- shipGroupDismantle
|
||
- shipGroupTransfer
|
||
- shipGroupJoinFleet
|
||
- fleetMerge
|
||
- fleetSend
|
||
- scienceCreate
|
||
- scienceRemove
|
||
- planetRename
|
||
- planetProduce
|
||
- planetRouteSet
|
||
- planetRouteRemove
|
||
Report:
|
||
type: object
|
||
description: |
|
||
Full game report for one player at one turn boundary. Optional array
|
||
fields are omitted when empty.
|
||
required:
|
||
- version
|
||
- turn
|
||
- mapWidth
|
||
- mapHeight
|
||
- mapPlanets
|
||
- race
|
||
- votes
|
||
- voteFor
|
||
- player
|
||
properties:
|
||
version:
|
||
type: integer
|
||
minimum: 0
|
||
description: Report format version.
|
||
turn:
|
||
type: integer
|
||
minimum: 0
|
||
description: Turn number this report covers.
|
||
mapWidth:
|
||
type: integer
|
||
minimum: 0
|
||
description: Width of the star map.
|
||
mapHeight:
|
||
type: integer
|
||
minimum: 0
|
||
description: Height of the star map.
|
||
mapPlanets:
|
||
type: integer
|
||
minimum: 0
|
||
description: Total number of planets on the map.
|
||
race:
|
||
type: string
|
||
description: Race name of the report recipient.
|
||
votes:
|
||
type: number
|
||
description: Fraction of alliance votes held by this race.
|
||
voteFor:
|
||
type: string
|
||
description: Race name this player is currently voting for.
|
||
player:
|
||
type: array
|
||
description: Diplomatic and aggregate statistics for each known player.
|
||
items:
|
||
$ref: "#/components/schemas/ReportPlayer"
|
||
localScience:
|
||
type: array
|
||
description: Science projects owned by this race.
|
||
items:
|
||
$ref: "#/components/schemas/Science"
|
||
otherScience:
|
||
type: array
|
||
description: Science projects owned by other known races.
|
||
items:
|
||
$ref: "#/components/schemas/OtherScience"
|
||
localShipClass:
|
||
type: array
|
||
description: Ship classes designed by this race.
|
||
items:
|
||
$ref: "#/components/schemas/ShipClass"
|
||
otherShipClass:
|
||
type: array
|
||
description: Ship classes belonging to other known races.
|
||
items:
|
||
$ref: "#/components/schemas/OtherShipClass"
|
||
battle:
|
||
type: array
|
||
description: Battle summaries relevant to this turn.
|
||
items:
|
||
$ref: "#/components/schemas/BattleSummary"
|
||
bombing:
|
||
type: array
|
||
description: Bombing events that occurred during this turn.
|
||
items:
|
||
$ref: "#/components/schemas/Bombing"
|
||
incomingGroup:
|
||
type: array
|
||
description: Identified ship groups inbound toward this race's planets.
|
||
items:
|
||
$ref: "#/components/schemas/IncomingGroup"
|
||
localPlanet:
|
||
type: array
|
||
description: Full state of planets owned by this race.
|
||
items:
|
||
$ref: "#/components/schemas/LocalPlanet"
|
||
shipProduction:
|
||
type: array
|
||
description: Active ship construction status on this race's planets.
|
||
items:
|
||
$ref: "#/components/schemas/ShipProduction"
|
||
route:
|
||
type: array
|
||
description: Cargo route configuration per planet.
|
||
items:
|
||
$ref: "#/components/schemas/Route"
|
||
otherPlanet:
|
||
type: array
|
||
description: Partial state of planets owned by other known races.
|
||
items:
|
||
$ref: "#/components/schemas/OtherPlanet"
|
||
uninhabitedPlanet:
|
||
type: array
|
||
description: Uninhabited planets within sensor range.
|
||
items:
|
||
$ref: "#/components/schemas/UninhabitedPlanet"
|
||
unidentifiedPlanet:
|
||
type: array
|
||
description: Unidentified planet positions within sensor range.
|
||
items:
|
||
$ref: "#/components/schemas/UnidentifiedPlanet"
|
||
localFleet:
|
||
type: array
|
||
description: Named fleets belonging to this race.
|
||
items:
|
||
$ref: "#/components/schemas/LocalFleet"
|
||
localGroup:
|
||
type: array
|
||
description: Ship groups belonging to this race.
|
||
items:
|
||
$ref: "#/components/schemas/LocalGroup"
|
||
otherGroup:
|
||
type: array
|
||
description: Ship groups belonging to other known races.
|
||
items:
|
||
$ref: "#/components/schemas/OtherGroup"
|
||
unidentifiedGroup:
|
||
type: array
|
||
description: Unidentified ship group positions within sensor range.
|
||
items:
|
||
$ref: "#/components/schemas/UnidentifiedGroup"
|
||
ReportPlayer:
|
||
type: object
|
||
description: Diplomatic and aggregate statistics for one player as seen in a report.
|
||
required:
|
||
- name
|
||
- drive
|
||
- weapons
|
||
- shields
|
||
- cargo
|
||
- population
|
||
- industry
|
||
- planets
|
||
- relation
|
||
- votes
|
||
- extinct
|
||
properties:
|
||
name:
|
||
type: string
|
||
description: Race name.
|
||
drive:
|
||
type: number
|
||
description: Current drive technology level.
|
||
weapons:
|
||
type: number
|
||
description: Current weapons technology level.
|
||
shields:
|
||
type: number
|
||
description: Current shields technology level.
|
||
cargo:
|
||
type: number
|
||
description: Current cargo technology level.
|
||
population:
|
||
type: number
|
||
description: Total population across all planets.
|
||
industry:
|
||
type: number
|
||
description: Total industrial output.
|
||
planets:
|
||
type: integer
|
||
minimum: 0
|
||
description: Number of planets owned.
|
||
relation:
|
||
type: string
|
||
description: Current diplomatic relation toward this race.
|
||
votes:
|
||
type: number
|
||
description: Fraction of alliance votes held.
|
||
extinct:
|
||
type: boolean
|
||
description: True when the race has been eliminated or quit.
|
||
Science:
|
||
type: object
|
||
description: A science project describing technology investment ratios.
|
||
required:
|
||
- name
|
||
- drive
|
||
- weapons
|
||
- shields
|
||
- cargo
|
||
properties:
|
||
name:
|
||
type: string
|
||
description: Science project name.
|
||
drive:
|
||
type: number
|
||
description: Investment ratio for drive technology (0–1).
|
||
weapons:
|
||
type: number
|
||
description: Investment ratio for weapons technology (0–1).
|
||
shields:
|
||
type: number
|
||
description: Investment ratio for shields technology (0–1).
|
||
cargo:
|
||
type: number
|
||
description: Investment ratio for cargo technology (0–1).
|
||
OtherScience:
|
||
allOf:
|
||
- $ref: "#/components/schemas/Science"
|
||
- type: object
|
||
required:
|
||
- race
|
||
properties:
|
||
race:
|
||
type: string
|
||
description: Race that owns this science project.
|
||
ShipClass:
|
||
type: object
|
||
description: Design parameters for one ship class.
|
||
required:
|
||
- name
|
||
- drive
|
||
- armament
|
||
- weapons
|
||
- shields
|
||
- cargo
|
||
- mass
|
||
properties:
|
||
name:
|
||
type: string
|
||
description: Ship class name.
|
||
drive:
|
||
type: number
|
||
description: Drive technology level.
|
||
armament:
|
||
type: integer
|
||
minimum: 0
|
||
description: Number of weapon mounts (ammo units).
|
||
weapons:
|
||
type: number
|
||
description: Weapons technology multiplier.
|
||
shields:
|
||
type: number
|
||
description: Shields technology multiplier.
|
||
cargo:
|
||
type: number
|
||
description: Cargo technology multiplier.
|
||
mass:
|
||
type: number
|
||
description: Computed ship mass.
|
||
OtherShipClass:
|
||
allOf:
|
||
- $ref: "#/components/schemas/ShipClass"
|
||
- type: object
|
||
required:
|
||
- race
|
||
properties:
|
||
race:
|
||
type: string
|
||
description: Race that owns this ship class.
|
||
Bombing:
|
||
type: object
|
||
description: Record of a bombing event that occurred during turn processing.
|
||
required:
|
||
- planet
|
||
- planetName
|
||
- owner
|
||
- attacker
|
||
- production
|
||
- industry
|
||
- population
|
||
- colonists
|
||
- capital
|
||
- material
|
||
- attack
|
||
- wiped
|
||
properties:
|
||
planet:
|
||
type: integer
|
||
minimum: 0
|
||
description: Global planet number.
|
||
planetName:
|
||
type: string
|
||
description: Planet name.
|
||
owner:
|
||
type: string
|
||
description: Race name of the planet owner.
|
||
attacker:
|
||
type: string
|
||
description: Race name of the attacker.
|
||
production:
|
||
type: string
|
||
description: Production type active on the planet at the time of bombing.
|
||
industry:
|
||
type: number
|
||
description: Industrial capacity remaining after the bombing.
|
||
population:
|
||
type: number
|
||
description: Population remaining after the bombing.
|
||
colonists:
|
||
type: number
|
||
description: Colonist units remaining after the bombing.
|
||
capital:
|
||
type: number
|
||
description: Capital reserves remaining after the bombing.
|
||
material:
|
||
type: number
|
||
description: Material reserves remaining after the bombing.
|
||
attack:
|
||
type: number
|
||
description: Aggregate attack power applied during the bombing.
|
||
wiped:
|
||
type: boolean
|
||
description: True when all population was eliminated by the bombing.
|
||
BattleSummary:
|
||
type: object
|
||
description: |
|
||
Identifies one battle relevant to the report recipient. Used by
|
||
clients to render a battle marker on the map without fetching
|
||
the full BattleReport. `planet` locates the marker; `shots`
|
||
scales the marker stroke with the battle length.
|
||
required:
|
||
- id
|
||
- planet
|
||
- shots
|
||
properties:
|
||
id:
|
||
type: string
|
||
format: uuid
|
||
description: Battle identifier; fetch the full report via `/api/v1/battle/{turn}/{uuid}`.
|
||
planet:
|
||
type: integer
|
||
minimum: 0
|
||
description: Planet number the battle took place on.
|
||
shots:
|
||
type: integer
|
||
minimum: 0
|
||
description: Number of shots exchanged during the battle.
|
||
BattleReport:
|
||
type: object
|
||
description: |
|
||
Full battle report. `races` and `ships` are JSON objects whose
|
||
keys are stringified integers used to cross-reference entries
|
||
from `protocol`: a `BattleActionReport` carries integer indices
|
||
into both maps. The serialised key is a string because JSON
|
||
object keys are always strings.
|
||
required:
|
||
- id
|
||
- planet
|
||
- planetName
|
||
- races
|
||
- ships
|
||
- protocol
|
||
properties:
|
||
id:
|
||
type: string
|
||
format: uuid
|
||
description: Battle identifier.
|
||
planet:
|
||
type: integer
|
||
minimum: 0
|
||
description: Planet number the battle took place on.
|
||
planetName:
|
||
type: string
|
||
description: Planet name at battle start.
|
||
races:
|
||
type: object
|
||
description: |
|
||
Participating races keyed by the integer index used in
|
||
`protocol.a` / `protocol.d`. Values are race identifiers.
|
||
additionalProperties:
|
||
type: string
|
||
format: uuid
|
||
ships:
|
||
type: object
|
||
description: |
|
||
Participating ship groups keyed by the integer index used
|
||
in `protocol.sa` / `protocol.sd`.
|
||
additionalProperties:
|
||
$ref: "#/components/schemas/BattleReportGroup"
|
||
protocol:
|
||
type: array
|
||
description: Ordered list of shots exchanged during the battle.
|
||
items:
|
||
$ref: "#/components/schemas/BattleActionReport"
|
||
BattleReportGroup:
|
||
type: object
|
||
description: One ship group participating in the battle.
|
||
required:
|
||
- race
|
||
- className
|
||
- tech
|
||
- num
|
||
- numLeft
|
||
- loadType
|
||
- loadQuantity
|
||
- inBattle
|
||
properties:
|
||
race:
|
||
type: string
|
||
description: Race name of the group owner.
|
||
className:
|
||
type: string
|
||
description: Ship class name; resolvable through `LocalShipClass` or `OtherShipClass`.
|
||
tech:
|
||
type: object
|
||
description: Technology levels keyed by tech type name.
|
||
additionalProperties:
|
||
type: number
|
||
num:
|
||
type: integer
|
||
minimum: 0
|
||
description: Initial number of ships in this group.
|
||
numLeft:
|
||
type: integer
|
||
minimum: 0
|
||
description: Number of ships remaining at the end of the battle.
|
||
loadType:
|
||
type: string
|
||
description: Type of cargo loaded.
|
||
loadQuantity:
|
||
type: number
|
||
description: Quantity of cargo loaded.
|
||
inBattle:
|
||
type: boolean
|
||
description: |
|
||
True when the group actually fights. False groups observe
|
||
the battle in peace state and never fire or take damage.
|
||
BattleActionReport:
|
||
type: object
|
||
description: |
|
||
One shot in the battle. Attacker and defender indices reference
|
||
`BattleReport.races`; ship-class indices reference
|
||
`BattleReport.ships`.
|
||
required:
|
||
- a
|
||
- sa
|
||
- d
|
||
- sd
|
||
- x
|
||
properties:
|
||
a:
|
||
type: integer
|
||
description: Index into `BattleReport.races` for the attacker.
|
||
sa:
|
||
type: integer
|
||
description: Index into `BattleReport.ships` for the attacker's group.
|
||
d:
|
||
type: integer
|
||
description: Index into `BattleReport.races` for the defender.
|
||
sd:
|
||
type: integer
|
||
description: Index into `BattleReport.ships` for the defender's group.
|
||
x:
|
||
type: boolean
|
||
description: True when the defender ship was destroyed by this shot.
|
||
IncomingGroup:
|
||
type: object
|
||
description: An identified ship group inbound toward a planet of this race.
|
||
required:
|
||
- origin
|
||
- destination
|
||
- distance
|
||
- speed
|
||
- mass
|
||
properties:
|
||
origin:
|
||
type: integer
|
||
minimum: 0
|
||
description: Planet number where this group originated.
|
||
destination:
|
||
type: integer
|
||
minimum: 0
|
||
description: Planet number this group is heading toward.
|
||
distance:
|
||
type: number
|
||
description: Remaining travel distance.
|
||
speed:
|
||
type: number
|
||
description: Travel speed.
|
||
mass:
|
||
type: number
|
||
description: Total mass of the group.
|
||
UnidentifiedPlanet:
|
||
type: object
|
||
description: Minimal sensor reading for an unidentified planet.
|
||
required:
|
||
- x
|
||
- "y"
|
||
- number
|
||
properties:
|
||
x:
|
||
type: number
|
||
description: Horizontal map coordinate.
|
||
"y":
|
||
type: number
|
||
description: Vertical map coordinate.
|
||
number:
|
||
type: integer
|
||
minimum: 0
|
||
description: Global planet number.
|
||
UninhabitedPlanet:
|
||
allOf:
|
||
- $ref: "#/components/schemas/UnidentifiedPlanet"
|
||
- type: object
|
||
description: An uninhabited planet within sensor range.
|
||
required:
|
||
- size
|
||
- name
|
||
- resources
|
||
- capital
|
||
- material
|
||
properties:
|
||
size:
|
||
type: number
|
||
description: Planet size.
|
||
name:
|
||
type: string
|
||
description: Planet name.
|
||
resources:
|
||
type: number
|
||
description: Natural resource yield (R).
|
||
capital:
|
||
type: number
|
||
description: Capital reserves stored on the planet (CAP).
|
||
material:
|
||
type: number
|
||
description: Material reserves stored on the planet (MAT).
|
||
LocalPlanet:
|
||
allOf:
|
||
- $ref: "#/components/schemas/UninhabitedPlanet"
|
||
- type: object
|
||
description: Full state for a planet owned by this race.
|
||
required:
|
||
- industry
|
||
- population
|
||
- colonists
|
||
- production
|
||
- freeIndustry
|
||
properties:
|
||
industry:
|
||
type: number
|
||
description: Industrial capacity of the planet (I).
|
||
population:
|
||
type: number
|
||
description: Population of the planet (P).
|
||
colonists:
|
||
type: number
|
||
description: Number of colonists on the planet (COL).
|
||
production:
|
||
type: string
|
||
description: Current production assignment.
|
||
freeIndustry:
|
||
type: number
|
||
description: Unused industrial capacity available for new production (L).
|
||
OtherPlanet:
|
||
allOf:
|
||
- $ref: "#/components/schemas/LocalPlanet"
|
||
- type: object
|
||
description: Partial planet state for a planet owned by another race.
|
||
required:
|
||
- owner
|
||
properties:
|
||
owner:
|
||
type: string
|
||
description: Race name of the planet owner.
|
||
Route:
|
||
type: object
|
||
description: Cargo route configuration originating from one planet.
|
||
required:
|
||
- planet
|
||
- route
|
||
properties:
|
||
planet:
|
||
type: integer
|
||
minimum: 0
|
||
description: Source planet number.
|
||
route:
|
||
type: object
|
||
description: |
|
||
Mapping from destination planet number (as a string key) to the
|
||
cargo load type being routed (MAT, CAP, COL, EMP).
|
||
additionalProperties:
|
||
type: string
|
||
ShipProduction:
|
||
type: object
|
||
description: Active ship construction progress on one planet.
|
||
required:
|
||
- planet
|
||
- class
|
||
- cost
|
||
- prodUsed
|
||
- percent
|
||
- free
|
||
properties:
|
||
planet:
|
||
type: integer
|
||
minimum: 0
|
||
description: Planet number where construction is taking place.
|
||
class:
|
||
type: string
|
||
description: Name of the ship class being built.
|
||
cost:
|
||
type: number
|
||
description: Total production cost for one unit of this class.
|
||
prodUsed:
|
||
type: number
|
||
description: Production units already spent on this build.
|
||
percent:
|
||
type: number
|
||
description: Completion percentage of the current build.
|
||
free:
|
||
type: number
|
||
description: Remaining free industrial capacity on this planet.
|
||
LocalFleet:
|
||
type: object
|
||
description: A named fleet belonging to this race.
|
||
required:
|
||
- name
|
||
- groups
|
||
- destination
|
||
- speed
|
||
- state
|
||
properties:
|
||
name:
|
||
type: string
|
||
description: Fleet name.
|
||
groups:
|
||
type: integer
|
||
minimum: 0
|
||
description: Number of ship groups in this fleet.
|
||
destination:
|
||
type: integer
|
||
minimum: 0
|
||
description: Destination planet number.
|
||
origin:
|
||
type: integer
|
||
minimum: 0
|
||
description: Origin planet number when the fleet is in transit.
|
||
range:
|
||
type: number
|
||
description: Remaining travel range when the fleet is in transit.
|
||
speed:
|
||
type: number
|
||
description: Travel speed.
|
||
state:
|
||
type: string
|
||
description: Fleet operational state.
|
||
OtherGroup:
|
||
type: object
|
||
description: A ship group visible to this race belonging to another race.
|
||
required:
|
||
- number
|
||
- class
|
||
- tech
|
||
- cargo
|
||
- load
|
||
- destination
|
||
- speed
|
||
- mass
|
||
properties:
|
||
number:
|
||
type: integer
|
||
minimum: 0
|
||
description: Group identifier number.
|
||
class:
|
||
type: string
|
||
description: Ship class name.
|
||
tech:
|
||
type: object
|
||
description: Technology levels of this group keyed by tech type name.
|
||
additionalProperties:
|
||
type: number
|
||
cargo:
|
||
type: string
|
||
description: Type of cargo carried by this group.
|
||
load:
|
||
type: number
|
||
description: Current cargo load quantity.
|
||
destination:
|
||
type: integer
|
||
minimum: 0
|
||
description: Destination planet number.
|
||
origin:
|
||
type: integer
|
||
minimum: 0
|
||
description: Origin planet number when the group is in transit.
|
||
range:
|
||
type: number
|
||
description: Remaining travel range when the group is in transit.
|
||
speed:
|
||
type: number
|
||
description: Travel speed.
|
||
mass:
|
||
type: number
|
||
description: Total mass of the group.
|
||
LocalGroup:
|
||
allOf:
|
||
- $ref: "#/components/schemas/OtherGroup"
|
||
- type: object
|
||
description: A ship group belonging to this race with full ownership detail.
|
||
required:
|
||
- id
|
||
- state
|
||
properties:
|
||
id:
|
||
type: string
|
||
format: uuid
|
||
description: Unique group identifier.
|
||
state:
|
||
type: string
|
||
description: Group operational state.
|
||
fleet:
|
||
type: string
|
||
nullable: true
|
||
description: Name of the fleet this group belongs to, or null if ungrouped.
|
||
UnidentifiedGroup:
|
||
type: object
|
||
description: Positional reading for an unidentified ship group.
|
||
required:
|
||
- x
|
||
- "y"
|
||
properties:
|
||
x:
|
||
type: number
|
||
description: Horizontal map coordinate.
|
||
"y":
|
||
type: number
|
||
description: Vertical map coordinate.
|
||
ValidationErrorResponse:
|
||
type: object
|
||
description: Validation error returned for malformed requests.
|
||
required:
|
||
- error
|
||
properties:
|
||
error:
|
||
type: string
|
||
description: Human-readable validation error message from the binding layer.
|
||
ConflictErrorResponse:
|
||
type: object
|
||
description: |
|
||
Conflict error returned when the engine refuses an operation
|
||
that would clash with persisted state. Today the only producer
|
||
is `POST /api/v1/admin/init` when the storage directory
|
||
already contains a game state.
|
||
required:
|
||
- error
|
||
properties:
|
||
error:
|
||
type: string
|
||
description: Human-readable conflict description.
|
||
InternalErrorResponse:
|
||
type: object
|
||
description: |
|
||
Internal server error. The shape depends on the error source:
|
||
- `{"error": "message"}` for generic runtime errors
|
||
- `{"generic_error": "message", "code": integer}` for game-engine errors
|
||
properties:
|
||
error:
|
||
type: string
|
||
description: Generic runtime error message.
|
||
generic_error:
|
||
type: string
|
||
description: Game-engine error message.
|
||
code:
|
||
type: integer
|
||
description: Game-engine error code.
|
||
responses:
|
||
ValidationError:
|
||
description: Request body or query parameters are invalid.
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/ValidationErrorResponse"
|
||
examples:
|
||
validationError:
|
||
value:
|
||
error: "Key: 'InitRequest.Races' Error:Field validation for 'Races' failed on the 'gte' tag"
|
||
ConflictError:
|
||
description: |
|
||
The requested operation conflicts with persisted engine state.
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/ConflictErrorResponse"
|
||
examples:
|
||
alreadyInitialized:
|
||
value:
|
||
error: "game init: game already initialized"
|
||
InternalError:
|
||
description: Internal Game Service error.
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/InternalErrorResponse"
|