Reduce GameWindow.OnUpdate to one typed orchestration call and remove transitive window callbacks from teardown, liveness, teleport placement, live presentation, auto-entry, and entity packet routing. Preserve the frozen retail object/network order while making the production owner graph explicit and testable.
78 lines
2.5 KiB
C#
78 lines
2.5 KiB
C#
using AcDream.App.Input;
|
|
using AcDream.App.World;
|
|
using AcDream.Core.Vfx;
|
|
|
|
namespace AcDream.App.Update;
|
|
|
|
/// <summary>Bridges canonical live-entity teardown into the host frame.</summary>
|
|
internal sealed class LiveEntityTeardownFramePhase : IUpdateFrameTeardownPhase
|
|
{
|
|
private readonly LiveEntityRuntime _runtime;
|
|
|
|
public LiveEntityTeardownFramePhase(LiveEntityRuntime runtime) =>
|
|
_runtime = runtime ?? throw new ArgumentNullException(nameof(runtime));
|
|
|
|
public void RetryPendingTeardowns() => _runtime.RetryPendingTeardowns();
|
|
}
|
|
|
|
internal sealed class ConsoleUpdateFrameFailureSink : IUpdateFrameFailureSink
|
|
{
|
|
public void ReportTeardownFailure(AggregateException error) =>
|
|
Console.Error.WriteLine($"[live-entity-teardown] {error}");
|
|
}
|
|
|
|
/// <summary>Publishes the frame clock to the retail PhysicsScript owner.</summary>
|
|
internal sealed class PhysicsScriptClockPublisher : IUpdateFrameScriptClockPublisher
|
|
{
|
|
private readonly PhysicsScriptRunner _runner;
|
|
|
|
public PhysicsScriptClockPublisher(PhysicsScriptRunner runner) =>
|
|
_runner = runner ?? throw new ArgumentNullException(nameof(runner));
|
|
|
|
public void PublishTime(double scriptTime) => _runner.PublishTime(scriptTime);
|
|
}
|
|
|
|
internal interface IClientMonotonicTimeSource
|
|
{
|
|
double Now { get; }
|
|
}
|
|
|
|
internal sealed class StopwatchClientMonotonicTimeSource
|
|
: IClientMonotonicTimeSource
|
|
{
|
|
public double Now =>
|
|
System.Diagnostics.Stopwatch.GetTimestamp()
|
|
/ (double)System.Diagnostics.Stopwatch.Frequency;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Supplies the absolute client timer to liveness independently of the
|
|
/// normalized simulation delta.
|
|
/// </summary>
|
|
internal sealed class LiveEntityLivenessFramePhase
|
|
: ILiveEntityLivenessFramePhase
|
|
{
|
|
private readonly LiveEntityLivenessController _liveness;
|
|
private readonly IClientMonotonicTimeSource _clock;
|
|
|
|
public LiveEntityLivenessFramePhase(
|
|
LiveEntityLivenessController liveness,
|
|
IClientMonotonicTimeSource clock)
|
|
{
|
|
_liveness = liveness ?? throw new ArgumentNullException(nameof(liveness));
|
|
_clock = clock ?? throw new ArgumentNullException(nameof(clock));
|
|
}
|
|
|
|
public void Tick() => _liveness.Tick(_clock.Now);
|
|
}
|
|
|
|
internal sealed class PlayerModeAutoEntryFramePhase
|
|
: IPlayerModeAutoEntryFramePhase
|
|
{
|
|
private readonly PlayerModeAutoEntry _autoEntry;
|
|
|
|
public PlayerModeAutoEntryFramePhase(PlayerModeAutoEntry autoEntry) =>
|
|
_autoEntry = autoEntry ?? throw new ArgumentNullException(nameof(autoEntry));
|
|
|
|
public void TryEnter() => _autoEntry.TryEnter();
|
|
}
|