refactor(runtime): extract the live object frame

This commit is contained in:
Erik 2026-07-22 00:42:26 +02:00
parent 99a3e819c4
commit 4e4aac2c5a
27 changed files with 1217 additions and 371 deletions

View file

@ -1,4 +1,5 @@
using AcDream.App.Physics;
using AcDream.App.Rendering.Vfx;
using AcDream.App.World;
using AcDream.Core.Physics;
using AcDream.Core.World;
@ -12,30 +13,28 @@ namespace AcDream.App.Rendering;
/// </summary>
internal sealed class StaticLiveRootCommitter
{
private readonly Func<LiveEntityRuntime?> _runtime;
private readonly ILiveEntityRuntimeSource _runtime;
private readonly ShadowObjectRegistry _shadows;
private readonly Func<(int X, int Y)> _liveCenter;
private readonly Action<WorldEntity> _updateEffectRoot;
private readonly LiveWorldOriginState _origin;
private readonly EntityEffectPoseRegistry _effectPoses;
public StaticLiveRootCommitter(
Func<LiveEntityRuntime?> runtime,
ILiveEntityRuntimeSource runtime,
ShadowObjectRegistry shadows,
Func<(int X, int Y)> liveCenter,
Action<WorldEntity> updateEffectRoot)
LiveWorldOriginState origin,
EntityEffectPoseRegistry effectPoses)
{
_runtime = runtime ?? throw new ArgumentNullException(nameof(runtime));
_shadows = shadows ?? throw new ArgumentNullException(nameof(shadows));
_liveCenter = liveCenter
?? throw new ArgumentNullException(nameof(liveCenter));
_updateEffectRoot = updateEffectRoot
?? throw new ArgumentNullException(nameof(updateEffectRoot));
_origin = origin ?? throw new ArgumentNullException(nameof(origin));
_effectPoses = effectPoses ?? throw new ArgumentNullException(nameof(effectPoses));
}
public bool Commit(WorldEntity entity, PhysicsBody body)
{
ArgumentNullException.ThrowIfNull(entity);
ArgumentNullException.ThrowIfNull(body);
LiveEntityRuntime? runtime = _runtime();
LiveEntityRuntime? runtime = _runtime.Current;
if (runtime is null
|| !runtime.TryGetRecord(entity.ServerGuid, out LiveEntityRecord record)
|| !ReferenceEquals(record.WorldEntity, entity)
@ -46,15 +45,14 @@ internal sealed class StaticLiveRootCommitter
// The retained pose owner follows the CPhysicsObj root even while its
// mesh is hidden. Hidden is presentation state, not logical teardown.
_updateEffectRoot(entity);
_effectPoses.UpdateRoot(entity);
// EffectPoseChanged observers run synchronously and may delete this
// incarnation (or replace the GUID) before returning. Do not let the
// stale root restore collision shadows for an owner which no longer
// exists. This is the same callback-boundary lifetime rule used by the
// live schedulers and movement controllers.
if (!ReferenceEquals(_runtime(), runtime)
|| !runtime.TryGetRecord(entity.ServerGuid, out LiveEntityRecord current)
if (!runtime.TryGetRecord(entity.ServerGuid, out LiveEntityRecord current)
|| !ReferenceEquals(current, record)
|| !ReferenceEquals(current.WorldEntity, entity)
|| !ReferenceEquals(current.PhysicsBody, body))
@ -76,15 +74,14 @@ internal sealed class StaticLiveRootCommitter
uint cellId = body.CellPosition.ObjCellId != 0
? body.CellPosition.ObjCellId
: record.FullCellId;
(int centerX, int centerY) = _liveCenter();
ShadowPositionSynchronizer.Sync(
_shadows,
entity.Id,
body.Position,
body.Orientation,
cellId,
centerX,
centerY);
_origin.CenterX,
_origin.CenterY);
return true;
}
}