Exact source used by this build. SHA-256: 013e9fa9a179482364d1894361d592b18652d552a20f23249fa14a63672509ec.
1 import type { Crop, FarmConfig, Item } from "./schemas";
2
3 function unique(label: string, ids: readonly string[]): void {
4 if (new Set(ids).size !== ids.length) throw new Error(`${label} ids must be unique`);
5 }
6
7 export function validateContent(crops: readonly Crop[], items: readonly Item[], farm: FarmConfig): void {
8 unique("crop", crops.map((crop) => crop.id));
9 unique("item", items.map((item) => item.id));
10 unique("area", farm.areas.map((area) => area.id));
11 for (const item of items) {
12 if (item.kind === "seed" && !crops.some((crop) => crop.id === item.cropId)) throw new Error(`seed ${item.id} refers to a missing crop`);
13 }
14 for (const crop of crops) {
15 if (!items.some((item) => item.kind === "seed" && item.cropId === crop.id)) throw new Error(`crop ${crop.id} has no seed item`);
16 if (!items.some((item) => item.kind === "crop" && item.cropId === crop.id)) throw new Error(`crop ${crop.id} has no produce item`);
17 }
18 for (const area of farm.areas) {
19 for (const landmark of area.landmarks) {
20 if (landmark.x + landmark.width > area.width || landmark.y + landmark.height > area.height) throw new Error(`landmark ${landmark.id} is outside area ${area.id}`);
21 }
22 }
23 const starterArea = farm.areas.find((area) => area.id === farm.starterPlayer.areaId);
24 if (!starterArea) throw new Error("starter player refers to a missing area");
25 if (farm.starterPlayer.x >= starterArea.width || farm.starterPlayer.y >= starterArea.height) throw new Error("starter player is outside its area");
26 for (const itemId of Object.keys(farm.starterPlayer.inventory)) {
27 if (!items.some((item) => item.id === itemId)) throw new Error(`starter inventory refers to a missing item ${itemId}`);
28 }
29 }
30