Exact source used by this build. SHA-256: c8cda3e3bcb83a466d3daa699e2abd143d34fb69e2effe8da0da99d8e659ed14.
1 export type Season = "spring" | "summer" | "autumn" | "winter";
2 export type Facing = "up" | "down" | "left" | "right";
3 export type Weather = "sunny" | "rain" | "storm" | "wind" | "snow";
4 export type Tool = "hoe" | "wateringCan";
5
6 export interface CropDefinition {
7 id: string;
8 name: string;
9 description: string;
10 seasons: readonly Season[];
11 growthStages: readonly { days: number }[];
12 regrowthDays: number | null;
13 sellPrice: number;
14 seedPrice: number;
15 }
16
17 export interface CropInstance {
18 cropId: string;
19 /** Zero based stage index. */
20 stage: number;
21 /** Watered days accumulated within this stage. */
22 daysInStage: number;
23 /** True when a crop can be harvested. */
24 ready: boolean;
25 /** True only after harvesting a regrowing crop. */
26 regrowing: boolean;
27 }
28
29 export interface Landmark { id: string; kind: "home"; x: number; y: number; width: number; height: number }
30 /** Authored interaction targets; content owns names and any additional presentation metadata. */
31 export interface PointOfInterest { id: string; kind: string; x: number; y: number; width: number; height: number }
32
33 export interface Tile {
34 ground: string;
35 tillable: boolean;
36 tilled: boolean;
37 watered: boolean;
38 objectId: string | null;
39 /** Occupies the tile for placement/planting but allows walking, e.g. a path. */
40 walkableObject?: boolean;
41 crop: CropInstance | null;
42 }
43
44 export interface Warp {
45 id: string; x: number; y: number; width: number; height: number;
46 targetAreaId: string; targetX: number; targetY: number;
47 locked: boolean; label: string; kind?: string;
48 }
49 export interface SeasonAppearance { tint: number; groundCover: string; groundColor: number; foliageColor: number }
50 export interface Area {
51 id: string;
52 width: number;
53 height: number;
54 tiles: Tile[];
55 /** Time cost in real milliseconds for one game minute in this area. */
56 clockRateMsPerGameMinute: number;
57 spawn: TilePosition;
58 landmarks: Landmark[];
59 pois?: PointOfInterest[];
60 name?: string;
61 outdoor: boolean;
62 locked: boolean;
63 collision: boolean[];
64 groundTiles: number[];
65 decorTiles: number[];
66 warps: Warp[];
67 seasons?: Record<Season, SeasonAppearance>;
68 systems: Record<string, unknown>;
69 }
70
71 export interface AreaConfig {
72 id: string;
73 width: number;
74 height: number;
75 ground: string;
76 tillable: boolean;
77 clockRateMsPerGameMinute?: number;
78 spawn?: TilePosition;
79 landmarks?: Landmark[];
80 pois?: PointOfInterest[];
81 name?: string;
82 outdoor?: boolean;
83 locked?: boolean;
84 collision?: boolean[];
85 groundTiles?: number[];
86 decorTiles?: number[];
87 tillableTiles?: boolean[];
88 warps?: Warp[];
89 seasons?: Record<Season, SeasonAppearance>;
90 }
91 export interface StarterPlayer { areaId: string; x: number; y: number; facing: Facing; inventory: Record<string, number> }
92 export interface WorldConfig { id: string; areas: readonly AreaConfig[]; starterPlayer?: StarterPlayer }
93
94 export interface Player {
95 id: string;
96 name: string;
97 areaId: string;
98 x: number;
99 y: number;
100 facing: Facing;
101 energy: number;
102 maxEnergy: number;
103 inventory: Record<string, number>;
104 connected: boolean;
105 sleeping: boolean;
106 sleepConfirmedAt: number | null;
107 /** Set during a forced 2 AM end-of-day so overnight does not restore energy. */
108 passedOut: boolean;
109 systems: Record<string, unknown>;
110 }
111
112 export interface Clock {
113 year: number;
114 season: Season;
115 day: number;
116 weekday: number;
117 /** Minutes after midnight. 6:00 is 360 and 2:00 AM next day is 1560. */
118 minuteOfDay: number;
119 realMsRemainder: number;
120 machineMinutes: number;
121 }
122
123 export interface Wallet {
124 mode: "shared" | "separate";
125 shared: number;
126 balances: Record<string, number>;
127 ledger: WalletLedgerEntry[];
128 }
129 export interface WalletLedgerEntry { fromPlayerId: string; toPlayerId: string; amount: number }
130
131 export interface WorldState {
132 revision: number;
133 clock: Clock;
134 areas: Record<string, Area>;
135 players: Record<string, Player>;
136 wallet: Wallet;
137 rngState: number;
138 paused: boolean;
139 starterPlayer: StarterPlayer;
140 weather: Weather;
141 systems: Record<string, unknown>;
142 }
143
144 /** Derived from the registered system schemas; no protocol list to maintain. */
145 export type Intent = import("zod").z.infer<typeof import("./systems").IntentSchema>;
146
147 export interface TilePosition { x: number; y: number }
148 export interface SimEvent {
149 /** Presentation/progress only: broadcast live, persist with the next bounded flush. */
150 transient?: boolean;
151 type: string;
152 areaId?: string;
153 checkpoint?: boolean;
154 snapshot?: boolean;
155 data?: Record<string, unknown>;
156 playerId?: string;
157 message?: string;
158 }
159
160 export interface IntentResult {
161 state: WorldState;
162 events: SimEvent[];
163 error?: string;
164 /** Accepted input cost for the server's generic elapsed-time credit bucket. */
165 timingCostMs?: number;
166 }
167 export interface SimRules {
168 /** Domain-keyed validated content, injected by the content registry for independent systems. */
169 content?: Readonly<Record<string, unknown>>;
170 crops: Record<string, CropDefinition>;
171 /** Map a seed item id to its crop id. */
172 seedToCrop?: Record<string, string>;
173 weatherOdds?: Record<Season, Record<Weather, number>>;
174 }
175