improve game websockt (re)connection (#2584)

Previously, the connection and reconnection logic were identical in
Worker.ts, so clients would need to be re-authorized for cosmetics etc
even when reconnecting. Now, on reconnect, Worker.ts only does
authentication - verifying the jwt is valid.

This will allow clients to require a valid turnstile token when first
connecting, and not when reconnecting after a broken ws connection.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
This commit is contained in:
Evan
2025-12-08 14:07:07 -08:00
committed by GitHub
parent cb4cf091ff
commit 075c232d8a
7 changed files with 158 additions and 56 deletions
+11 -1
View File
@@ -88,6 +88,7 @@ export type ClientMessage =
| ClientPingMessage
| ClientIntentMessage
| ClientJoinMessage
| ClientRejoinMessage
| ClientLogMessage
| ClientHashMessage;
export type ServerMessage =
@@ -110,6 +111,7 @@ export type ClientSendWinnerMessage = z.infer<typeof ClientSendWinnerSchema>;
export type ClientPingMessage = z.infer<typeof ClientPingMessageSchema>;
export type ClientIntentMessage = z.infer<typeof ClientIntentMessageSchema>;
export type ClientJoinMessage = z.infer<typeof ClientJoinMessageSchema>;
export type ClientRejoinMessage = z.infer<typeof ClientRejoinMessageSchema>;
export type ClientLogMessage = z.infer<typeof ClientLogMessageSchema>;
export type ClientHashMessage = z.infer<typeof ClientHashSchema>;
@@ -529,17 +531,25 @@ export const ClientJoinMessageSchema = z.object({
clientID: ID,
token: TokenSchema, // WARNING: PII
gameID: ID,
lastTurn: z.number(), // The last turn the client saw.
username: UsernameSchema,
// Server replaces the refs with the actual cosmetic data.
cosmetics: PlayerCosmeticRefsSchema.optional(),
});
export const ClientRejoinMessageSchema = z.object({
type: z.literal("rejoin"),
gameID: ID,
clientID: ID,
lastTurn: z.number(),
token: TokenSchema,
});
export const ClientMessageSchema = z.discriminatedUnion("type", [
ClientSendWinnerSchema,
ClientPingMessageSchema,
ClientIntentMessageSchema,
ClientJoinMessageSchema,
ClientRejoinMessageSchema,
ClientLogMessageSchema,
ClientHashSchema,
]);