1import type { games, users } from "~/server/db/schema";
2import type { GridType, Rocket, Rockets, Tiles, TilesNoEmpty } from "./grid";
3
4type UserId = number;
5
6export type Game = {
7 name: string;
8 password: string;
9 ownerId: UserId;
10 players: UserId[];
11 grid: GridType;
12};
13
14export type CtoSBasePacket = {
15 sessionToken: string;
16 gameId: number;
17};
18
19export type CtoSPlayerJoinPacket = {
20 type: "playerJoin";
21 sessionToken: string;
22 data: {
23 gameCode: string;
24 };
25};
26
27export type CtoSPlayerChatPacket = CtoSBasePacket & {
28 type: "playerChat";
29 data: {
30 message: string;
31 };
32};
33
34export type CtoSRequestGameStartPacket = CtoSBasePacket & {
35 type: "requestGameStart";
36};
37
38export type CtoSRequestGameEndPacket = CtoSBasePacket & {
39 type: "requestGameEnd";
40};
41
42export type CtoSPlayerBidPacket = CtoSBasePacket & {
43 type: "playerBid";
44 data: {
45 bid: number;
46 time: number;
47 };
48};
49
50export type MoveDirection = "up" | "down" | "left" | "right";
51
52export type CtoSPlayerVerifyMovePacket = CtoSBasePacket & {
53 type: "playerVerifyMove";
54 data: {
55 rocket: Rocket;
56 direction: MoveDirection;
57 };
58};
59
60export type CtoSPlayerVerifyResetPacket = CtoSBasePacket & {
61 type: "playerVerifyReset";
62};
63
64export type CtoSUpdateSettingsPacket = CtoSBasePacket & {
65 type: "updateSettings";
66 data: Settings;
67};
68
69export type CtoSPacket =
70 | CtoSPlayerJoinPacket
71 | CtoSRequestGameStartPacket
72 | CtoSRequestGameEndPacket
73 | CtoSPlayerChatPacket
74 | CtoSPlayerBidPacket
75 | CtoSPlayerVerifyMovePacket
76 | CtoSPlayerVerifyResetPacket
77 | CtoSUpdateSettingsPacket;
78
79export type PlayerInfo = {
80 id: number;
81 username: string;
82};
83
84export type GameInfo = {
85 id: number;
86 name: string;
87 state: (typeof games.$inferSelect)["state"];
88 ownerId: number;
89};
90
91export type Bid = {
92 bid: number;
93 time: number;
94};
95
96export const compareBid = (a: Bid, b: Bid) => {
97 if (a.bid === b.bid) {
98 return a.time - b.time;
99 }
100
101 return a.bid - b.bid;
102};
103
104export type Settings = {
105 startingDelay: number;
106 verificationTime: number;
107 biddingCountdownTime: number;
108};
109
110export type GameRoom = {
111 ingameState:
112 | "starting"
113 | "nobid"
114 | "countdown"
115 | "verify"
116 | "winner"
117 | "failed";
118 board: GridType;
119 restorableRockets: Rockets;
120 currentRockets: Rockets;
121 currentBids: Record<number, Bid>; // playerId => bid
122 currentVerifyingPlayerId: number | null;
123 targetTile: TilesNoEmpty | null;
124 movesTaken: number | null;
125 wins: Record<number, TilesNoEmpty[]>;
126 usedTiles: TilesNoEmpty[];
127 settings: Settings;
128};
129
130export type StoCPlayerJoinResponse = {
131 type: "playerJoinResponse";
132 data: {
133 game: GameInfo;
134 players: PlayerInfo[];
135 room: GameRoom;
136 };
137};
138
139export type StoCErrorResponse = {
140 type: "errorResponse";
141 data: {
142 message: string;
143 };
144};
145
146export type StoCResponsePacket = StoCPlayerJoinResponse | StoCErrorResponse;
147
148export type StoCPlayerJoinEvent = {
149 type: "playerJoinedEvent";
150 data: PlayerInfo;
151};
152
153export type Chat = {
154 playerId: number;
155 message: string;
156};
157
158export type StoCPlayerChatEvent = {
159 type: "playerChatEvent";
160 data: Chat;
161};
162
163export type StoCGameStartEvent = {
164 type: "gameStartEvent";
165 data: {
166 startUnix: number;
167 room: GameRoom;
168 };
169};
170
171export type StoCGamEndEvent = {
172 type: "gameEndEvent";
173};
174
175export type StoCGameRevealBoardEvent = {
176 type: "gameRevealBoard";
177 data: {
178 room: GameRoom;
179 };
180};
181
182export type StoCPlayerBidEvent = {
183 type: "playerBidEvent";
184 data: {
185 playerId: number;
186 bid: Bid;
187 endUnix: number | null;
188 };
189};
190
191export type StoCGameStartVerificationEvent = {
192 type: "gameStartVerification";
193 data: {
194 playerId: number;
195 endUnix: number;
196 };
197};
198
199export type StoCPlayerVerifyMoveEvent = {
200 type: "playerVerifyMove";
201 data: {
202 rocket: Rocket;
203 direction: MoveDirection;
204 };
205};
206
207export type StoCPlayerVerifyResetEvent = {
208 type: "playerVerifyReset";
209};
210
211export type StoCPlayerVerifyCompletedEvent = {
212 type: "playerVerifyCompleted";
213 data: {
214 wins: Record<number, TilesNoEmpty[]>;
215 endUnix: number;
216 };
217};
218
219export type StoCGameVerifyNextEvent = {
220 type: "gameVerifyNext";
221 data: {
222 newCurrentBids: Record<number, Bid>;
223 newVerifyingPlayerId: number;
224 endUnix: number;
225 };
226};
227
228export type StoCGameVerifyFailedEvent = {
229 type: "gameVerifyFailed";
230};
231
232export type StoCGameCompletedEvent = {
233 type: "gameCompleted";
234};
235
236export type StoCEventPacket =
237 | StoCPlayerJoinEvent
238 | StoCPlayerChatEvent
239 | StoCGameStartEvent
240 | StoCGamEndEvent
241 | StoCGameRevealBoardEvent
242 | StoCPlayerBidEvent
243 | StoCGameStartVerificationEvent
244 | StoCPlayerVerifyMoveEvent
245 | StoCPlayerVerifyResetEvent
246 | StoCPlayerVerifyCompletedEvent
247 | StoCGameVerifyNextEvent
248 | StoCGameVerifyFailedEvent
249 | StoCGameCompletedEvent;
250
251export type StoCPacket = StoCEventPacket | StoCResponsePacket;