import { z } from "zod"; import { displayNameSchema } from "./account"; import type { Bounds, DifficultyPreset } from "./protocol"; export const createRoomSchema = z .object({ datasetId: z.string().uuid(), difficulty: z.union([ z.enum(["easy", "normal", "hard", "void"]), z.string().uuid(), ]), playerLimit: z.number().int().min(2).max(16), }) .strict(); export const joinRoomSchema = z.object({ displayName: displayNameSchema }); export const chatMessageSchema = z.object({ clientId: z.string().uuid(), text: z .string() .trim() .min(1) .max(500) .refine( (text) => !/[\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/u.test(text), "Messages cannot contain hidden controls", ), }); export type RoomChat = { messages: { id: string; playerId: string; name: string; appearance?: import("./profile-appearance").ProfileAppearance; text: string; tag?: string | null; createdAt: string; }[]; }; export const roomRoundSchema = z.object({ round: z.number().int().min(0).max(4), }); export const roomGuessSchema = roomRoundSchema.extend({ x: z.number().finite(), z: z.number().finite(), }); export type RoomResult = { playerId: string; score: number; distance: number | null; timedOut: boolean; actual: { x: number; z: number }; guess: { x: number; z: number } | null; }; export type RoomView = { discord?: import("./discord").PartyAnnouncement; id: string; datasetId: string; name: string; difficulty: string; difficultySettings: DifficultyPreset; playerLimit: number; playerCount: number; status: "lobby" | "loading" | "playing" | "results" | "finished" | "closed"; round: number; hostId: string; you: string | null; serverNow: number; transitionAt: string | null; players: { id: string; name: string; appearance?: import("./profile-appearance").ProfileAppearance; left: boolean; ready: boolean; submitted: boolean; total: number; rank: number; }[]; rounds: { number: number; deadline: string | null; closedAt: string | null; results: RoomResult[]; }[]; myGuess: { x: number; z: number } | null; }; export type RoomMedia = { round: number; map: string; bounds: Bounds; faces: string[]; };