// --------------------------------------------------------------------------- // Network protocol shared between server and client (JSON over WebSocket) // --------------------------------------------------------------------------- export interface PelletData { id: number; x: number; y: number; v: number; // food value (also drives render size) c: number; // color index into PELLET_COLORS } export interface SnakeSnap { id: number; n: string; // nickname c: number; // color index into SNAKE_COLORS s: number; // score p: number[]; // flat body points [x0,y0,x1,y1,...], head first b: boolean; // boosting k: number; // kills sp?: boolean; // spawn protection active (ghost) } export type GameEvent = | { t: 'die'; id: number; x: number; y: number; c: number; s: number; p: number[] } | { t: 'join'; id: number; n: string } | { t: 'leave'; id: number }; export interface LeaderboardRow { id: number; n: string; s: number; } export interface YouState { score: number; rank: number; alive: boolean; kills: number; best: number; } // --- server -> client ------------------------------------------------------- export interface InitMsg { t: 'init'; id: number; // your snake id arena: number; // arena radius pellets: PelletData[]; // full pellet list (deltas arrive afterwards) } export interface SnapMsg { t: 'snap'; tick: number; snakes: SnakeSnap[]; add: PelletData[]; // pellets added since last snapshot rem: number[]; // pellet ids removed since last snapshot ev: GameEvent[]; // events since last snapshot lb: LeaderboardRow[]; you?: YouState; total: number; // total snakes alive } export type ServerMsg = InitMsg | SnapMsg; // --- client -> server ------------------------------------------------------- export interface JoinMsg { t: 'join'; name: string } export interface InputMsg { t: 'in'; a: number; b: boolean } // angle, boosting export interface RespawnMsg { t: 'respawn' } export type ClientMsg = JoinMsg | InputMsg | RespawnMsg;