refactor(runtime): extract the live object frame
This commit is contained in:
parent
99a3e819c4
commit
4e4aac2c5a
27 changed files with 1217 additions and 371 deletions
24
src/AcDream.App/World/LiveEntityRuntimeSlot.cs
Normal file
24
src/AcDream.App/World/LiveEntityRuntimeSlot.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
namespace AcDream.App.World;
|
||||
|
||||
internal interface ILiveEntityRuntimeSource
|
||||
{
|
||||
LiveEntityRuntime? Current { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// One-time composition bridge for the resource-activation/runtime cycle.
|
||||
/// It owns no identity or entity state; all authority remains in the bound
|
||||
/// <see cref="LiveEntityRuntime"/>.
|
||||
/// </summary>
|
||||
internal sealed class LiveEntityRuntimeSlot : ILiveEntityRuntimeSource
|
||||
{
|
||||
public LiveEntityRuntime? Current { get; private set; }
|
||||
|
||||
public void Bind(LiveEntityRuntime runtime)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(runtime);
|
||||
if (Current is not null)
|
||||
throw new InvalidOperationException("The live entity runtime is already bound.");
|
||||
Current = runtime;
|
||||
}
|
||||
}
|
||||
|
|
@ -9,21 +9,21 @@ public sealed class LiveEntityAnimationRuntimeView<TAnimation>
|
|||
: IEnumerable<KeyValuePair<uint, TAnimation>>
|
||||
where TAnimation : class, ILiveEntityAnimationRuntime
|
||||
{
|
||||
private readonly Func<LiveEntityRuntime?> _runtime;
|
||||
private readonly ILiveEntityRuntimeSource _runtime;
|
||||
private readonly List<KeyValuePair<uint, TAnimation>> _iterationSnapshot = new();
|
||||
|
||||
public LiveEntityAnimationRuntimeView(Func<LiveEntityRuntime?> runtime) =>
|
||||
internal LiveEntityAnimationRuntimeView(ILiveEntityRuntimeSource runtime) =>
|
||||
_runtime = runtime ?? throw new ArgumentNullException(nameof(runtime));
|
||||
|
||||
public int Count => _runtime()?.SpatialAnimationRuntimes.Count ?? 0;
|
||||
public int Count => _runtime.Current?.SpatialAnimationRuntimes.Count ?? 0;
|
||||
public IEnumerable<uint> Keys =>
|
||||
_runtime()?.SpatialAnimationRuntimes.Keys ?? Array.Empty<uint>();
|
||||
_runtime.Current?.SpatialAnimationRuntimes.Keys ?? Array.Empty<uint>();
|
||||
|
||||
public TAnimation this[uint localEntityId]
|
||||
{
|
||||
set
|
||||
{
|
||||
LiveEntityRuntime runtime = _runtime()
|
||||
LiveEntityRuntime runtime = _runtime.Current
|
||||
?? throw new InvalidOperationException("Live entity runtime is not initialized.");
|
||||
if (!runtime.TryGetServerGuid(localEntityId, out uint guid))
|
||||
throw new InvalidOperationException($"No live entity owns local id 0x{localEntityId:X8}.");
|
||||
|
|
@ -33,7 +33,7 @@ public sealed class LiveEntityAnimationRuntimeView<TAnimation>
|
|||
|
||||
public bool TryGetValue(uint localEntityId, out TAnimation animation)
|
||||
{
|
||||
if (_runtime()?.TryGetAnimationRuntime(localEntityId, out var found) == true
|
||||
if (_runtime.Current?.TryGetAnimationRuntime(localEntityId, out var found) == true
|
||||
&& found is TAnimation typed)
|
||||
{
|
||||
animation = typed;
|
||||
|
|
@ -46,7 +46,7 @@ public sealed class LiveEntityAnimationRuntimeView<TAnimation>
|
|||
|
||||
public bool Remove(uint localEntityId)
|
||||
{
|
||||
LiveEntityRuntime? runtime = _runtime();
|
||||
LiveEntityRuntime? runtime = _runtime.Current;
|
||||
return runtime is not null
|
||||
&& runtime.TryGetServerGuid(localEntityId, out uint guid)
|
||||
&& runtime.ClearAnimationRuntime(guid);
|
||||
|
|
@ -57,7 +57,7 @@ public sealed class LiveEntityAnimationRuntimeView<TAnimation>
|
|||
public void CopySpatialIdsTo(HashSet<uint> destination)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(destination);
|
||||
LiveEntityRuntime? runtime = _runtime();
|
||||
LiveEntityRuntime? runtime = _runtime.Current;
|
||||
if (runtime is null)
|
||||
destination.Clear();
|
||||
else
|
||||
|
|
@ -66,7 +66,7 @@ public sealed class LiveEntityAnimationRuntimeView<TAnimation>
|
|||
|
||||
public Enumerator GetEnumerator()
|
||||
{
|
||||
LiveEntityRuntime? runtime = _runtime();
|
||||
LiveEntityRuntime? runtime = _runtime.Current;
|
||||
if (runtime is null)
|
||||
_iterationSnapshot.Clear();
|
||||
else
|
||||
|
|
@ -135,21 +135,21 @@ public sealed class LiveEntityAnimationRuntimeView<TAnimation>
|
|||
public sealed class LiveEntityRemoteMotionRuntimeView<TRemoteMotion>
|
||||
where TRemoteMotion : class, ILiveEntityRemoteMotionRuntime
|
||||
{
|
||||
private readonly Func<LiveEntityRuntime?> _runtime;
|
||||
private readonly ILiveEntityRuntimeSource _runtime;
|
||||
|
||||
public LiveEntityRemoteMotionRuntimeView(Func<LiveEntityRuntime?> runtime) =>
|
||||
internal LiveEntityRemoteMotionRuntimeView(ILiveEntityRuntimeSource runtime) =>
|
||||
_runtime = runtime ?? throw new ArgumentNullException(nameof(runtime));
|
||||
|
||||
public TRemoteMotion this[uint serverGuid]
|
||||
{
|
||||
set => (_runtime()
|
||||
set => (_runtime.Current
|
||||
?? throw new InvalidOperationException("Live entity runtime is not initialized."))
|
||||
.SetRemoteMotionRuntime(serverGuid, value);
|
||||
}
|
||||
|
||||
public bool TryGetValue(uint serverGuid, out TRemoteMotion motion)
|
||||
{
|
||||
if (_runtime()?.TryGetRemoteMotionRuntime(serverGuid, out var found) == true
|
||||
if (_runtime.Current?.TryGetRemoteMotionRuntime(serverGuid, out var found) == true
|
||||
&& found is TRemoteMotion typed)
|
||||
{
|
||||
motion = typed;
|
||||
|
|
@ -161,5 +161,5 @@ public sealed class LiveEntityRemoteMotionRuntimeView<TRemoteMotion>
|
|||
}
|
||||
|
||||
public bool Remove(uint serverGuid) =>
|
||||
_runtime()?.ClearRemoteMotionRuntime(serverGuid) == true;
|
||||
_runtime.Current?.ClearRemoteMotionRuntime(serverGuid) == true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
using AcDream.App.Update;
|
||||
using AcDream.App.Input;
|
||||
using AcDream.App.Net;
|
||||
using AcDream.App.Streaming;
|
||||
|
||||
namespace AcDream.App.World;
|
||||
|
||||
|
|
@ -14,36 +17,37 @@ namespace AcDream.App.World;
|
|||
/// from freezing an action due to complete this frame while ensuring the
|
||||
/// periodic AutonomousPosition check observes accepted inbound state.
|
||||
/// </remarks>
|
||||
public sealed class RetailLiveFrameCoordinator
|
||||
internal sealed class RetailLiveFrameCoordinator : IRetailLiveFramePhase
|
||||
{
|
||||
private readonly Action<float> _advanceObjectRuntime;
|
||||
private readonly Action _dispatchInboundNetwork;
|
||||
private readonly Action _runPostNetworkCommands;
|
||||
private readonly Action _reconcileSpatialPresentation;
|
||||
private readonly ILiveObjectFramePhase _objects;
|
||||
private readonly GpuWorldState _worldState;
|
||||
private readonly ILiveSessionFramePhase _session;
|
||||
private readonly IPostNetworkCommandFramePhase _localPlayer;
|
||||
private readonly ILiveSpatialReconcilePhase _spatialReconciler;
|
||||
|
||||
public RetailLiveFrameCoordinator(
|
||||
Action<float> advanceObjectRuntime,
|
||||
Action dispatchInboundNetwork,
|
||||
Action runPostNetworkCommands,
|
||||
Action reconcileSpatialPresentation)
|
||||
ILiveObjectFramePhase objects,
|
||||
GpuWorldState worldState,
|
||||
ILiveSessionFramePhase session,
|
||||
IPostNetworkCommandFramePhase localPlayer,
|
||||
ILiveSpatialReconcilePhase spatialReconciler)
|
||||
{
|
||||
_advanceObjectRuntime = advanceObjectRuntime
|
||||
?? throw new ArgumentNullException(nameof(advanceObjectRuntime));
|
||||
_dispatchInboundNetwork = dispatchInboundNetwork
|
||||
?? throw new ArgumentNullException(nameof(dispatchInboundNetwork));
|
||||
_runPostNetworkCommands = runPostNetworkCommands
|
||||
?? throw new ArgumentNullException(nameof(runPostNetworkCommands));
|
||||
_reconcileSpatialPresentation = reconcileSpatialPresentation
|
||||
?? throw new ArgumentNullException(nameof(reconcileSpatialPresentation));
|
||||
_objects = objects ?? throw new ArgumentNullException(nameof(objects));
|
||||
_worldState = worldState ?? throw new ArgumentNullException(nameof(worldState));
|
||||
_session = session ?? throw new ArgumentNullException(nameof(session));
|
||||
_localPlayer = localPlayer ?? throw new ArgumentNullException(nameof(localPlayer));
|
||||
_spatialReconciler = spatialReconciler
|
||||
?? throw new ArgumentNullException(nameof(spatialReconciler));
|
||||
}
|
||||
|
||||
public void Tick(float deltaSeconds)
|
||||
{
|
||||
float frameDelta = (float)NormalizeDeltaSeconds(deltaSeconds);
|
||||
_advanceObjectRuntime(frameDelta);
|
||||
_dispatchInboundNetwork();
|
||||
_runPostNetworkCommands();
|
||||
_reconcileSpatialPresentation();
|
||||
_objects.Tick(frameDelta);
|
||||
using (_worldState.BeginMutationBatch())
|
||||
_session.Tick();
|
||||
_localPlayer.RunPostNetworkCommandPhase();
|
||||
_spatialReconciler.Reconcile();
|
||||
}
|
||||
|
||||
public static double NormalizeDeltaSeconds(double deltaSeconds) =>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue