using System.Numerics;
using AcDream.Core.Net.Messages;
using AcDream.Core.Physics;
using AcDream.Runtime.Entities;
using AcDream.Runtime.Physics;
using AcDream.Runtime.Session;
namespace AcDream.Runtime.Tests.Physics;
///
/// C4 route 4b-2: the arm-selection half of the remote far snap. Every route
/// here is produced by the REAL classifier from a real request, including the
/// negative cases the classifier genuinely emits from other entry points (a
/// local-player SetPositionSimple, a remote top-level Create) and which
/// the far arm must decline. Exactly ONE route is hand-shaped — the
/// flags/disposition mismatch in
/// ,
/// which no classifier path produces but a caller could express.
///
///
/// Each test was verified to discriminate by temporarily reverting the
/// corresponding guard in and
/// confirming the matching test failed, then restoring it.
///
///
public sealed class RuntimeRemoteFarSnapPositionTests
{
private const uint Cell = 0x0101FFFFu;
[Fact]
public void OwnsFarSnap_TrueForTheRemoteFarBranch()
{
RuntimeAuthoritativePositionRoute far =
Classify(hasContact: true, playerDistance: 200f);
// Retail: player_distance >= 96f -> StopInterpolating @0x005163CB +
// SetPositionSimple @0x005163D9, whose arg3 != 0 builds flags 0x1012
// (Teleport|Slide|SendPositionEvent) @0x005162C4.
Assert.Equal(
RuntimeAuthoritativePositionDisposition.SetPositionSimple,
far.Disposition);
Assert.True(far.StopInterpolating);
Assert.True(RuntimeRemoteFarSnapPosition.OwnsFarSnap(far));
}
[Fact]
public void OwnsFarSnap_TrueExactlyAtTheRetailBoundary()
{
// Retail compares player_distance against 96f and takes the
// InterpolateTo branch only when strictly LESS (@0x00516393-@0x0051639E,
// the `x87_r7 < temp1` test). 96.0 itself is the far branch.
Assert.False(RuntimeRemoteFarSnapPosition.OwnsFarSnap(
Classify(hasContact: true, playerDistance: 95.99f)));
Assert.True(RuntimeRemoteFarSnapPosition.OwnsFarSnap(
Classify(hasContact: true, playerDistance: 96f)));
}
[Fact]
public void OwnsFarSnap_FalseForEveryOtherRemoteClassification()
{
// Near InterpolateTo @0x005163AF.
Assert.False(RuntimeRemoteFarSnapPosition.OwnsFarSnap(
Classify(hasContact: true, playerDistance: 10f)));
// Airborne no-op @0x0051636D.
Assert.False(RuntimeRemoteFarSnapPosition.OwnsFarSnap(
Classify(hasContact: false, playerDistance: 10f)));
// Cell-less: retail's `this_1->cell == 0` branch @0x00516386 —
// SetPosition, NOT the far snap. 4b-3 owns it.
Assert.False(RuntimeRemoteFarSnapPosition.OwnsFarSnap(
Classify(hasContact: true, playerDistance: 200f, committedCellId: 0u)));
// Fresh TELEPORT_TS: the same @0x00516386 branch. 4b-3 owns it.
Assert.False(RuntimeRemoteFarSnapPosition.OwnsFarSnap(
Classify(
hasContact: true,
playerDistance: 200f,
previousTeleport: 10,
acceptedTeleport: 11)));
// Rejections and "no classification at all".
Assert.False(RuntimeRemoteFarSnapPosition.OwnsFarSnap(
Classify(
hasContact: true,
playerDistance: 200f,
disposition: PositionTimestampDisposition.Rejected)));
Assert.False(RuntimeRemoteFarSnapPosition.OwnsFarSnap(
Classify(hasContact: true, playerDistance: float.NaN)));
Assert.False(RuntimeRemoteFarSnapPosition.OwnsFarSnap(null));
}
///
/// The disposition alone is not the discriminator: the classifier emits
/// SetPositionSimple for the LOCAL PLAYER's FORCE_POSITION branch
/// too (RuntimeAuthoritativePositionRouteClassifier.cs:332). Route
/// 4b-2 is a remote route; claiming that one would run a remote arm over
/// route 2's local-player transaction.
///
[Fact]
public void OwnsFarSnap_FalseForTheLocalPlayerForcePositionRoute()
{
RuntimeAuthoritativePositionRoute force = ClassifyKind(
RuntimePositionEntityKind.LocalPlayer,
hasContact: true,
playerDistance: 200f,
disposition: PositionTimestampDisposition.ForcePosition);
Assert.Equal(
RuntimeAuthoritativePositionDisposition.SetPositionSimple,
force.Disposition);
Assert.Equal(
RuntimeSetPositionOperationKind.LocalAuthoritative,
force.OperationKind);
Assert.False(RuntimeRemoteFarSnapPosition.OwnsFarSnap(force));
}
///
/// A REMOTE top-level initial Create is also RemoteAuthoritative;
/// it is excluded here by its disposition (SetPosition), which
/// route 4b-3 owns.
///
[Fact]
public void OwnsFarSnap_FalseForARemoteTopLevelCreateRoute()
{
RuntimeAuthoritativePositionRoute create =
RuntimeAuthoritativePositionRouteClassifier.ClassifyCreate(
new RuntimeCreatePositionRouteRequest(
Authority(PositionTimestampDisposition.Apply, 10, 10),
RuntimePositionEntityKind.Remote,
RuntimeCreateResidenceKind.TopLevel,
new CreateObject.ServerPosition(
Cell, 10f, 20f, 30f, 1f, 0f, 0f, 0f),
default));
Assert.Equal(
RuntimeSetPositionOperationKind.RemoteAuthoritative,
create.OperationKind);
Assert.Equal(
PhysicsSetPositionFlags.Placement | PhysicsSetPositionFlags.Slide,
create.SetPositionFlags);
Assert.False(RuntimeRemoteFarSnapPosition.OwnsFarSnap(create));
}
///
/// The invariant the Teleport-flag term actually carries:
/// must be a strict
/// SUBSET of
/// . The
/// far arm hands its route straight to that controller, so any route the
/// arm claims but the controller declines would execute
/// StopInterpolating and then silently do nothing
/// (NotApplicable) — a remote that stops tracking the server with
/// no diagnostic. The flags term is what keeps the two predicates
/// aligned; without it, the hand-shaped route below is claimed here and
/// declined there.
///
[Fact]
public void OwnsFarSnap_IsAStrictSubsetOfThePlacementOwnersPredicate()
{
// Every route the real classifier produces.
foreach (RuntimeAuthoritativePositionRoute route in new[]
{
Classify(hasContact: true, playerDistance: 200f),
Classify(hasContact: true, playerDistance: 10f),
Classify(hasContact: false, playerDistance: 10f),
Classify(hasContact: true, playerDistance: 200f, committedCellId: 0u),
Classify(hasContact: true, playerDistance: float.NaN),
ClassifyKind(
RuntimePositionEntityKind.LocalPlayer,
hasContact: true,
playerDistance: 200f,
disposition: PositionTimestampDisposition.ForcePosition),
})
{
if (RuntimeRemoteFarSnapPosition.OwnsFarSnap(route))
{
Assert.True(
RuntimeRemotePlacementDriveController.OwnsPlacement(route));
}
}
// …and the shape a caller could construct that the classifier does
// not: the far disposition and operation kind with a Create's flags.
RuntimeAuthoritativePositionRoute mismatched =
Classify(hasContact: true, playerDistance: 200f) with
{
SetPositionFlags = PhysicsSetPositionFlags.Placement
| PhysicsSetPositionFlags.Slide,
};
Assert.False(
RuntimeRemotePlacementDriveController.OwnsPlacement(mismatched));
Assert.False(RuntimeRemoteFarSnapPosition.OwnsFarSnap(mismatched));
}
// ── Arm selection is total, and the leftovers are named ─────────────────
[Fact]
public void ResolveArm_MapsEveryRemoteClassificationToExactlyOneArm()
{
Assert.Equal(
RuntimeRemoteAcceptedPositionArm.AirborneNoOperation,
RuntimeRemoteFarSnapPosition.ResolveArm(
Classify(hasContact: false, playerDistance: 10f)));
Assert.Equal(
RuntimeRemoteAcceptedPositionArm.NearInterpolate,
RuntimeRemoteFarSnapPosition.ResolveArm(
Classify(hasContact: true, playerDistance: 10f)));
Assert.Equal(
RuntimeRemoteAcceptedPositionArm.FarSnapPlacement,
RuntimeRemoteFarSnapPosition.ResolveArm(
Classify(hasContact: true, playerDistance: 200f)));
// The acdream-only leftovers left in THIS arm after C4 route 4b-3
// moved the cell-less/fresh-teleport shapes onto the teleport arm
// (RuntimeRemoteTeleportPosition.OwnsTeleportPlacement — see that
// class's own tests). What remains: no classification at all, and
// the two rejections.
Assert.Equal(
RuntimeRemoteAcceptedPositionArm.UnroutedCatchUp,
RuntimeRemoteFarSnapPosition.ResolveArm(
Classify(
hasContact: true,
playerDistance: 10f,
disposition: PositionTimestampDisposition.Rejected)));
Assert.Equal(
RuntimeRemoteAcceptedPositionArm.UnroutedCatchUp,
RuntimeRemoteFarSnapPosition.ResolveArm(
Classify(hasContact: true, playerDistance: float.NaN)));
Assert.Equal(
RuntimeRemoteAcceptedPositionArm.UnroutedCatchUp,
RuntimeRemoteFarSnapPosition.ResolveArm(null));
}
private static RuntimeAuthoritativePositionAuthority Authority(
PositionTimestampDisposition disposition,
ushort previousTeleport,
ushort acceptedTeleport) =>
new(
new RuntimeGenerationToken(7),
new RuntimeEntityKey(0x70000001u, 3),
PositionAuthorityVersion: 11UL,
AcceptedPositionSequence: 20,
previousTeleport,
acceptedTeleport,
disposition);
private static RuntimeAuthoritativePositionRoute Classify(
bool hasContact,
float playerDistance,
uint committedCellId = Cell,
ushort previousTeleport = 10,
ushort acceptedTeleport = 10,
PositionTimestampDisposition disposition =
PositionTimestampDisposition.Apply) =>
ClassifyKind(
RuntimePositionEntityKind.Remote,
hasContact,
playerDistance,
committedCellId,
previousTeleport,
acceptedTeleport,
disposition);
private static RuntimeAuthoritativePositionRoute ClassifyKind(
RuntimePositionEntityKind kind,
bool hasContact,
float playerDistance,
uint committedCellId = Cell,
ushort previousTeleport = 10,
ushort acceptedTeleport = 10,
PositionTimestampDisposition disposition =
PositionTimestampDisposition.Apply) =>
RuntimeAuthoritativePositionRouteClassifier.ClassifyAcceptedPosition(
new RuntimeAcceptedPositionRouteRequest(
Authority(disposition, previousTeleport, acceptedTeleport),
kind,
RuntimeAcceptedPositionSource.PositionEvent,
new CreateObject.ServerPosition(
Cell, 10f, 20f, 30f, 1f, 0f, 0f, 0f),
PlacementFrame: 0u,
PositionPackVelocity: Vector3.Zero,
committedCellId,
hasContact,
playerDistance,
UsePositionFromServer: false,
HasAnimations: false,
default));
}