go-fish-web 0.3.0

Web protocol types for the go-fish game
Documentation

go-fish-web

Shared protocol types for the Go Fish game — serialised as JSON over WebSocket.

This crate defines ClientMessage and ServerMessage plus all supporting types. It contains no application logic; the server and client own the transport and deserialization call sites.

Types

ClientMessage (client → server)

Variant Payload Purpose
Identity First message sent on connect; requests a server-assigned player name
CreateLobby Create a new game lobby
JoinLobby(String) lobby ID Join an existing lobby
LeaveLobby Exit the current lobby
StartGame Lobby leader starts the game
Hook(ClientHookRequest) { target_name, rank } Execute a turn: ask target_name for all cards of rank
AddBot { bot_type } BotType Leader adds a bot slot (currently only SimpleBot)
RemoveBot Leader removes the last bot slot

ServerMessage (server → client)

Variant Payload Purpose
PlayerIdentity(String) assigned name Response to Identity
LobbyJoined { lobby_id, leader, players, max_players } players: Vec<LobbyPlayer> Lobby entry confirmed
LobbyUpdated { leader, players } players: Vec<LobbyPlayer> Broadcast when lobby roster changes
LobbyLeft(LobbyLeftReason) Lobby exit confirmed
GameStarted Broadcast when the game begins
GameSnapshot(GameSnapshot) full state Sent to all players after each turn
HookError(HookError) error kind Turn was rejected
PlayerTurn(PlayerTurnValue) YourTurn or OtherTurn(name) Indicates whose turn it is
GameResult(GameResult) winners + losers Sent when the game ends
Error(String) message Generic server error

Supporting types

BotType — identifies which bot implementation to add to a lobby. Currently the only variant is SimpleBot.

LobbyPlayer — a slot in the lobby player list, used in LobbyJoined and LobbyUpdated:

pub enum LobbyPlayer {
    Human { name: String },
    Bot { name: String, bot_type: BotType },
}

GameSnapshot — the primary message during play, sent after every turn:

pub struct GameSnapshot {
    pub hand_state: HandState,                    // your hand + completed books
    pub opponents: Vec<OpponentState>,            // opponents' visible state
    pub active_player: String,                    // whose turn it is
    pub last_hook_outcome: Option<HookOutcome>,   // result of the last turn
    pub deck_size: usize,                         // cards remaining in the draw pile
}

OpponentState — what you can see of another player:

pub struct OpponentState {
    pub name: String,
    pub card_count: usize,                   // hand size (individual cards hidden)
    pub completed_books: Vec<CompleteBook>,
}

HookError variants: NotYourTurn, UnknownPlayer(String), CannotTargetYourself, YouDoNotHaveRank(Rank).

PlayerTurnValue variants: YourTurn, OtherTurn(String).

Wire format

All types derive serde::Serialize / Deserialize. The wire format is JSON using Serde's default tagged-union encoding:

"Identity"

{"Hook": {"target_name": "Alice", "rank": "Ace"}}

{"LobbyJoined": {
  "lobby_id": "abc123",
  "leader": "Bob",
  "players": ["Alice", "Bob"],
  "max_players": 4
}}

{"GameSnapshot": {
  "hand_state": { ... },
  "opponents": [{ "name": "Alice", "card_count": 3, "completed_book_count": 1 }],
  "active_player": "Bob",
  "last_hook_outcome": null
}}

Protocol flow

Client                          Server
  │─── Identity ───────────────▶│
  │◀── PlayerIdentity("Bob") ───│
  │
  │─── CreateLobby ────────────▶│
  │◀── LobbyJoined ─────────────│  (broadcast LobbyUpdated to others)
  │
  │─── StartGame ──────────────▶│
  │◀── GameStarted ─────────────│  (broadcast to all)
  │
  │─── Hook({target, rank}) ───▶│
  │◀── GameSnapshot ────────────│  (broadcast to all; contains HookOutcome)
  │  or HookError ──────────────│  (only to sender, if invalid)
  │
  │◀── GameResult ──────────────│  (broadcast when game ends)

Dependencies

Crate Use
go-fish Rank, Hand, CompleteBook, HookResult, IncompleteBook
serde Serialisation derive macros
serde_json JSON codec

License

MIT