using AcDream.App.Update; using AcDream.Runtime; namespace AcDream.App.Input; /// /// Owns the local player's once-per-frame retail object phase. /// /// /// Retail advances the player and sends input-originated movement/jump output /// before SmartBox::UseTime drains inbound events. Its later /// CommandInterpreter::UseTime position check uses current post-inbound /// state. The cached input result is presentation-only after the barrier: its /// one-shot commands are never replayed against a later authoritative cell. /// internal sealed class RetailLocalPlayerFrameController : IPostNetworkCommandFramePhase { private readonly RuntimeLocalPlayerFrameController _runtime; public readonly record struct PresentationFrame( MovementResult Movement, bool Hidden, bool AdvancedBeforeNetwork); /// /// Whether the pre-network Hidden player update admitted a complete object /// quantum whose retained CPartArray pose must be sampled this frame. /// internal bool HiddenPartPoseDirty => _runtime.HiddenPartPoseDirty; public RetailLocalPlayerFrameController( ILocalPlayerFrameRuntime runtime, IMovementInputSource movementInput) { _runtime = new RuntimeLocalPlayerFrameController( runtime ?? throw new ArgumentNullException(nameof(runtime)), movementInput ?? throw new ArgumentNullException(nameof(movementInput))); } public RetailLocalPlayerFrameController( GameRuntime gameRuntime, ILocalPlayerFrameRuntime runtime, IMovementInputSource movementInput) { ArgumentNullException.ThrowIfNull(gameRuntime); _runtime = gameRuntime.CreateLocalPlayerFrameController( runtime ?? throw new ArgumentNullException(nameof(runtime)), movementInput ?? throw new ArgumentNullException(nameof(movementInput))); } /// /// Advances the existing local object exactly once on the object side of /// the inbound-network barrier. /// public void AdvanceBeforeNetwork(float deltaSeconds) => _runtime.AdvanceBeforeNetwork(deltaSeconds); /// /// Runs retail's post-inbound command-interpreter phase. The split /// controller/render projection is reconciled without advancing physics, /// then AutonomousPosition is evaluated from that current state. /// public void RunPostNetworkCommandPhase() => _runtime.RunPostNetworkCommandPhase(); /// /// Produces the post-network presentation sample without advancing /// physics. An owner first created by the inbound pass is seeded from its /// current state and receives its first real object tick next frame. /// public bool TryGetPresentationAfterNetwork(out PresentationFrame frame) { bool available = _runtime.TryGetPresentationAfterNetwork( out AcDream.Runtime.Gameplay.RuntimeLocalPlayerPresentationFrame shared); frame = available ? new PresentationFrame( shared.Movement, shared.Hidden, shared.AdvancedBeforeNetwork) : default; return available; } }