using AcDream.App.Net;
using AcDream.App.Physics;
using AcDream.App.Rendering;
using AcDream.App.World;
using AcDream.Core.Physics;
namespace AcDream.App.Input;
///
/// Focused runtime seam for the local player's retail object and command
/// phases. The frame controller owns ordering; this seam resolves the current
/// session-scoped owners without retaining callbacks into the window host.
///
internal interface ILocalPlayerPresentationRuntime
{
bool CanPresentPlayer { get; }
PlayerMovementController? Controller { get; }
}
internal interface ILocalPlayerFrameRuntime : ILocalPlayerPresentationRuntime
{
uint ResolveLocalEntityId();
void HandleTargeting();
bool IsHidden { get; }
RetailObjectClockDisposition ObjectClockDisposition { get; }
void Project(PlayerMovementController controller, MovementResult movement, bool hidden);
void SendPreNetwork(PlayerMovementController controller, MovementResult movement, bool hidden);
void SendPostNetwork(PlayerMovementController controller, bool hidden);
}
///
/// Production local-player frame runtime composed from canonical typed owners.
///
internal sealed class LiveLocalPlayerFrameRuntime : ILocalPlayerFrameRuntime
{
private readonly CameraController _camera;
private readonly ILocalPlayerModeSource _mode;
private readonly ILocalPlayerControllerSource _controller;
private readonly IChaseCameraSource _chase;
private readonly DispatcherMovementInputSource _input;
private readonly IInputCaptureSource _capture;
private readonly LiveEntityRuntime _liveEntities;
private readonly ILocalPlayerIdentitySource _identity;
private readonly ILocalPlayerPhysicsHostSource _physicsHost;
private readonly LocalPlayerProjectionController _projection;
private readonly LocalPlayerOutboundController _outbound;
private readonly ILiveWorldSessionSource _session;
public LiveLocalPlayerFrameRuntime(
CameraController camera,
ILocalPlayerModeSource mode,
ILocalPlayerControllerSource controller,
IChaseCameraSource chase,
DispatcherMovementInputSource input,
IInputCaptureSource capture,
LiveEntityRuntime liveEntities,
ILocalPlayerIdentitySource identity,
ILocalPlayerPhysicsHostSource physicsHost,
LocalPlayerProjectionController projection,
LocalPlayerOutboundController outbound,
ILiveWorldSessionSource session)
{
_camera = camera ?? throw new ArgumentNullException(nameof(camera));
_mode = mode ?? throw new ArgumentNullException(nameof(mode));
_controller = controller ?? throw new ArgumentNullException(nameof(controller));
_chase = chase ?? throw new ArgumentNullException(nameof(chase));
_input = input ?? throw new ArgumentNullException(nameof(input));
_capture = capture ?? throw new ArgumentNullException(nameof(capture));
_liveEntities = liveEntities ?? throw new ArgumentNullException(nameof(liveEntities));
_identity = identity ?? throw new ArgumentNullException(nameof(identity));
_physicsHost = physicsHost ?? throw new ArgumentNullException(nameof(physicsHost));
_projection = projection ?? throw new ArgumentNullException(nameof(projection));
_outbound = outbound ?? throw new ArgumentNullException(nameof(outbound));
_session = session ?? throw new ArgumentNullException(nameof(session));
}
public bool CanPresentPlayer =>
!_camera.IsFlyMode
&& _mode.IsPlayerMode
&& _controller.Controller is not null
&& _chase.Legacy is not null
&& _input.IsAvailable
&& !_capture.DevToolsWantCaptureKeyboard;
public PlayerMovementController? Controller => _controller.Controller;
public uint ResolveLocalEntityId() =>
_liveEntities.TryGetWorldEntity(_identity.ServerGuid, out var entity)
? entity.Id
: 0u;
public void HandleTargeting() => _physicsHost.Host?.HandleTargetting();
public bool IsHidden => _liveEntities.IsHidden(_identity.ServerGuid);
public RetailObjectClockDisposition ObjectClockDisposition =>
_liveEntities.GetRootObjectClockDisposition(_identity.ServerGuid);
public void Project(
PlayerMovementController controller,
MovementResult movement,
bool hidden) =>
_projection.Project(controller, movement, hidden);
public void SendPreNetwork(
PlayerMovementController controller,
MovementResult movement,
bool hidden) =>
_outbound.SendPreNetworkActions(
_session.CurrentSession,
controller,
movement,
hidden);
public void SendPostNetwork(
PlayerMovementController controller,
bool hidden) =>
_outbound.SendPostNetworkPosition(
_session.CurrentSession,
controller,
hidden);
}