using System.Numerics; using AcDream.App.Physics; using AcDream.Core.Physics; using Xunit; namespace AcDream.App.Tests.Physics; public sealed class RemoteTeleportPlacementTests { [Fact] public void Apply_HardSnapsFullFrameAndPhysicsClock() { var body = new PhysicsBody { Orientation = Quaternion.Identity, LastUpdateTime = 2.0, }; body.SnapToCell( 0x01010001u, new Vector3(3f, 4f, 5f), new Vector3(3f, 4f, 5f)); var remote = new AcDream.App.Rendering.GameWindow.RemoteMotion(body); Quaternion orientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, 0.75f); RemoteTeleportPlacement.Apply( remote, body, new ResolveResult( new Vector3(210f, 220f, 12f), 0x02020123u, IsOnGround: false), new Vector3(18f, 28f, 12f), orientation, 17.5, previousContact: body.InContact, previousOnWalkable: body.OnWalkable); Assert.Equal(new Vector3(210f, 220f, 12f), body.Position); Assert.Equal(0x02020123u, body.CellPosition.ObjCellId); Assert.Equal(new Vector3(18f, 28f, 12f), body.CellPosition.Frame.Origin); Assert.Equal(orientation, body.Orientation); Assert.Equal(17.5, body.LastUpdateTime); Assert.True(body.InWorld); } [Fact] public void Apply_InstallsPlacementDerivedContactAndSynchronizesAirborneState() { var velocity = new Vector3(1f, 2f, 3f); var body = new PhysicsBody { Velocity = velocity, TransientState = TransientStateFlags.Active, State = PhysicsStateFlags.Gravity | PhysicsStateFlags.ReportCollisions, }; var contactPlane = new Plane(Vector3.UnitZ, 0f); var remote = new AcDream.App.Rendering.GameWindow.RemoteMotion(body) { Airborne = true, }; RemoteTeleportPlacement.Apply( remote, body, new ResolveResult( new Vector3(200f, 200f, 50f), 0x02020001u, IsOnGround: true, InContact: true, OnWalkable: true, ContactPlane: contactPlane, ContactPlaneCellId: 0x02020001u), new Vector3(8f, 8f, 50f), Quaternion.Identity, 9.0, previousContact: false, previousOnWalkable: false); Assert.Equal(Vector3.Zero, body.Velocity); Assert.True(body.InContact); Assert.True(body.OnWalkable); Assert.True(body.ContactPlaneValid); Assert.Equal(contactPlane, body.ContactPlane); Assert.False(remote.Airborne); } [Fact] public void Apply_PendingHydrationUsesPreservedSourceFlagsBeforeCollisionResponse() { var originalVelocity = new Vector3(-3f, 0f, 0f); var body = new PhysicsBody { Velocity = originalVelocity, State = PhysicsStateFlags.Gravity | PhysicsStateFlags.ReportCollisions, }; // ParkPending deliberately clears these flags while the destination // 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) { Airborne = true, }; RemoteTeleportPlacement.Apply( remote, body, new ResolveResult( new Vector3(200f, 200f, 50f), 0x02020001u, IsOnGround: true, CollisionNormalValid: true, CollisionNormal: Vector3.UnitX, InContact: true, OnWalkable: true, ContactPlane: new Plane(Vector3.UnitZ, 0f), ContactPlaneCellId: 0x02020001u), new Vector3(8f, 8f, 50f), Quaternion.Identity, 9.0, previousContact: true, previousOnWalkable: true); // Staying on walkable ground suppresses reflection. If the parked // false/false flags were used, the -X velocity would reflect to +X. Assert.Equal(originalVelocity, body.Velocity); Assert.True(body.OnWalkable); Assert.False(remote.Airborne); } [Fact] public void Apply_PendingGroundToSteepContact_RestoresSourceWalkabilityForFirstAcceleration() { var body = new PhysicsBody { Omega = new Vector3(0f, 0f, 3f), State = PhysicsStateFlags.Gravity | PhysicsStateFlags.ReportCollisions, }; // The unloaded-destination parking frame cleared both bits. Retail // restores the captured source OnWalkable bit through the first // 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); RemoteTeleportPlacement.Apply( remote, body, new ResolveResult( new Vector3(200f, 200f, 50f), 0x02020001u, IsOnGround: false, InContact: true, OnWalkable: false, ContactPlane: new Plane(Vector3.Normalize(new Vector3(1f, 0f, 0.2f)), 0f), ContactPlaneCellId: 0x02020001u), new Vector3(8f, 8f, 50f), Quaternion.Identity, 9.0, previousContact: true, previousOnWalkable: true); Assert.Equal(Vector3.Zero, body.Omega); Assert.True(body.InContact); Assert.False(body.OnWalkable); Assert.True(remote.Airborne); } [Fact] public void Apply_RejectsMalformedPlacementWithoutMutatingBody() { var original = new Vector3(7f, 8f, 9f); var body = new PhysicsBody { Position = original }; var remote = new AcDream.App.Rendering.GameWindow.RemoteMotion(body); Assert.Throws(() => RemoteTeleportPlacement.Apply( remote, body, new ResolveResult( new Vector3(float.NaN, 0f, 0f), 0, IsOnGround: false, Ok: false), Vector3.Zero, Quaternion.Identity, double.NaN, previousContact: false, previousOnWalkable: false)); Assert.Equal(original, body.Position); Assert.Equal(0u, body.CellPosition.ObjCellId); } }