fix: complete retail parity stability pass
This commit is contained in:
parent
d3df4cb20a
commit
f7aa8e0eb7
131 changed files with 7765 additions and 1190 deletions
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue