diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonOperations.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonOperations.cs index ee337bb11..a4bd52ac4 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonOperations.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonOperations.cs @@ -186,7 +186,7 @@ namespace GameCult.Aetheria.State.Verse } } - public static readonly double[] SupportedSimulationRates = { 0, 0.25, 0.5, 1, 2, 4, 8, 16 }; + public static readonly double[] SupportedSimulationRates = { 0, 0.25, 0.5, 1, 2, 4, 8, 16, 32, 64, 128 }; public static bool IsSupportedSimulationRate(double value) => SupportedSimulationRates.Any(rate => Math.Abs(value - rate) < 0.000001); diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonTickRunner.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonTickRunner.cs index 4180fbe0f..231390b42 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonTickRunner.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonTickRunner.cs @@ -187,9 +187,9 @@ namespace GameCult.Aetheria.State.Verse options.WorldPhysics ?? throw new InvalidOperationException("Ymir world physics owner is required."), options.Catalog, options.FrameId, - options.SimulationTimeSeconds); + stepTime); Trace("world-step"); - StampZoneSimulationTime(operationResult.Run, options.SimulationTimeSeconds); + StampZoneSimulationTime(operationResult.Run, stepTime); } var frame = AetheriaRuntimeDaemonFrameDocument.Create( diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeInputCapabilityDocuments.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeInputCapabilityDocuments.cs index cd3975282..61b75c884 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeInputCapabilityDocuments.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeInputCapabilityDocuments.cs @@ -75,6 +75,9 @@ namespace GameCult.Aetheria.State.Verse actions.Add(Action("simulation.rate.quadruple", "4x Speed", "SetSimulationRate", "simulation", "terminus-clock", ("scalarValue", "4"))); actions.Add(Action("simulation.rate.eight", "8x Speed", "SetSimulationRate", "simulation", "terminus-clock", ("scalarValue", "8"))); actions.Add(Action("simulation.rate.sixteen", "16x Speed", "SetSimulationRate", "simulation", "terminus-clock", ("scalarValue", "16"))); + actions.Add(Action("simulation.rate.thirty-two", "32x Speed", "SetSimulationRate", "simulation", "terminus-clock", ("scalarValue", "32"))); + actions.Add(Action("simulation.rate.sixty-four", "64x Speed", "SetSimulationRate", "simulation", "terminus-clock", ("scalarValue", "64"))); + actions.Add(Action("simulation.rate.one-twenty-eight", "128x Speed", "SetSimulationRate", "simulation", "terminus-clock", ("scalarValue", "128"))); } if (entity != null) { diff --git a/docs/renderless-aetheria-architecture.md b/docs/renderless-aetheria-architecture.md index 102b923d8..ed3a57e5d 100644 --- a/docs/renderless-aetheria-architecture.md +++ b/docs/renderless-aetheria-architecture.md @@ -91,6 +91,35 @@ does not earn state authority merely by crossing CultNet. Separate persistence or leases are justified only for a future shared spatial Verse with an explicit owner and lifecycle; they are not part of the Aetheria daemon contract. +## Terminus Simulation Clock + +Terminus uses a daemon-owned, user-controllable simulation clock. Pause and slow +rates provide unbounded tactical decision time. High rates provide transit time +compression so a physically larger world does not require the player to watch +uneventful coasting in real time. Supported requested rates currently range from +pause through `128x`; Starbridge remains real-time-owned. + +The requested simulation rate is not a renderer time scale. The daemon advances +the deterministic fixed-step simulation repeatedly and publishes one coherent +sample of the resulting state. Unity, Electron, bots, and other Eve clients may +interpolate presentation between samples, but cannot advance committed game +time or invent intermediate outcomes. + +Time compression must eventually distinguish requested rate from effective +rate. Decision-relevant daemon facts, including contact, hostile targeting, +damage, weapon readiness, arrival, resource discovery, cargo events, docking, +and failed orders, will clamp or pause the effective rate according to an +explicit player policy. The interruption fact must name its reason and the +simulation time at which it occurred; the daemon may not simulate past that +boundary before publishing it. This attention policy is daemon-owned gameplay +state, not client heuristics. + +Compressed stepping must not multiply control-plane traffic. Commands and +receipts retain their ordinary typed CultMesh path, SoA consumers receive the +latest complete leased frame, and reactive UI state is sampled at a bounded +publication cadence. Internal fixed steps remain deterministic and testable +without requiring a renderer or wall-clock delays. + ## Current Mechanism The repo is mid-migration.