1import myzod, { Infer } from 'myzod';
  2import { DeepReadonly } from 'ts-essentials';
  3
  4// See protocol.go.
  5
  6// Messages sent from client to server.
  7
  8export type WordPack = Infer<typeof WordPack>;
  9const WordPack = myzod.object({
 10    name: myzod.string(),
 11    words: myzod.array(myzod.string()),
 12});
 13
 14export type ClientNote = Infer<typeof ClientNote>;
 15export const ClientNote = myzod
 16    .object({
 17        version: myzod.number(),
 18    })
 19    .and(
 20        myzod.union([
 21            myzod.object({
 22                method: myzod.literal('newGame'),
 23                params: myzod.object({}),
 24            }),
 25            myzod.object({
 26                method: myzod.literal('endTurn'),
 27                params: myzod.object({}),
 28            }),
 29            myzod.object({
 30                method: myzod.literal('randomizeTeams'),
 31                params: myzod.object({}),
 32            }),
 33            myzod.object({
 34                method: myzod.literal('reveal'),
 35                params: myzod.object({ row: myzod.number(), col: myzod.number() }),
 36            }),
 37            myzod.object({
 38                method: myzod.literal('changeTeam'),
 39                params: myzod.object({ team: myzod.number() }),
 40            }),
 41            myzod.object({
 42                method: myzod.literal('changeNickname'),
 43                params: myzod.object({ nickname: myzod.string() }),
 44            }),
 45            myzod.object({
 46                method: myzod.literal('changeRole'),
 47                params: myzod.object({ spymaster: myzod.boolean() }),
 48            }),
 49            myzod.object({
 50                method: myzod.literal('changePack'),
 51                params: myzod.object({ num: myzod.number(), enable: myzod.boolean() }),
 52            }),
 53            myzod.object({
 54                method: myzod.literal('changeTurnMode'),
 55                params: myzod.object({ timed: myzod.boolean() }),
 56            }),
 57            myzod.object({
 58                method: myzod.literal('changeTurnTime'),
 59                params: myzod.object({ seconds: myzod.number() }),
 60            }),
 61            myzod.object({
 62                method: myzod.literal('addPacks'),
 63                params: myzod.object({
 64                    packs: myzod.array(WordPack),
 65                }),
 66            }),
 67            myzod.object({
 68                method: myzod.literal('removePack'),
 69                params: myzod.object({ num: myzod.number() }),
 70            }),
 71            myzod.object({
 72                method: myzod.literal('changeHideBomb'),
 73                params: myzod.object({ hideBomb: myzod.boolean() }),
 74            }),
 75        ])
 76    );
 77
 78// Messages sent from server to client.
 79
 80export type RoomResponse = DeepReadonly<Infer<typeof RoomResponse>>;
 81export const RoomResponse = myzod.object({
 82    id: myzod.string().optional().nullable(),
 83    error: myzod.string().optional().nullable(),
 84});
 85
 86export type TimeResponse = DeepReadonly<Infer<typeof TimeResponse>>;
 87export const TimeResponse = myzod.object({
 88    time: myzod.date(),
 89});
 90
 91export type StateTile = DeepReadonly<Infer<typeof StateTile>>;
 92const StateTile = myzod.object({
 93    word: myzod.string(),
 94    revealed: myzod.boolean(),
 95    view: myzod
 96        .object({
 97            team: myzod.number(),
 98            neutral: myzod.boolean(),
 99            bomb: myzod.boolean(),
100        })
101        .optional()
102        .nullable(),
103});
104
105export type StateBoard = DeepReadonly<Infer<typeof StateBoard>>;
106const StateBoard = myzod.array(myzod.array(StateTile));
107
108export type StatePlayer = DeepReadonly<Infer<typeof StatePlayer>>;
109const StatePlayer = myzod.object({
110    playerID: myzod.string(),
111    nickname: myzod.string(),
112    spymaster: myzod.boolean(),
113});
114
115export type StateTeams = DeepReadonly<Infer<typeof StateTeams>>;
116const StateTeams = myzod.array(myzod.array(StatePlayer));
117
118export type StateTimer = DeepReadonly<Infer<typeof StateTimer>>;
119const StateTimer = myzod.object({
120    turnTime: myzod.number(),
121    turnEnd: myzod.date(),
122});
123
124export type State = DeepReadonly<Infer<typeof State>>;
125export const State = myzod.object({
126    version: myzod.number(),
127    teams: StateTeams,
128    turn: myzod.number(),
129    winner: myzod.number().optional().nullable(),
130    board: StateBoard,
131    wordsLeft: myzod.array(myzod.number()),
132    lists: myzod.array(
133        myzod.object({
134            name: myzod.string(),
135            count: myzod.number(),
136            custom: myzod.boolean(),
137            enabled: myzod.boolean(),
138        })
139    ),
140    timer: StateTimer.optional().nullable(),
141    hideBomb: myzod.boolean(),
142});
143
144export type ServerNote = DeepReadonly<Infer<typeof ServerNote>>;
145export const ServerNote = myzod.union([
146    myzod.object({
147        method: myzod.literal('state'),
148        params: State,
149    }),
150]);