package ports import ( "context" "encoding/json" "errors" ) //go:generate go run go.uber.org/mock/mockgen -destination=../adapters/mocks/mock_engineclient.go -package=mocks galaxy/gamemaster/internal/ports EngineClient // EngineClient is the narrow surface Game Master uses against a running // engine container. The production adapter (Stage 12) speaks REST/JSON // against the engine routes documented in `galaxy/game/openapi.yaml`: // // - admin paths under `/api/v1/admin/*` (init, status, turn, // race/banish); // - player paths under `/api/v1/{command, order, report}`. // // The admin-path responses are typed (Init, Status, Turn) because GM // reads structured fields out of them (`current_turn`, `finished`, // per-player stats). The player-path payloads are forwarded verbatim: // the gateway transcodes FlatBuffers to JSON, GM passes the JSON // through, and the engine response is returned to the gateway // unchanged. type EngineClient interface { // Init calls POST /api/v1/admin/init. The returned StateResponse // carries the initial player roster used to install // `player_mappings`. Init(ctx context.Context, baseURL string, request InitRequest) (StateResponse, error) // Status calls GET /api/v1/admin/status. Used by inspect surfaces // and by recovery flows. Status(ctx context.Context, baseURL string) (StateResponse, error) // Turn calls PUT /api/v1/admin/turn. The returned StateResponse // carries the new turn number, the per-player stats projected into // `player_turn_stats`, and the `finished` flag. Turn(ctx context.Context, baseURL string) (StateResponse, error) // BanishRace calls POST /api/v1/admin/race/banish with body // `{race_name}`. The engine returns 204 on success. BanishRace(ctx context.Context, baseURL, raceName string) error // ExecuteCommands calls PUT /api/v1/command. The request payload // is forwarded verbatim; the engine response body is returned // verbatim. ExecuteCommands(ctx context.Context, baseURL string, payload json.RawMessage) (json.RawMessage, error) // PutOrders calls PUT /api/v1/order with the same forwarding // semantics as ExecuteCommands. PutOrders(ctx context.Context, baseURL string, payload json.RawMessage) (json.RawMessage, error) // GetReport calls GET /api/v1/report?player=&turn=. // The engine response body is returned verbatim. GetReport(ctx context.Context, baseURL, raceName string, turn int) (json.RawMessage, error) } // InitRequest carries the race roster sent to the engine `/admin/init` // route. The shape mirrors `galaxy/game/openapi.yaml`'s `InitRequest`. type InitRequest struct { // Races stores the per-player race entries in the order returned // by Lobby's roster. Races []InitRace } // InitRace stores one entry of an InitRequest. type InitRace struct { // RaceName stores the in-game race name reserved for the player. RaceName string } // StateResponse is the typed projection of the engine's `StateResponse` // payload (`galaxy/game/openapi.yaml`). GM reads only the fields it // needs; the adapter is allowed to discard the rest. type StateResponse struct { // Turn stores the engine's current turn number. Turn int // Players stores the per-player state entries returned by the // engine. Each entry is mapped into `player_turn_stats[]` by // resolving `RaceName` through `playermappingstore.ListByGame` to // the platform `user_id`. Players []PlayerState // Finished reports whether the engine considers the game finished. // Becomes true on a turn-generation response when the engine's // finish condition is satisfied. Finished bool } // PlayerState stores one entry of StateResponse.Players. The set of // fields is the minimum GM needs from the engine surface; the adapter // may decode additional fields and discard them. type PlayerState struct { // RaceName stores the in-game race name. RaceName string // EnginePlayerUUID stores the engine-side player handle. Populated // from `/admin/init` and `/admin/status`. EnginePlayerUUID string // Planets stores the planet count reported for this player on the // most recent turn. Planets int // Population stores the population count reported for this player // on the most recent turn. Population int } // ErrEngineUnreachable reports that the engine returned a transport // error or 5xx status code. Surfaced to callers as `engine_unreachable`. var ErrEngineUnreachable = errors.New("engine unreachable") // ErrEngineProtocolViolation reports that the engine responded with a // payload that did not match the expected schema (missing required // fields, malformed JSON, unexpected types). Surfaced as // `engine_protocol_violation`. var ErrEngineProtocolViolation = errors.New("engine protocol violation") // ErrEngineValidation reports that the engine returned 4xx with a // per-command result. Surfaced as `engine_validation_error`; the // engine's body is returned verbatim to the caller through the player // command/order forwarding paths. var ErrEngineValidation = errors.New("engine validation error")