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