namespace Age.Engine.Hosting; /// Host-owned virtual clock + per-frame op budget. Pure (no threading): the Godot host /// advances it once per rendered frame and consults it to pace the VM. The one /// factor is the future (unwired) Ctrl fast-forward multiplier — scaling it scales the throttle /// budget, sleeps, and the anim tween together. See docs/superpowers/specs/2026-07-08-frame-stepped-vm-design.md. public sealed class FrameClock { /// Monotonic virtual time in milliseconds (scaled by Speed). public long NowMs { get; private set; } /// Speed multiplier. 1.0 = normal. The future Ctrl hook (ADV-scoped); leave at 1.0 for now. public double Speed = 1.0; /// Base per-frame interpreter op budget (tunable by eye; ~30 ≈ 1,800 ops/sec at 60fps). public int OpsPerFrame = 30; /// Advance the clock by one rendered frame's real delta (seconds), scaled by Speed. public void Advance(double realDeltaSeconds) => NowMs += (long)(realDeltaSeconds * 1000.0 * Speed); /// Ops the VM may run before yielding a frame, scaled by Speed (min 1). public int EffectiveBudget => System.Math.Max(1, (int)System.Math.Round(OpsPerFrame * Speed)); }