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