first prototype
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
"""Messages exchanged with web clients over the ``/api/ws`` websocket.
|
||||
|
||||
Client -> server messages are validated with pydantic. Server -> client
|
||||
messages are plain dicts:
|
||||
|
||||
- ``{"type": "welcome", "player_id", "token", "name"}``
|
||||
- ``{"type": "state", "lobby": LobbyView | null, "game": GameView | null, "events": [...]}``
|
||||
- ``{"type": "error", "message"}``
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Annotated, Any, Literal
|
||||
|
||||
from pydantic import BaseModel, Field, StringConstraints, TypeAdapter
|
||||
|
||||
PlayerName = Annotated[str, StringConstraints(strip_whitespace=True, min_length=1, max_length=20)]
|
||||
LobbyCode = Annotated[str, StringConstraints(strip_whitespace=True, to_upper=True, min_length=4, max_length=12)]
|
||||
|
||||
|
||||
class Hello(BaseModel):
|
||||
type: Literal["hello"]
|
||||
# Token of a previous session, used to reconnect after a page reload.
|
||||
token: str | None = None
|
||||
|
||||
|
||||
class CreateLobby(BaseModel):
|
||||
type: Literal["create_lobby"]
|
||||
name: PlayerName
|
||||
|
||||
|
||||
class JoinLobby(BaseModel):
|
||||
type: Literal["join_lobby"]
|
||||
code: LobbyCode
|
||||
name: PlayerName
|
||||
|
||||
|
||||
class LeaveLobby(BaseModel):
|
||||
type: Literal["leave_lobby"]
|
||||
|
||||
|
||||
class AddAI(BaseModel):
|
||||
type: Literal["add_ai"]
|
||||
|
||||
|
||||
class RemovePlayer(BaseModel):
|
||||
type: Literal["remove_player"]
|
||||
player_id: str
|
||||
|
||||
|
||||
class SetOptions(BaseModel):
|
||||
type: Literal["set_options"]
|
||||
not_equal: bool
|
||||
hidden_bids: bool
|
||||
|
||||
|
||||
class StartGame(BaseModel):
|
||||
type: Literal["start_game"]
|
||||
|
||||
|
||||
class GameAction(BaseModel):
|
||||
type: Literal["action"]
|
||||
action: dict[str, Any]
|
||||
|
||||
|
||||
class ReturnToLobby(BaseModel):
|
||||
type: Literal["return_to_lobby"]
|
||||
|
||||
|
||||
ClientMessage = Annotated[
|
||||
Hello | CreateLobby | JoinLobby | LeaveLobby | AddAI | RemovePlayer
|
||||
| SetOptions | StartGame | GameAction | ReturnToLobby,
|
||||
Field(discriminator="type"),
|
||||
]
|
||||
|
||||
client_message_adapter: TypeAdapter[ClientMessage] = TypeAdapter(ClientMessage)
|
||||
|
||||
|
||||
def error(message: str) -> dict:
|
||||
return {"type": "error", "message": message}
|
||||
Reference in New Issue
Block a user