refactor(runtime): define the update-frame contract

This commit is contained in:
Erik 2026-07-22 00:15:27 +02:00
parent a36a7015c4
commit 99a3e819c4
8 changed files with 646 additions and 26 deletions

View file

@ -158,6 +158,7 @@ public sealed class GameWindow : IDisposable, ILiveAnimationPresentationContext
private readonly AcDream.App.Input.LocalPlayerOutboundController _localPlayerOutbound;
private readonly AcDream.App.Input.RetailLocalPlayerFrameController _localPlayerFrame;
private readonly AcDream.App.World.RetailLiveFrameCoordinator _liveFrameCoordinator;
private readonly AcDream.App.Update.UpdateFrameClock _updateFrameClock = new();
private AcDream.App.Physics.RemoteTeleportController? _remoteTeleportController;
// Step 7 projectile presentation. The controller owns no identity map;
// each runtime component is stored on the canonical LiveEntityRecord.
@ -295,7 +296,6 @@ public sealed class GameWindow : IDisposable, ILiveAnimationPresentationContext
private AcDream.Core.Vfx.PhysicsScriptRunner? _scriptRunner;
private AcDream.Content.Vfx.RetailPhysicsScriptLoader? _physicsScriptLoader;
private AcDream.App.Rendering.Vfx.EntityEffectController? _entityEffects;
private double _physicsScriptGameTime;
private AcDream.App.Rendering.ParticleRenderer? _particleRenderer;
private readonly AcDream.App.Rendering.RetailAlphaQueue _retailAlphaQueue = new();
// Retail GameSky copies SkyObject.PesObjectId into CelestialPosition but
@ -2569,7 +2569,7 @@ public sealed class GameWindow : IDisposable, ILiveAnimationPresentationContext
_animationPresenter,
_staticAnimationScheduler!,
_liveWorldOrigin,
() => _physicsScriptGameTime);
_updateFrameClock);
var originCoordinator =
new AcDream.App.World.LiveEntityWorldOriginCoordinator(
_liveWorldOrigin,
@ -2642,7 +2642,7 @@ public sealed class GameWindow : IDisposable, ILiveAnimationPresentationContext
_localPlayerOutbound,
() => _playerHost,
() => _playerServerGuid,
() => _physicsScriptGameTime,
_updateFrameClock,
() => LiveSession,
PublishLocalPhysicsTimestamps,
AimTeleportDestination,
@ -3800,16 +3800,16 @@ public sealed class GameWindow : IDisposable, ILiveAnimationPresentationContext
Console.Error.WriteLine($"[live-entity-teardown] {error}");
}
double frameSeconds =
AcDream.App.World.RetailLiveFrameCoordinator.NormalizeDeltaSeconds(dt);
float frameDelta = (float)frameSeconds;
AcDream.App.Update.UpdateFrameTiming frameTiming = _updateFrameClock.Advance(
new AcDream.App.Update.UpdateFrameInput(dt));
double frameSeconds = frameTiming.SimulationDeltaSeconds;
float frameDelta = frameTiming.SimulationDeltaSecondsSingle;
// Retail ScriptManager::AddScriptInternal (0x0051B310) stamps
// Timer::cur_time at the packet/default-script call site. Publish this
// update frame's clock before streaming and network dispatch, then
// reuse the same timestamp for animation hooks and the later drain.
_physicsScriptGameTime += frameSeconds;
_scriptRunner?.PublishTime(_physicsScriptGameTime);
_scriptRunner?.PublishTime(frameTiming.ScriptTime);
// Phase A.1: advance the streaming controller FIRST so the initial
// landblocks are loaded into GpuWorldState before live-session
@ -5739,7 +5739,6 @@ public sealed class GameWindow : IDisposable, ILiveAnimationPresentationContext
// Use directly from Silk's key callback inverted that order and left
// the client walking to a corpse whose server callback was cancelled.
_selectionInteractions?.DrainOutbound();
_scriptRunner?.PublishTime(_physicsScriptGameTime);
System.Numerics.Vector3? playerPosition =
_entitiesByServerGuid.TryGetValue(
_playerServerGuid,
@ -5792,7 +5791,7 @@ public sealed class GameWindow : IDisposable, ILiveAnimationPresentationContext
// ParticleManager before ScriptManager. A particle created by a PES
// hook therefore begins simulation on the following object frame.
_particleSystem?.Tick(dt);
_scriptRunner?.Tick(_physicsScriptGameTime);
_scriptRunner?.Tick(_updateFrameClock.CurrentScriptTime);
}
/// <summary>