feat: gamemaster
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
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=<raceName>&turn=<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")
|
||||
Reference in New Issue
Block a user