export interface TimeConfig { /** Game-seconds that elapse per real second at 1× speed. Default 1 (real time). Sims-style compression sets this high (e.g. 60 → one real second is one in-game minute). */ scale?: number; /** Selectable play/fast-forward multipliers for the speed control. Default [1, 2, 3, 4]. Pause (0×) is always available and separate. */ speeds?: readonly number[]; /** Game-seconds in one in-world day; drives the 24-hour calendar breakdown. Default 86400 (1 game-second = 1 clock-second). */ dayLength?: number; /** Game-seconds already elapsed at boot — start the world at 08:00 with `8 * 3600`. Default 0. */ start?: number; /** Boot with the clock paused. Default false. */ startPaused?: boolean; /** In-world days per year, driving `calendar().year`/`dayOfYear`/`yearFraction`. Default 365. */ daysPerYear?: number; /** Named season segments spanning the year in equal shares; when set, `calendar().season` names the current one. */ seasons?: readonly string[]; } export interface CalendarTime { /** Total game-seconds since the world started. */ totalSeconds: number; /** 0-based day index. */ day: number; hour: number; minute: number; second: number; /** Progress through the current day, 0..1. */ dayFraction: number; /** 0-based year index, using `daysPerYear` (default 365). */ year: number; /** 0-based day index within the current year. */ dayOfYear: number; /** Progress through the current year, 0..1. */ yearFraction: number; /** Current season name, present only when `TimeConfig.seasons` is configured. */ season?: string; } export interface ClockSnapshot { now: number; paused: boolean; /** Speed-control multiplier — 0 while paused. The full game-time rate is `speed × timescale × scale`. */ speed: number; /** The non-zero multiplier `play()` resumes to. */ playSpeed: number; /** Global slow-motion/fast-forward multiplier; 1 unless `setTimescale` was called. */ timescale: number; scale: number; speeds: readonly number[]; calendar: CalendarTime; } export interface SimClock { /** Advance the clock directly when used alone. A GameContext's `ctx.sim.advance` owns this call once per step and passes scaled dt to its callback; game loops must not advance it again. */ advance(realDt: number): number; now(): number; /** Local accepted advance seconds × play speed × timescale, excluding calendar scale and saved offsets. Never hydrated or serialized; optional for external clocks. */ advancedSeconds?(): number; snapshot(): ClockSnapshot; /** Restore clock position — game-time, pause state, and speed multipliers — from a {@link ClockSnapshot} for whole-world save/load. Live timers registered via `after`/`every`/`at` are unaffected. */ hydrate(snapshot: ClockSnapshot): void; calendar(): CalendarTime; isPaused(): boolean; speed(): number; pause(): void; play(): void; toggle(): void; /** Set the play multiplier; `0` (or negative) pauses, any positive value unpauses and becomes the resume speed. */ setSpeed(multiplier: number): void; /** Step to the next configured speed (wraps); always unpauses. */ cycleSpeed(): void; /** Current global timescale multiplier; 1 by default. */ timescale(): number; /** * Global slow-motion/fast-forward multiplier composed with the speed control — * `advance` returns `realDt × scale × speed × timescale`. `0` freezes game time * without flipping pause state (`0.08` = bullet time, `2` = fast-forward); negative * or non-finite values clamp to 0. Timescale is host-authoritative: in multiplayer * it belongs to the host simulation, never to an individual client. */ setTimescale(multiplier: number): void; /** Run `callback` once, `seconds` of game-time from now. Returns a cancel handle. */ after(seconds: number, callback: () => void): () => void; /** Run `callback` every `seconds` of game-time. Returns a cancel handle. */ every(seconds: number, callback: () => void): () => void; /** Run `callback` when game-time reaches the absolute `time` (game-seconds). Returns a cancel handle. */ at(time: number, callback: () => void): () => void; } export interface SimClockOptions { config?: TimeConfig; /** Called on control changes and once per displayed in-game minute so UI can rebind; never fires per frame. */ onChange?: () => void; } export declare function createSimClock(options?: SimClockOptions): SimClock & { advancedSeconds(): number; };