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]);