๐๏ธ Cozy Parrot Architecture
See also: index ยท runbook ยท opcodes ยท Nakama Multiplayer ยท Plugin Architecture
Components
flowchart LR
Browser["Browser<br/>CozyParrotGame / Threlte"]
MM["CozyParrotMatchManager"]
Sock["Nakama socket"]
Handler["cozy_parrot match handler<br/>(10 Hz)"]
Shared["shared types<br/>CozyParrot/*"]
Browser <--> MM
MM <--> Sock
Sock <--> Handler
Handler --- Shared
MM --- Shared
Authority
| Concern | Authority | Notes |
|---|
Move {x,z} | Client trusted | Server clamps to arena; applied outside result |
Grab | Server-validated | phase===play, not holding, nearest token โค INTERACT_RADIUS |
Throw | Server-validated | phase===play, holding, โค INTERACT_RADIUS of hopper; blank / IDEA / โ1 score |
Score / prompt / tokens / winnerId | Server-only | Spawned, filled, scored, and broadcast via GameUpdate |
Snapshot โ CozyParrotMatchSnapshot
| Field | Type | Role |
|---|
players | Record<id, CozyParrotPlayerState> | Positions, score, held token/word |
tokens | Record<id, CozyParrotToken> | World word tokens |
targetPrompt | CozyParrotPrompt | text / blanks / filled |
phase | 'lobby'|'countdown'|'play'|'result' | Match lifecycle |
timer | number | Ticks remaining in phase |
winnerId | string | null | Set in result |
Lifecycle ticks (10 Hz)
| Constant | Value | Meaning |
|---|
COUNTDOWN_TICKS | 30 | 3s pre-play |
PLAY_TICKS | 600 | 60s play |
RESULT_TICKS | 50 | 5s results |
TOKEN_SPAWN_INTERVAL | 20 | Spawn every 2s |
MAX_TOKENS | 10 | Cap on world tokens |
MIN_PLAYERS | 2 | Lobby โ countdown |
Directory map
games/cozy-parrot/
โโโ frontend/src/lib/
โ โโโ CozyParrotGame.svelte # Threlte scene host
โ โโโ components/ # Player, RemotePlayer, Token, HUD, Scene
โ โโโ nakama/CozyParrot/
โ โโโ CozyParrotMatchManager.ts # reactive GameUpdate consumer
โโโ shared/src/CozyParrot/index.ts # snapshot, opcodes, arena consts
โโโ nakama/runtime/src/matchHandlers/cozyParrot/
โโโ index.ts # authoritative matchLoop
โโโ createCozyParrotMessageUtils.ts