add game engine openapi

This commit is contained in:
Ilia Denisov
2026-04-26 22:10:02 +02:00
parent b4591cabd4
commit e0a99b346b
8 changed files with 1298 additions and 5 deletions
+964
View File
@@ -0,0 +1,964 @@
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
- validation errors return `400` with `{"error": "message"}`
- game-engine errors return `500` with `{"generic_error": "message", "code": integer}`
- other internal errors return `500` with `{"error": "message"}`
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.
paths:
/api/v1/status:
get:
tags:
- GameLifecycle
operationId: getGameStatus
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.
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/init:
post:
tags:
- GameLifecycle
operationId: initGame
summary: Initialize a new game
description: |
Generates a new game instance with the supplied list of races.
Requires at least 10 race entries.
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"
"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 `204 No
Content` on success.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CommandRequest"
responses:
"204":
description: All commands applied successfully.
"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 structurally without executing them.
Returns `204 No Content` if the order is valid and accepted.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CommandRequest"
responses:
"204":
description: Order is structurally valid.
"400":
$ref: "#/components/responses/ValidationError"
"500":
$ref: "#/components/responses/InternalError"
/api/v1/turn:
put:
tags:
- GameLifecycle
operationId: generateTurn
summary: Advance the game to the next turn
description: |
Processes the current turn and generates the next one. Returns the
updated game state.
responses:
"200":
description: Updated game state after turn generation.
content:
application/json:
schema:
$ref: "#/components/schemas/StateResponse"
"500":
$ref: "#/components/responses/InternalError"
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
schemas:
StateResponse:
type: object
description: Summary game state returned after initialization and at each turn boundary.
required:
- id
- turn
- stage
- player
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"
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 race list for a new game.
required:
- races
properties:
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
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"
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: Set in command-result responses; true when the command was applied.
cmdErrorCode:
type: integer
description: Set in command-result responses; non-zero when the command was rejected.
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: UUIDs of battle reports relevant to this turn.
items:
type: string
format: uuid
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 (01).
weapons:
type: number
description: Investment ratio for weapons technology (01).
shields:
type: number
description: Investment ratio for shields technology (01).
cargo:
type: number
description: Investment ratio for cargo technology (01).
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.
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.
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"
InternalError:
description: Internal Game Service error.
content:
application/json:
schema:
$ref: "#/components/schemas/InternalErrorResponse"