All checks were successful
Deploy MineGeo to Dokploy / deploy (push) Successful in 12m17s
94 lines
2.3 KiB
TypeScript
94 lines
2.3 KiB
TypeScript
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[];
|
|
};
|