Schema cleanup (#1219)

## Description:

Cleanup schemas that are using `z.discriminatedUnion()`.

## 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
- [x] I understand that submitting code with bugs that could have been
caught through manual testing blocks releases and new features for all
contributors

---------

Co-authored-by: Scott Anderson <662325+scottanderson@users.noreply.github.com>
This commit is contained in:
Scott Anderson
2025-06-18 03:29:49 -04:00
committed by GitHub
parent c0ada43740
commit 85d94e484a
+56 -41
View File
@@ -122,6 +122,10 @@ export enum LogSeverity {
Fatal = "FATAL",
}
//
// Utility types
//
export const GameConfigSchema = z.object({
gameMap: z.nativeEnum(GameMapType),
difficulty: z.nativeEnum(Difficulty),
@@ -170,7 +174,19 @@ export const ID = z
export const AllPlayersStatsSchema = z.record(ID, PlayerStatsSchema);
// Zod schemas
export const UsernameSchema = SafeString;
export const FlagSchema = z.string().max(128).optional();
export const QuickChatKeySchema = z.enum(
Object.entries(quickChatData).flatMap(([category, entries]) =>
entries.map((entry) => `${category}.${entry.key}`),
) as [string, ...string[]],
);
//
// Intents
//
const BaseIntentSchema = z.object({
clientID: ID,
});
@@ -181,9 +197,6 @@ export const AttackIntentSchema = BaseIntentSchema.extend({
troops: z.number().nullable(),
});
export const UsernameSchema = SafeString;
export const FlagSchema = z.string().max(128).optional();
export const SpawnIntentSchema = BaseIntentSchema.extend({
type: z.literal("spawn"),
name: UsernameSchema,
@@ -282,12 +295,6 @@ export const MoveWarshipIntentSchema = BaseIntentSchema.extend({
tile: z.number(),
});
export const QuickChatKeySchema = z.enum(
Object.entries(quickChatData).flatMap(([category, entries]) =>
entries.map((entry) => `${category}.${entry.key}`),
) as [string, ...string[]],
);
export const QuickChatIntentSchema = BaseIntentSchema.extend({
type: z.literal("quick_chat"),
recipient: ID,
@@ -322,6 +329,10 @@ const IntentSchema = z.discriminatedUnion("type", [
QuickChatIntentSchema,
]);
//
// Server utility types
//
export const TurnSchema = z.object({
turnNumber: z.number(),
intents: IntentSchema.array(),
@@ -329,26 +340,6 @@ export const TurnSchema = z.object({
hash: z.number().nullable().optional(),
});
// Server
const ServerBaseMessageSchema = z.object({
type: z.enum(["turn", "ping", "prestart", "start", "desync", "error"]),
});
export const ServerTurnMessageSchema = ServerBaseMessageSchema.extend({
type: z.literal("turn"),
turn: TurnSchema,
});
export const ServerPingMessageSchema = ServerBaseMessageSchema.extend({
type: z.literal("ping"),
});
export const ServerPrestartMessageSchema = ServerBaseMessageSchema.extend({
type: z.literal("prestart"),
gameMap: z.nativeEnum(GameMapType),
});
export const PlayerSchema = z.object({
clientID: ID,
username: UsernameSchema,
@@ -361,14 +352,40 @@ export const GameStartInfoSchema = z.object({
players: PlayerSchema.array(),
});
export const ServerStartGameMessageSchema = ServerBaseMessageSchema.extend({
export const WinnerSchema = z
.union([
z.tuple([z.literal("player"), ID]),
z.tuple([z.literal("team"), SafeString]),
])
.optional();
export type Winner = z.infer<typeof WinnerSchema>;
//
// Server
//
export const ServerTurnMessageSchema = z.object({
type: z.literal("turn"),
turn: TurnSchema,
});
export const ServerPingMessageSchema = z.object({
type: z.literal("ping"),
});
export const ServerPrestartMessageSchema = z.object({
type: z.literal("prestart"),
gameMap: z.nativeEnum(GameMapType),
});
export const ServerStartGameMessageSchema = z.object({
type: z.literal("start"),
// Turns the client missed if they are late to the game.
turns: TurnSchema.array(),
gameStartInfo: GameStartInfoSchema,
});
export const ServerDesyncSchema = ServerBaseMessageSchema.extend({
export const ServerDesyncSchema = z.object({
type: z.literal("desync"),
turn: z.number(),
correctHash: z.number().nullable(),
@@ -377,7 +394,7 @@ export const ServerDesyncSchema = ServerBaseMessageSchema.extend({
yourHash: z.number().optional(),
});
export const ServerErrorSchema = ServerBaseMessageSchema.extend({
export const ServerErrorSchema = z.object({
type: z.literal("error"),
error: z.string(),
});
@@ -391,15 +408,9 @@ export const ServerMessageSchema = z.discriminatedUnion("type", [
ServerErrorSchema,
]);
//
// Client
export const WinnerSchema = z
.union([
z.tuple([z.literal("player"), ID]),
z.tuple([z.literal("team"), SafeString]),
])
.optional();
export type Winner = z.infer<typeof WinnerSchema>;
//
export const ClientSendWinnerSchema = z.object({
type: z.literal("winner"),
@@ -448,6 +459,10 @@ export const ClientMessageSchema = z.discriminatedUnion("type", [
ClientHashSchema,
]);
//
// Records
//
export const PlayerRecordSchema = PlayerSchema.extend({
persistentID: PersistentIdSchema, // WARNING: PII
stats: PlayerStatsSchema,