refactor(physics): extract remote motion runtime

This commit is contained in:
Erik 2026-07-21 13:17:58 +02:00
parent d68c83d1a5
commit 5882b308c1
12 changed files with 368 additions and 361 deletions

View file

@ -41,7 +41,7 @@ public sealed class LiveEntityOrdinaryPhysicsUpdaterTests
ParentCellId = SourceCell,
})!;
var remote = new AcDream.App.Rendering.GameWindow.RemoteMotion
var remote = new AcDream.App.Physics.RemoteMotion
{
CellId = SourceCell,
};
@ -108,7 +108,7 @@ public sealed class LiveEntityOrdinaryPhysicsUpdaterTests
MeshRefs = Array.Empty<MeshRef>(),
ParentCellId = SourceCell,
})!;
var remote = new AcDream.App.Rendering.GameWindow.RemoteMotion
var remote = new AcDream.App.Physics.RemoteMotion
{
CellId = SourceCell,
};

View file

@ -104,7 +104,7 @@ public sealed class ProjectileControllerTests
LiveEntityRecord record = fixture.Spawn(instance: 1);
WorldEntity entity = record.WorldEntity!;
Assert.Null(record.AnimationRuntime);
var remote = new GameWindow.RemoteMotion();
var remote = new AcDream.App.Physics.RemoteMotion();
RemotePhysicsBodyInitializer.Initialize(remote.Body, record);
remote.Body.Position = entity.Position;
remote.Body.Orientation = entity.Rotation;
@ -683,7 +683,7 @@ public sealed class ProjectileControllerTests
LiveEntityRecord record = fixture.Spawn(instance: 1);
Assert.True(fixture.Controller.TryBind(record, ProjectileSetup(), 1.0));
PhysicsBody body = record.PhysicsBody!;
fixture.Live.SetRemoteMotionRuntime(Guid, new GameWindow.RemoteMotion(body));
fixture.Live.SetRemoteMotionRuntime(Guid, new AcDream.App.Physics.RemoteMotion(body));
record.FinalPhysicsState = PhysicsStateFlags.ReportCollisions;
Assert.True(fixture.Controller.ApplyAuthoritativeState(
record, record.FinalPhysicsState, 2.0, 1, 1));
@ -707,7 +707,7 @@ public sealed class ProjectileControllerTests
Assert.True(fixture.Controller.TryBind(record, ProjectileSetup(), 1.0));
PhysicsBody body = record.PhysicsBody!;
Vector3 position = body.Position;
fixture.Live.SetRemoteMotionRuntime(Guid, new GameWindow.RemoteMotion(body));
fixture.Live.SetRemoteMotionRuntime(Guid, new AcDream.App.Physics.RemoteMotion(body));
record.FinalPhysicsState = PhysicsStateFlags.ReportCollisions;
Assert.True(fixture.Controller.ApplyAuthoritativeState(
@ -946,7 +946,7 @@ public sealed class ProjectileControllerTests
var fixture = new Fixture();
LiveEntityRecord record = fixture.Spawn(instance: 1);
record.FinalPhysicsState = PhysicsStateFlags.ReportCollisions;
var remote = new GameWindow.RemoteMotion();
var remote = new AcDream.App.Physics.RemoteMotion();
RemotePhysicsBodyInitializer.Initialize(remote.Body, record);
fixture.Live.SetRemoteMotionRuntime(Guid, remote);
@ -998,7 +998,7 @@ public sealed class ProjectileControllerTests
var fixture = new Fixture();
LiveEntityRecord record = fixture.Spawn(instance: 1);
record.FinalPhysicsState = PhysicsStateFlags.ReportCollisions;
var remote = new GameWindow.RemoteMotion();
var remote = new AcDream.App.Physics.RemoteMotion();
RemotePhysicsBodyInitializer.Initialize(remote.Body, record);
fixture.Live.SetRemoteMotionRuntime(Guid, remote);
@ -1070,7 +1070,7 @@ public sealed class ProjectileControllerTests
seedCellId: startCell,
isStatic: false);
record.FinalPhysicsState = PhysicsStateFlags.ReportCollisions;
var remote = new GameWindow.RemoteMotion();
var remote = new AcDream.App.Physics.RemoteMotion();
RemotePhysicsBodyInitializer.Initialize(remote.Body, record);
Assert.Equal(new Vector3(40f, 0f, 0f), remote.Body.Velocity);
Assert.Equal(new Vector3(0f, 0f, 2f), remote.Body.Omega);
@ -1136,7 +1136,7 @@ public sealed class ProjectileControllerTests
velocity: new Vector3(float.NaN, 0f, 0f));
WorldEntity entity = record.WorldEntity!;
record.FinalPhysicsState = PhysicsStateFlags.ReportCollisions;
var remote = new GameWindow.RemoteMotion();
var remote = new AcDream.App.Physics.RemoteMotion();
RemotePhysicsBodyInitializer.Initialize(remote.Body, record);
remote.Body.Position = entity.Position;
remote.Body.Orientation = entity.Rotation;
@ -1162,7 +1162,7 @@ public sealed class ProjectileControllerTests
LiveEntityRecord record = fixture.Spawn(instance: 1);
WorldEntity entity = record.WorldEntity!;
record.FinalPhysicsState = PhysicsStateFlags.ReportCollisions;
var remote = new GameWindow.RemoteMotion();
var remote = new AcDream.App.Physics.RemoteMotion();
RemotePhysicsBodyInitializer.Initialize(remote.Body, record);
remote.Body.Position = entity.Position;
remote.Body.Orientation = entity.Rotation;
@ -1186,7 +1186,7 @@ public sealed class ProjectileControllerTests
LiveEntityRecord record = fixture.Spawn(instance: 1);
Assert.True(fixture.Controller.TryBind(record, ProjectileSetup(), 1.0));
PhysicsBody body = record.PhysicsBody!;
var remote = new GameWindow.RemoteMotion(body);
var remote = new AcDream.App.Physics.RemoteMotion(body);
fixture.Live.SetRemoteMotionRuntime(Guid, remote);
fixture.Live.RebucketLiveEntity(Guid, CellB);
@ -1198,7 +1198,7 @@ public sealed class ProjectileControllerTests
Assert.Same(body, record.RemoteMotionRuntime!.Body);
Assert.Same(body, record.ProjectileRuntime!.Body);
var replacement = new GameWindow.RemoteMotion(body);
var replacement = new AcDream.App.Physics.RemoteMotion(body);
fixture.Live.SetRemoteMotionRuntime(Guid, replacement);
remote.CellId = CellB;
Assert.Equal(CellA, record.FullCellId);

View file

@ -68,7 +68,7 @@ public sealed class RemotePhysicsUpdaterTests
MeshRefs = Array.Empty<MeshRef>(),
ParentCellId = cellId,
};
var motion = new GameWindow.RemoteMotion
var motion = new AcDream.App.Physics.RemoteMotion
{
LastShadowSyncPos = Vector3.Zero,
LastShadowSyncOrientation = Quaternion.Identity,
@ -151,7 +151,7 @@ public sealed class RemotePhysicsUpdaterTests
PartTemplate = Array.Empty<LiveAnimationPartTemplate>(),
PartAvailability = Array.Empty<bool>(),
};
var motion = new GameWindow.RemoteMotion();
var motion = new AcDream.App.Physics.RemoteMotion();
motion.Body.Position = entity.Position;
motion.Body.Orientation = entity.Rotation;
motion.Body.TransientState = TransientStateFlags.Contact
@ -217,7 +217,7 @@ public sealed class RemotePhysicsUpdaterTests
PartTemplate = Array.Empty<LiveAnimationPartTemplate>(),
PartAvailability = Array.Empty<bool>(),
};
var motion = new GameWindow.RemoteMotion
var motion = new AcDream.App.Physics.RemoteMotion
{
Airborne = true,
};
@ -272,7 +272,7 @@ public sealed class RemotePhysicsUpdaterTests
PartTemplate = Array.Empty<LiveAnimationPartTemplate>(),
PartAvailability = Array.Empty<bool>(),
};
var motion = new GameWindow.RemoteMotion();
var motion = new AcDream.App.Physics.RemoteMotion();
motion.Body.Position = entity.Position;
motion.Body.Orientation = initial;
motion.Interp.Enqueue(
@ -308,7 +308,7 @@ public sealed class RemotePhysicsUpdaterTests
[Fact]
public void TickHidden_AppliesPositionManagerOffsetWithoutAdvancingPhysics()
{
var motion = new GameWindow.RemoteMotion();
var motion = new AcDream.App.Physics.RemoteMotion();
motion.Body.Position = Vector3.Zero;
motion.Body.Orientation = Quaternion.Identity;
motion.Body.Velocity = new Vector3(4f, 0f, 5f);
@ -354,7 +354,7 @@ public sealed class RemotePhysicsUpdaterTests
new PhysicsEngine(),
(_, _) => (0.48f, 1.835f),
(_, _, _, _) => { });
var motion = new GameWindow.RemoteMotion();
var motion = new AcDream.App.Physics.RemoteMotion();
motion.Body.Orientation = Quaternion.Identity;
var entity = new WorldEntity
{
@ -384,7 +384,7 @@ public sealed class RemotePhysicsUpdaterTests
new PhysicsEngine(),
(_, _) => (0.48f, 1.835f),
(_, _, _, _) => { });
var motion = new GameWindow.RemoteMotion();
var motion = new AcDream.App.Physics.RemoteMotion();
motion.Body.Orientation = Quaternion.Identity;
var entity = new WorldEntity
{
@ -424,7 +424,7 @@ public sealed class RemotePhysicsUpdaterTests
engine,
(_, _) => (0.48f, 1.835f),
(_, _, _, _) => { });
var motion = new GameWindow.RemoteMotion();
var motion = new AcDream.App.Physics.RemoteMotion();
motion.Body.Position = new Vector3(191f, 10f, 50f);
motion.Body.Orientation = Quaternion.Identity;
motion.Body.TransientState = TransientStateFlags.Contact
@ -471,7 +471,7 @@ public sealed class RemotePhysicsUpdaterTests
engine,
(_, _) => (0.48f, 1.835f),
(_, _, _, _) => { });
var motion = new GameWindow.RemoteMotion
var motion = new AcDream.App.Physics.RemoteMotion
{
Airborne = true,
};
@ -591,7 +591,7 @@ public sealed class RemotePhysicsUpdaterTests
using var fixture = new BoundaryRemoteFixture();
LiveEntityRecord oldRecord = fixture.Record;
WorldEntity oldEntity = fixture.Entity;
GameWindow.RemoteMotion oldRemote = fixture.Remote;
AcDream.App.Physics.RemoteMotion oldRemote = fixture.Remote;
ulong oldAuthority = oldRecord.PositionAuthorityVersion;
int publications = 0;
@ -628,9 +628,9 @@ public sealed class RemotePhysicsUpdaterTests
using var fixture = new BoundaryRemoteFixture();
LiveEntityRecord oldRecord = fixture.Record;
WorldEntity oldEntity = fixture.Entity;
GameWindow.RemoteMotion oldRemote = fixture.Remote;
AcDream.App.Physics.RemoteMotion oldRemote = fixture.Remote;
WorldEntity? replacementEntity = null;
GameWindow.RemoteMotion? replacementRemote = null;
AcDream.App.Physics.RemoteMotion? replacementRemote = null;
ulong clockEpoch = oldRecord.ObjectClockEpoch;
fixture.Live.ProjectionVisibilityChanged += (record, visible) =>
@ -813,7 +813,7 @@ public sealed class RemotePhysicsUpdaterTests
MeshRefs = Array.Empty<MeshRef>(),
ParentCellId = cellId,
})!;
var remote = new GameWindow.RemoteMotion();
var remote = new AcDream.App.Physics.RemoteMotion();
remote.Body.Position = entity.Position;
remote.Body.Orientation = entity.Rotation;
remote.CellId = cellId;
@ -872,7 +872,7 @@ public sealed class RemotePhysicsUpdaterTests
public RemotePhysicsUpdater Updater { get; }
public LiveEntityRecord Record { get; }
public WorldEntity Entity { get; }
public GameWindow.RemoteMotion Remote { get; }
public AcDream.App.Physics.RemoteMotion Remote { get; }
public void HydrateDestination() =>
Spatial.AddLandblock(new LoadedLandblock(
@ -881,7 +881,7 @@ public sealed class RemotePhysicsUpdaterTests
Array.Empty<WorldEntity>()));
public (LiveEntityRecord Record, WorldEntity Entity,
GameWindow.RemoteMotion Remote) ReplaceAtSource()
AcDream.App.Physics.RemoteMotion Remote) ReplaceAtSource()
{
Assert.True(Live.UnregisterLiveEntity(
new DeleteObject.Parsed(Guid, InstanceSequence: 1),
@ -902,7 +902,7 @@ public sealed class RemotePhysicsUpdaterTests
}
private (LiveEntityRecord Record, WorldEntity Entity,
GameWindow.RemoteMotion Remote) SpawnAndBind(
AcDream.App.Physics.RemoteMotion Remote) SpawnAndBind(
ushort instanceSequence,
Vector3 position,
bool enqueueDestination)
@ -925,7 +925,7 @@ public sealed class RemotePhysicsUpdaterTests
MeshRefs = Array.Empty<MeshRef>(),
ParentCellId = SourceCell,
}));
var remote = new GameWindow.RemoteMotion();
var remote = new AcDream.App.Physics.RemoteMotion();
remote.Body.Position = position;
remote.Body.Orientation = Quaternion.Identity;
remote.CellId = SourceCell;
@ -945,7 +945,7 @@ public sealed class RemotePhysicsUpdaterTests
private void RegisterShadow(
WorldEntity entity,
GameWindow.RemoteMotion remote)
AcDream.App.Physics.RemoteMotion remote)
{
Engine.ShadowObjects.Register(
entity.Id,

View file

@ -101,7 +101,7 @@ public sealed class RemoteTeleportControllerTests
Rotation = Quaternion.Identity,
MeshRefs = Array.Empty<MeshRef>(),
})!;
var remote = new GameWindow.RemoteMotion();
var remote = new AcDream.App.Physics.RemoteMotion();
remote.Body.SnapToCell(
sourceCell,
entity.Position,
@ -242,7 +242,7 @@ public sealed class RemoteTeleportControllerTests
Rotation = Quaternion.Identity,
MeshRefs = Array.Empty<MeshRef>(),
})!;
var remote = new GameWindow.RemoteMotion();
var remote = new AcDream.App.Physics.RemoteMotion();
remote.Body.SnapToCell(sourceCell, entity.Position, entity.Position);
live.SetRemoteMotionRuntime(guid, remote);
var engine = new PhysicsEngine { DataCache = new PhysicsDataCache() };
@ -333,7 +333,7 @@ public sealed class RemoteTeleportControllerTests
Rotation = Quaternion.Identity,
MeshRefs = Array.Empty<MeshRef>(),
})!;
var remote = new GameWindow.RemoteMotion();
var remote = new AcDream.App.Physics.RemoteMotion();
remote.Body.SnapToCell(sourceCell, sourcePosition, sourcePosition);
remote.Body.TransientState = TransientStateFlags.Contact
| TransientStateFlags.OnWalkable;
@ -774,13 +774,13 @@ public sealed class RemoteTeleportControllerTests
Assert.Throws<InvalidOperationException>(() =>
fixture.Live.SetRemoteMotionRuntime(
RollbackFixture.Guid,
new GameWindow.RemoteMotion()));
new AcDream.App.Physics.RemoteMotion()));
Assert.Throws<InvalidOperationException>(() =>
fixture.Live.SetRemoteMotionRuntime(
RollbackFixture.Guid,
new BodyOnlyRemote(fixture.Remote.Body)));
var replacement = new GameWindow.RemoteMotion(fixture.Remote.Body);
var replacement = new AcDream.App.Physics.RemoteMotion(fixture.Remote.Body);
fixture.Live.SetRemoteMotionRuntime(RollbackFixture.Guid, replacement);
fixture.Spatial.AddLandblock(EmptyLandblock(RollbackFixture.DestinationLandblock));
@ -811,7 +811,7 @@ public sealed class RemoteTeleportControllerTests
Assert.Throws<InvalidOperationException>(() =>
fixture.Live.SetRemoteMotionRuntime(
RollbackFixture.Guid,
new GameWindow.RemoteMotion()));
new AcDream.App.Physics.RemoteMotion()));
Assert.Throws<InvalidOperationException>(() =>
fixture.Live.SetRemoteMotionRuntime(
RollbackFixture.Guid,
@ -1114,7 +1114,7 @@ public sealed class RemoteTeleportControllerTests
Rotation = Quaternion.Identity,
MeshRefs = Array.Empty<MeshRef>(),
})!;
var remote = new GameWindow.RemoteMotion();
var remote = new AcDream.App.Physics.RemoteMotion();
remote.Body.SnapToCell(sourceCell, entity.Position, entity.Position);
live.SetRemoteMotionRuntime(guid, remote);
controller = new RemoteTeleportController(
@ -1191,7 +1191,7 @@ public sealed class RemoteTeleportControllerTests
Rotation = Quaternion.Identity,
MeshRefs = Array.Empty<MeshRef>(),
})!;
var remote = new GameWindow.RemoteMotion();
var remote = new AcDream.App.Physics.RemoteMotion();
remote.Body.SnapToCell(sourceCell, entity.Position, entity.Position);
live.SetRemoteMotionRuntime(guid, remote);
return new LoadedRemoteFixture(
@ -1236,7 +1236,7 @@ public sealed class RemoteTeleportControllerTests
private readonly record struct LoadedRemoteFixture(
LiveEntityRuntime Live,
WorldEntity Entity,
GameWindow.RemoteMotion Remote,
AcDream.App.Physics.RemoteMotion Remote,
PhysicsEngine Engine);
private static void AddDestination(PhysicsEngine engine) =>
@ -1395,7 +1395,7 @@ public sealed class RemoteTeleportControllerTests
Rotation = Quaternion.Identity,
MeshRefs = Array.Empty<MeshRef>(),
})!;
Remote = new GameWindow.RemoteMotion();
Remote = new AcDream.App.Physics.RemoteMotion();
Remote.Body.SnapToCell(
celllessSource ? 0u : SourceCell,
SourcePosition,
@ -1476,7 +1476,7 @@ public sealed class RemoteTeleportControllerTests
internal GpuWorldState Spatial { get; } = new();
internal LiveEntityRuntime Live { get; }
internal WorldEntity Entity { get; }
internal GameWindow.RemoteMotion Remote { get; }
internal AcDream.App.Physics.RemoteMotion Remote { get; }
internal PhysicsEngine Engine { get; } = new() { DataCache = new PhysicsDataCache() };
internal RemoteTeleportController Controller { get; }
internal LiveEntityPresentationController Presentation { get; }

View file

@ -19,7 +19,7 @@ public sealed class RemoteTeleportPlacementTests
0x01010001u,
new Vector3(3f, 4f, 5f),
new Vector3(3f, 4f, 5f));
var remote = new AcDream.App.Rendering.GameWindow.RemoteMotion(body);
var remote = new AcDream.App.Physics.RemoteMotion(body);
Quaternion orientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, 0.75f);
RemoteTeleportPlacement.Apply(
@ -54,7 +54,7 @@ public sealed class RemoteTeleportPlacementTests
State = PhysicsStateFlags.Gravity | PhysicsStateFlags.ReportCollisions,
};
var contactPlane = new Plane(Vector3.UnitZ, 0f);
var remote = new AcDream.App.Rendering.GameWindow.RemoteMotion(body)
var remote = new AcDream.App.Physics.RemoteMotion(body)
{
Airborne = true,
};
@ -97,7 +97,7 @@ public sealed class RemoteTeleportPlacementTests
// landblock is absent. SetPositionInternal must still receive the
// grounded source edge captured before parking.
body.TransientState &= ~(TransientStateFlags.Contact | TransientStateFlags.OnWalkable);
var remote = new AcDream.App.Rendering.GameWindow.RemoteMotion(body)
var remote = new AcDream.App.Physics.RemoteMotion(body)
{
Airborne = true,
};
@ -141,7 +141,7 @@ public sealed class RemoteTeleportPlacementTests
// calc_acceleration, which clears grounded angular drift, before
// set_on_walkable installs the steep destination's false value.
body.TransientState &= ~(TransientStateFlags.Contact | TransientStateFlags.OnWalkable);
var remote = new AcDream.App.Rendering.GameWindow.RemoteMotion(body);
var remote = new AcDream.App.Physics.RemoteMotion(body);
RemoteTeleportPlacement.Apply(
remote,
@ -171,7 +171,7 @@ public sealed class RemoteTeleportPlacementTests
{
var original = new Vector3(7f, 8f, 9f);
var body = new PhysicsBody { Position = original };
var remote = new AcDream.App.Rendering.GameWindow.RemoteMotion(body);
var remote = new AcDream.App.Physics.RemoteMotion(body);
Assert.Throws<ArgumentOutOfRangeException>(() =>
RemoteTeleportPlacement.Apply(