fix: complete retail parity stability pass
All checks were successful
CI / linux-portable (push) Successful in 3m41s
CI / windows-gate (push) Successful in 6m49s
CI / release (push) Successful in 3m22s

This commit is contained in:
Erik 2026-08-28 20:01:39 +02:00
parent d3df4cb20a
commit f7aa8e0eb7
131 changed files with 7765 additions and 1190 deletions

View file

@ -298,14 +298,11 @@ public sealed class InboundPhysicsStateControllerTests
}
/// <summary>
/// C5b (#275) proof obligation 1: the merge's two pre-placement flags ARE
/// <see cref="RuntimeAuthoritativePositionRouteClassifier"/>'s
/// <c>ApplyPlacementFrameBeforeRouting</c>/<c>UnparentBeforeRouting</c>
/// rows. The production classifier is the oracle — this test does not
/// re-encode the truth table, it drives both computations over the packet
/// matrix and asserts the merged snapshot equals what the route's own
/// flags would have produced. Dual parent classes (player <c>0x5…</c> and
/// creature <c>0x8…</c>) per the #319 discipline.
/// #322: the merge and route classifier now consume one shared
/// pre-placement truth table. This remains an end-to-end packet matrix:
/// it proves the merge applies the shared result to placement and all
/// three parent fields, while the independently classified route exposes
/// that same result. Dual parent classes follow the #319 discipline.
/// </summary>
[Theory]
// guid, isLocalPlayer, animated, parented, force
@ -321,7 +318,7 @@ public sealed class InboundPhysicsStateControllerTests
[InlineData(0x80000032u, false, true, false, false)]
[InlineData(0x80000033u, false, false, true, false)]
[InlineData(0x80000034u, false, false, false, false)]
public void MergedPrePlacementFieldsMatchTheClassifiedRouteFlags(
public void MergedPrePlacementFieldsUseSharedRetailFlags(
uint guid,
bool isLocalPlayer,
bool animated,
@ -443,6 +440,28 @@ public sealed class InboundPhysicsStateControllerTests
merged.Physics!.Value.Parent);
}
[Theory]
[InlineData(PositionTimestampDisposition.Rejected, false, false, false)]
[InlineData(PositionTimestampDisposition.Rejected, true, false, false)]
[InlineData(PositionTimestampDisposition.ForcePosition, false, false, false)]
[InlineData(PositionTimestampDisposition.ForcePosition, true, false, false)]
[InlineData(PositionTimestampDisposition.Apply, false, true, true)]
[InlineData(PositionTimestampDisposition.Apply, true, true, false)]
public void SharedPrePlacementFlagsMatchRetailTruthTable(
PositionTimestampDisposition disposition,
bool hasAnimations,
bool expectedUnparent,
bool expectedPlacementFrame)
{
RuntimeAcceptedPositionPrePlacementFlags flags =
RuntimeAuthoritativePositionRouteClassifier.DerivePrePlacementFlags(
disposition,
hasAnimations);
Assert.Equal(expectedUnparent, flags.UnparentBeforeRouting);
Assert.Equal(expectedPlacementFrame, flags.ApplyPlacementFrameBeforeRouting);
}
[Fact]
public void RemotePositionWithoutVelocityAppliesUnpackedZeroVector()
{
@ -861,8 +880,8 @@ public sealed class InboundPhysicsStateControllerTests
/// #307, the shipped consequence: a local player who has portalled or
/// recalled this session holds a nonzero TELEPORT_TS. Retail's
/// FORCE_POSITION branch (<c>SmartBox::HandleReceivedPosition</c>
/// 0x00453FD0) fires only when the packet's teleport stamp EQUALS the live
/// one and never advances it, so the authority C4 route 2 builds from
/// 0x00453FD0) fires when the packet's teleport stamp is NOT OLDER than
/// the live one and never advances it, so the authority C4 route 2 builds from
/// these timestamps must satisfy
/// <c>PreviousTeleportSequence == AcceptedTeleportSequence</c>. With
/// PreviousTeleport pinned to 0 the classifier rejected the authority and
@ -926,6 +945,37 @@ public sealed class InboundPhysicsStateControllerTests
Assert.Equal((ushort)10, timestamps.Teleport);
}
[Fact]
public void LocalPlayerForcePositionWithNewerTeleportLeavesAStaleEqualAcceptedPair()
{
var controller = new InboundPhysicsStateController();
WorldSession.EntitySpawn spawn = WithTimestamps(
Spawn(0x50000012u, 3, 10, 1, Position(0x0101FFFFu, 10f), 0x408u),
teleport: 10,
forcePosition: 0);
controller.AcceptCreate(spawn);
Assert.True(controller.TryApplyPosition(
PositionUpdate(
spawn.Guid,
instance: 3,
position: 11,
teleport: 11,
forcePosition: 1),
isLocalPlayer: true,
forcePositionRotation: Quaternion.Identity,
currentLocalVelocity: new Vector3(1f, 2f, 3f),
out PositionTimestampDisposition disposition,
out WorldSession.EntitySpawn accepted,
out AcceptedPhysicsTimestamps timestamps));
Assert.Equal(PositionTimestampDisposition.ForcePosition, disposition);
Assert.Equal((ushort)10, timestamps.PreviousTeleport);
Assert.Equal((ushort)10, timestamps.Teleport);
Assert.False(timestamps.TeleportAdvanced);
Assert.Equal(new Vector3(1f, 2f, 3f), accepted.Physics!.Value.Velocity);
}
private static WorldSession.EntityPositionUpdate PositionUpdate(
uint guid,
ushort instance,