Exact source used by this build. SHA-256: 94b5900333f13e50689bb9c6f707e5bd5f08018b8e1a8241108c3935a2752c9a.

1 import { z } from "zod";
2 
3 const Id = z.string().min(1);
4 const Skill = z.enum(["farming", "mining", "foraging", "fishing", "combat"]);
5 const ItemCategory = z.enum(["seed", "crop", "forage", "fish", "mineral", "artisan", "cooked", "material", "tool", "equipment", "furniture", "misc"]);
6 export const IngredientSchema = z.object({
7   itemId: Id.optional(), tag: Id.optional(), category: ItemCategory.optional(),
8   quantity: z.number().int().positive(),
9 }).refine((value) => [value.itemId, value.tag, value.category].filter(Boolean).length === 1, "An ingredient needs exactly one selector");
10 export const UnlockSchema = z.discriminatedUnion("kind", [
11   z.object({ kind: z.literal("default") }),
12   z.object({ kind: z.literal("skill"), skill: Skill, level: z.number().int().min(1).max(10) }),
13   z.object({ kind: z.literal("purchase"), shopId: Id, price: z.number().int().positive() }),
14   z.object({ kind: z.literal("friendship"), villagerId: Id, hearts: z.number().int().min(1).max(14) }),
15 ]);
16 const OutputSchema = z.object({ itemId: Id, quantity: z.number().int().positive() });
17 export const RecipeSchema = z.object({
18   id: Id, name: Id, description: z.string(), kind: z.enum(["crafting", "cooking"]),
19   ingredients: IngredientSchema.array().min(1), output: OutputSchema,
20   unlock: UnlockSchema, visualKey: Id,
21 });
22 const OffsetSchema = z.object({ x: z.number().int(), y: z.number().int() });
23 export const PlacementSchema = z.object({
24   itemId: Id, kind: z.enum(["chest", "fence", "path", "sprinkler", "scarecrow", "machine", "cookout", "torch", "sign", "crabPot"]),
25   width: z.number().int().positive(), height: z.number().int().positive(), collision: z.boolean(),
26   pickupTool: z.enum(["axe", "pickaxe"]), visualKey: Id,
27   sprinklerOffsets: OffsetSchema.array().optional(), protectionOffsets: OffsetSchema.array().optional(),
28   machineId: Id.optional(), requiresTree: z.boolean().optional(),
29 });
30 export const ProcessingRecipeSchema = z.object({
31   id: Id, input: IngredientSchema.nullable(), fuel: IngredientSchema.array(), output: OutputSchema,
32   minutes: z.number().positive(), priceFormula: z.object({ multiplier: z.number().nonnegative(), add: z.number().int().nonnegative() }).optional(),
33   treeKinds: Id.array().optional(),
34 });
35 export const MachineSchema = z.object({ id: Id, kind: z.enum(["keg", "preserves", "dairy", "tapper", "furnace"]), recipes: ProcessingRecipeSchema.array().min(1) });
36 export const BuffEffectsSchema = z.object({
37   farming: z.number().optional(), fishing: z.number().optional(), mining: z.number().optional(), foraging: z.number().optional(), combat: z.number().optional(),
38   speed: z.number().optional(), luck: z.number().optional(), defense: z.number().optional(), attack: z.number().optional(), maxEnergy: z.number().optional(),
39 });
40 export const ConsumableSchema = z.object({
41   itemId: Id, kind: z.enum(["food", "drink"]), energy: z.number().int(), health: z.number().int().nonnegative(),
42   buff: z.object({ durationMs: z.number().int().positive(), effects: BuffEffectsSchema }).nullable(),
43 });
44 export const CraftingSchema = z.object({
45   externalTags: z.enum(["milk", "egg"]).array(), externalCategories: z.literal("fish").array(),
46   recipes: RecipeSchema.array(), placements: PlacementSchema.array(), machines: MachineSchema.array(), consumables: ConsumableSchema.array(),
47   fertilizers: z.array(z.object({ itemId: Id, kind: z.enum(["quality", "waterRetention"]), qualityLevel: z.number().int().min(0).max(3), retentionChance: z.number().min(0).max(1) })),
48   bombs: z.array(z.object({ itemId: Id, radius: z.number().int().positive(), fuseMs: z.number().int().positive(), damage: z.number().int().positive() })),
49   hooks: z.array(z.object({ itemId: Id, kind: z.enum(["crabPot", "bait", "staircase"]), ownerSystem: Id, targetItemId: Id.optional() })),
50   visuals: z.array(z.object({ itemId: Id, icon: Id, world: Id.optional() })),
51   settings: z.object({
52     nearbyChestRadius: z.number().nonnegative(), defaultMaxHealth: z.number().int().positive(),
53     crows: z.object({ minimumCrops: z.number().int().positive(), cropsPerAttempt: z.number().int().positive(), maximumAttempts: z.number().int().positive(), chance: z.number().min(0).max(1), targetAttempts: z.number().int().positive(), minimumGrowthStage: z.number().int().nonnegative(), areaIds: Id.array() }),
54     kitchen: z.object({ landmarkKind: Id, requiredUpgradeLevel: z.number().int().nonnegative() }),
55     machineClock: z.object({ gameMinuteMs: z.number().positive(), nightMinutesPerHour: z.number().positive() }),
56   }),
57 });
58 export type Ingredient = z.infer<typeof IngredientSchema>;
59 export type RecipeUnlock = z.infer<typeof UnlockSchema>;
60 export type Recipe = z.infer<typeof RecipeSchema>;
61 export type Placement = z.infer<typeof PlacementSchema>;
62 export type ProcessingRecipe = z.infer<typeof ProcessingRecipeSchema>;
63 export type Machine = z.infer<typeof MachineSchema>;
64 export type Consumable = z.infer<typeof ConsumableSchema>;
65 export type BuffEffects = z.infer<typeof BuffEffectsSchema>;
66 export type CraftingContent = z.infer<typeof CraftingSchema>;
67