Exact source used by this build. SHA-256: 3ee9c0ce5e58b8f3d98e71e092644d12171140a619d0978f60b0ea017945329b.
1 import { z } from "zod";
2
3 /** Fishing habitats belong to the authored water tiles, not coordinate copies. */
4 export const WaterTagSchema = z.enum(["river", "lake", "ocean", "mountain_lake", "rainforest_river", "bog"]);
5
6 export const TiledPropertySchema = z.object({
7 name: z.string().min(1), type: z.string(), value: z.union([z.string(), z.number().finite(), z.boolean()]),
8 });
9 export const TiledObjectSchema = z.object({
10 id: z.number().int().positive(), name: z.string().min(1), type: z.string(),
11 x: z.number().nonnegative(), y: z.number().nonnegative(),
12 width: z.number().nonnegative(), height: z.number().nonnegative(),
13 properties: TiledPropertySchema.array().default([]),
14 });
15 export const TiledTileLayerSchema = z.object({
16 type: z.literal("tilelayer"), name: z.string(), width: z.number().int().positive(), height: z.number().int().positive(),
17 data: z.array(z.number().int().nonnegative()),
18 });
19 export const TiledObjectLayerSchema = z.object({
20 type: z.literal("objectgroup"), name: z.string(), objects: TiledObjectSchema.array(),
21 });
22 export const TiledMapSchema = z.object({
23 type: z.literal("map"), orientation: z.literal("orthogonal"), infinite: z.literal(false),
24 width: z.number().int().positive(), height: z.number().int().positive(),
25 tilewidth: z.literal(16), tileheight: z.literal(16),
26 properties: TiledPropertySchema.array(),
27 layers: z.array(z.discriminatedUnion("type", [TiledTileLayerSchema, TiledObjectLayerSchema])),
28 tilesets: z.array(z.object({
29 firstgid: z.number().int().positive(), tilecount: z.number().int().positive(),
30 tilewidth: z.literal(16), tileheight: z.literal(16), image: z.string().min(1),
31 tiles: z.array(z.object({
32 id: z.number().int().nonnegative(), properties: TiledPropertySchema.array().default([]),
33 })).default([]),
34 })).min(1),
35 });
36 export const WarpSchema = z.object({
37 id: z.string().min(1), x: z.number().nonnegative(), y: z.number().nonnegative(),
38 width: z.number().positive(), height: z.number().positive(),
39 targetAreaId: z.string().min(1), targetX: z.number().nonnegative(), targetY: z.number().nonnegative(),
40 locked: z.boolean(), label: z.string().min(1), kind: z.string().min(1),
41 manifestKey: z.string().min(1).optional(),
42 });
43 export type AreaWarp = z.infer<typeof WarpSchema>;
44 export type TiledMap = z.infer<typeof TiledMapSchema>;
45
46 /** Named, content-owned schedule/festival targets. Display copy is deliberately unfilled. */
47 export const MapPoiSchema = z.object({
48 id: z.string().regex(/^poi\.[a-z][a-z0-9_]*\.[a-z][a-z0-9_.]*$/),
49 kind: z.string().min(1), name: z.string().min(1), description: z.string().min(1),
50 manifestKey: z.string().min(1), label: z.string().min(1).optional(),
51 x: z.number().nonnegative(), y: z.number().nonnegative(),
52 width: z.number().nonnegative(), height: z.number().nonnegative(),
53 });
54 export type MapPoi = z.infer<typeof MapPoiSchema>;
55
56 export interface AreaMap {
57 id: string;
58 width: number;
59 height: number;
60 tileSize: 16;
61 outdoor: boolean;
62 groundTiles: number[];
63 decorTiles: number[];
64 buildingTiles: number[];
65 frontTiles: number[];
66 alwaysFrontTiles: number[];
67 /** Keys point into the future art manifest; tile GIDs remain valid blockout fallbacks. */
68 tileManifest: Record<number, string>;
69 waterTags: Record<number, z.infer<typeof WaterTagSchema>>;
70 collision: boolean[];
71 tillableTiles: boolean[];
72 spawn: { x: number; y: number };
73 warps: AreaWarp[];
74 pois: MapPoi[];
75 landmarks: { id: string; kind: "home"; x: number; y: number; width: number; height: number }[];
76 markers: { id: string; label: string; kind: string; x: number; y: number; width: number; height: number }[];
77 }
78