export interface TickSystemDefinition { id: TSystemId; /** Minimum real time between runs; the heartbeat fires the system on the first tick at or past it. */ intervalMs: number; scope?: "onlinePlayers" | "allServers"; batchSize?: number; } /** Last-run timestamp per system id. */ export type TickAnchors = Record; /** One due system and how many times this heartbeat owes it. */ export interface TickSystemRun { id: TSystemId; /** Times to run the system now; above 1 when wall time stalled past several intervals. */ runs: number; scope?: "onlinePlayers" | "allServers"; batchSize?: number; } export interface ServerTickPlan { /** * Due systems, at most one entry per id. `runs` carries catch-up multiplicity — the anchors were * advanced by that many intervals, so a host that runs the handler once per entry silently drops * the rest. */ due: TickSystemRun[]; anchors: TickAnchors; } export type PlanServerTickOptions = { /** Cap catch-up runs per system per heartbeat to avoid spiral-of-death. Default 3. */ maxCatchUp?: number; }; /** * Decides which systems a heartbeat should run. A system with no anchor runs immediately. * When wall time stalls past multiple intervals the system's `runs` climbs (bounded by * maxCatchUp), and the returned anchor moves by that many intervals — so a host that ignores * `runs` loses the catch-up work. Excess lag past the bound resyncs the anchor to `now`. * Returned anchors carry only systems present in the pipeline, so removed systems clean up. */ export declare function planServerTick(systems: readonly TickSystemDefinition[], anchors: TickAnchors, now: number, options?: PlanServerTickOptions): ServerTickPlan; /** Times this plan owes `id`, or 0 when it is not due. Saves a host a lookup over {@link ServerTickPlan.due}. */ export declare function tickRunCount(plan: ServerTickPlan, id: TSystemId): number;