feat(runtime): freeze initial placement inbound admission

This commit is contained in:
Erik 2026-08-01 21:00:03 +02:00
parent 9d601817b8
commit 30012361e1
9 changed files with 2506 additions and 323 deletions

View file

@ -30,11 +30,14 @@ internal readonly record struct RuntimeInitialCreateResidenceLease(
RuntimeInitialCreateResidenceToken Token,
RuntimeAuthoritativePositionRoute Route,
RuntimeEntityPlacementToken Placement,
WorldSession.EntitySpawn InitialCreate,
ImmutableArray<RuntimeInitialCreateResidenceContinuation> Continuations)
{
internal bool IsValid => Token.IsValid
&& Route.Accepted
&& Route.Authority.Entity == Token.Entity
&& InitialCreate.Guid != 0u
&& InitialCreate.InstanceSequence == Token.Entity.Incarnation
&& !Continuations.IsDefault
&& HasValidContinuationChain()
&& (!Route.PerformsSetPosition
@ -43,7 +46,7 @@ internal readonly record struct RuntimeInitialCreateResidenceLease(
private bool HasValidContinuationChain()
{
ushort previousTeleport = Route.Authority.AcceptedTeleportSequence;
uint ownerGuid = InitialCreate.Guid;
for (int index = 0; index < Continuations.Length; index++)
{
RuntimeInitialCreateResidenceContinuation continuation =
@ -51,52 +54,291 @@ internal readonly record struct RuntimeInitialCreateResidenceLease(
if (!continuation.IsValid
|| continuation.Sequence != (ulong)index + 1UL
|| continuation.InstanceSequence != Token.Entity.Incarnation
|| continuation.PositionAuthorityVersion
!= Token.PositionAuthorityVersion
|| continuation.PreviousTeleportSequence
!= previousTeleport)
|| continuation.Actions.Any(
action => action.OwnerGuid != ownerGuid))
{
return false;
}
previousTeleport = continuation.AcceptedTeleportSequence;
}
return true;
}
}
internal enum RuntimeInitialCreateContinuationKind : byte
{
SameIncarnationCreate,
ObjDesc,
Parent,
Pickup,
Position,
Movement,
State,
Vector,
}
internal enum RuntimeInitialCreateTailActionKind : byte
{
/// <summary>
/// Isolated AP-119 compatibility behavior. Retail's equal-generation
/// Create tail starts at ObjDesc and does not call set_description again.
/// </summary>
PreTailDescriptionAdaptation,
ObjDesc,
CreateParent,
Parent,
Pickup,
Position,
Movement,
State,
Vector,
WeenieDescription,
ResidentCellCleanup,
}
internal readonly record struct RuntimeInitialCreateTailAction(
RuntimeInitialCreateTailActionKind Kind,
uint OwnerGuid,
PhysicsSpawnData? Description = null,
ObjDescEvent.Parsed? ObjDesc = null,
CreateParentUpdate? CreateParent = null,
ParentEvent.Parsed? Parent = null,
PickupEvent.Parsed? Pickup = null,
WorldSession.EntityPositionUpdate? Position = null,
WorldSession.EntityMotionUpdate? Movement = null,
SetState.Parsed? State = null,
VectorUpdate.Parsed? Vector = null,
WorldSession.EntitySpawn? WeenieDescription = null,
RuntimeAcceptedPositionSource PositionSource =
RuntimeAcceptedPositionSource.Unknown,
PositionTimestampDisposition PositionDisposition =
PositionTimestampDisposition.Rejected,
ushort PreviousTeleportSequence = 0,
AcceptedPhysicsTimestamps AcceptedTimestamps = default,
bool AppliesMovementPayload = false,
bool RetainMovementPayload = true,
bool HasTimestampMutation = false)
{
internal bool IsStructurallyValid => HasExclusivePayload()
&& Kind switch
{
RuntimeInitialCreateTailActionKind.PreTailDescriptionAdaptation =>
Description is not null,
RuntimeInitialCreateTailActionKind.ObjDesc => ObjDesc is { } objDesc
&& objDesc.Guid == OwnerGuid,
RuntimeInitialCreateTailActionKind.CreateParent =>
CreateParent is { } createParent
&& createParent.ChildGuid == OwnerGuid,
RuntimeInitialCreateTailActionKind.Parent => Parent is { } parent
&& parent.ChildGuid == OwnerGuid,
RuntimeInitialCreateTailActionKind.Pickup => Pickup is { } pickup
&& pickup.Guid == OwnerGuid,
RuntimeInitialCreateTailActionKind.Position => Position is { } position
&& position.Guid == OwnerGuid
&& PositionSource is RuntimeAcceptedPositionSource.PositionEvent
or RuntimeAcceptedPositionSource.SameIncarnationCreate
&& (PositionDisposition is PositionTimestampDisposition.Apply
or PositionTimestampDisposition.ForcePosition
|| PositionDisposition is PositionTimestampDisposition.Rejected
&& HasTimestampMutation),
RuntimeInitialCreateTailActionKind.Movement => Movement is { } movement
&& movement.Guid == OwnerGuid
&& (AppliesMovementPayload || HasTimestampMutation),
RuntimeInitialCreateTailActionKind.State => State is { } state
&& state.Guid == OwnerGuid,
RuntimeInitialCreateTailActionKind.Vector => Vector is { } vector
&& vector.Guid == OwnerGuid,
RuntimeInitialCreateTailActionKind.WeenieDescription =>
WeenieDescription is { } weenie
&& weenie.Guid == OwnerGuid,
RuntimeInitialCreateTailActionKind.ResidentCellCleanup => true,
_ => false,
};
internal bool MatchesInstance(ushort instanceSequence) => Kind switch
{
RuntimeInitialCreateTailActionKind.PreTailDescriptionAdaptation =>
Description is { } description
&& description.Timestamps.Instance == instanceSequence,
RuntimeInitialCreateTailActionKind.ObjDesc =>
ObjDesc is { } objDesc
&& objDesc.InstanceSequence == instanceSequence,
RuntimeInitialCreateTailActionKind.CreateParent =>
CreateParent is { } createParent
&& createParent.ChildInstanceSequence == instanceSequence,
// ParentEvent carries only the parent's INSTANCE_TS. Acceptance
// already exact-gated the child's current incarnation; preserve that
// proof in AcceptedTimestamps for the later no-regate executor.
RuntimeInitialCreateTailActionKind.Parent =>
AcceptedTimestamps.Instance == instanceSequence,
RuntimeInitialCreateTailActionKind.Pickup =>
Pickup is { } pickup
&& pickup.InstanceSequence == instanceSequence,
RuntimeInitialCreateTailActionKind.Position =>
Position is { } position
&& position.InstanceSequence == instanceSequence,
RuntimeInitialCreateTailActionKind.Movement =>
Movement is { } movement
&& movement.InstanceSequence == instanceSequence,
RuntimeInitialCreateTailActionKind.State =>
State is { } state
&& state.InstanceSequence == instanceSequence,
RuntimeInitialCreateTailActionKind.Vector =>
Vector is { } vector
&& vector.InstanceSequence == instanceSequence,
RuntimeInitialCreateTailActionKind.WeenieDescription =>
WeenieDescription is { } weenie
&& weenie.InstanceSequence == instanceSequence,
RuntimeInitialCreateTailActionKind.ResidentCellCleanup => true,
_ => false,
};
private bool HasExclusivePayload()
{
int payloadCount = (Description is null ? 0 : 1)
+ (ObjDesc is null ? 0 : 1)
+ (CreateParent is null ? 0 : 1)
+ (Parent is null ? 0 : 1)
+ (Pickup is null ? 0 : 1)
+ (Position is null ? 0 : 1)
+ (Movement is null ? 0 : 1)
+ (State is null ? 0 : 1)
+ (Vector is null ? 0 : 1)
+ (WeenieDescription is null ? 0 : 1);
return Kind is RuntimeInitialCreateTailActionKind.ResidentCellCleanup
? payloadCount == 0
: payloadCount == 1;
}
}
/// <summary>
/// One accepted Position packet which arrived before the immutable initial
/// CreateObject admission completed. These records remain dormant until a
/// host adopts the completed batch; accepting them never replaces or mutates
/// the initial 0x11 SetPosition operation.
/// One immutable inbound envelope which arrived while retail's synchronous
/// CreateObject critical section was virtualized by an asynchronous initial
/// SetPosition. Envelopes are never coalesced. A same-incarnation Create is
/// one atomic envelope whose ordered tail is expanded only by the executor.
/// Position retains the raw PositionPack and is classified only at the FIFO
/// head, after every earlier envelope has committed.
/// </summary>
internal readonly record struct RuntimeInitialCreateResidenceContinuation(
ulong Sequence,
RuntimePositionEntityKind EntityKind,
RuntimeInitialCreateContinuationKind Kind,
ushort InstanceSequence,
ushort PositionSequence,
ushort PreviousTeleportSequence,
ushort TeleportSequence,
ushort ForcePositionSequence,
ushort AcceptedTeleportSequence,
ushort AcceptedForcePositionSequence,
PositionTimestampDisposition TimestampDisposition,
CreateObject.ServerPosition AcceptedWirePosition,
Vector3? PositionPackVelocity,
Vector3? AcceptedVelocity,
Quaternion? ForcePositionRotation,
Vector3? CurrentLocalVelocity,
bool ProjectionRequiresTeleportHook,
uint PlacementFrame,
ulong PositionAuthorityVersion)
RuntimeAcceptedPositionSource PositionSource,
ImmutableArray<RuntimeInitialCreateTailAction> Actions)
{
internal bool IsValid => Sequence != 0UL
&& EntityKind is RuntimePositionEntityKind.LocalPlayer
or RuntimePositionEntityKind.Remote
or RuntimePositionEntityKind.Projectile
&& PositionAuthorityVersion != 0UL
&& TimestampDisposition is PositionTimestampDisposition.Apply
or PositionTimestampDisposition.ForcePosition;
&& !Actions.IsDefaultOrEmpty
&& Actions.All(static action => action.IsStructurallyValid)
&& HasMatchingInstances()
&& HasValidShape();
private bool HasMatchingInstances()
{
for (int index = 0; index < Actions.Length; index++)
{
if (!Actions[index].MatchesInstance(InstanceSequence))
return false;
}
return true;
}
private bool HasValidShape()
{
if (Kind is not RuntimeInitialCreateContinuationKind.SameIncarnationCreate)
{
if (Actions.Length != 1)
return false;
RuntimeInitialCreateTailAction action = Actions[0];
RuntimeInitialCreateTailActionKind expected = Kind switch
{
RuntimeInitialCreateContinuationKind.ObjDesc =>
RuntimeInitialCreateTailActionKind.ObjDesc,
RuntimeInitialCreateContinuationKind.Parent =>
RuntimeInitialCreateTailActionKind.Parent,
RuntimeInitialCreateContinuationKind.Pickup =>
RuntimeInitialCreateTailActionKind.Pickup,
RuntimeInitialCreateContinuationKind.Position =>
RuntimeInitialCreateTailActionKind.Position,
RuntimeInitialCreateContinuationKind.Movement =>
RuntimeInitialCreateTailActionKind.Movement,
RuntimeInitialCreateContinuationKind.State =>
RuntimeInitialCreateTailActionKind.State,
RuntimeInitialCreateContinuationKind.Vector =>
RuntimeInitialCreateTailActionKind.Vector,
_ => throw new InvalidOperationException(
$"Unsupported initial-Create continuation kind {Kind}."),
};
return action.Kind == expected
&& (Kind is RuntimeInitialCreateContinuationKind.Position
? PositionSource is RuntimeAcceptedPositionSource.PositionEvent
&& action.PositionSource == PositionSource
: PositionSource is RuntimeAcceptedPositionSource.Unknown);
}
if (Actions.Length < 2
|| Actions[^2].Kind
is not RuntimeInitialCreateTailActionKind.WeenieDescription
|| Actions[^1].Kind
is not RuntimeInitialCreateTailActionKind.ResidentCellCleanup)
{
return false;
}
bool hasPosition = Actions.Any(
static action => action.Kind
is RuntimeInitialCreateTailActionKind.Position);
if (hasPosition
? PositionSource
is not RuntimeAcceptedPositionSource.SameIncarnationCreate
: PositionSource is not RuntimeAcceptedPositionSource.Unknown)
{
return false;
}
int previousStage = -1;
int positionBranchCount = 0;
for (int index = 0; index < Actions.Length; index++)
{
RuntimeInitialCreateTailAction action = Actions[index];
int stage = SameCreateStage(action.Kind);
if (stage <= previousStage)
return false;
if (action.Kind is RuntimeInitialCreateTailActionKind.Position
&& action.PositionSource != PositionSource)
{
return false;
}
if (action.Kind is RuntimeInitialCreateTailActionKind.CreateParent
or RuntimeInitialCreateTailActionKind.Pickup
or RuntimeInitialCreateTailActionKind.Position)
{
positionBranchCount++;
}
previousStage = stage;
}
bool hasPhysicsDescription = Actions.Any(
static action => action.Kind
is RuntimeInitialCreateTailActionKind
.PreTailDescriptionAdaptation);
return hasPhysicsDescription
? positionBranchCount <= 1
: positionBranchCount == 0;
}
private static int SameCreateStage(RuntimeInitialCreateTailActionKind kind) =>
kind switch
{
RuntimeInitialCreateTailActionKind.PreTailDescriptionAdaptation => 0,
RuntimeInitialCreateTailActionKind.ObjDesc => 1,
RuntimeInitialCreateTailActionKind.CreateParent
or RuntimeInitialCreateTailActionKind.Pickup
or RuntimeInitialCreateTailActionKind.Position => 2,
RuntimeInitialCreateTailActionKind.Movement => 3,
RuntimeInitialCreateTailActionKind.State => 4,
RuntimeInitialCreateTailActionKind.Vector => 5,
RuntimeInitialCreateTailActionKind.WeenieDescription => 6,
RuntimeInitialCreateTailActionKind.ResidentCellCleanup => 7,
_ => int.MinValue,
};
}
internal readonly record struct RuntimeInitialCreateResidenceAdoptionToken(
@ -259,125 +501,37 @@ internal sealed class RuntimeInitialCreateResidenceState
return Own(record, route);
}
internal RuntimeInitialCreateResidenceLease EnqueueAcceptedPosition(
internal RuntimeInitialCreateResidenceLease EnqueueAccepted(
RuntimeEntityRecord record,
in RuntimeInitialCreateResidenceLease prior,
WorldSession.EntityPositionUpdate update,
in WorldSession.EntitySpawn accepted,
PositionTimestampDisposition disposition,
in AcceptedPhysicsTimestamps timestamps,
bool isLocalPlayer,
Quaternion? forcePositionRotation,
Vector3? currentLocalVelocity,
bool projectionRequiresTeleportHook)
RuntimeInitialCreateContinuationKind kind,
RuntimeAcceptedPositionSource positionSource,
ImmutableArray<RuntimeInitialCreateTailAction> actions)
{
ArgumentNullException.ThrowIfNull(record);
if (!_entities.IsCurrent(record)
|| record.Key is not { } key
|| update.Guid != record.ServerGuid
|| accepted.Guid != record.ServerGuid
|| disposition is PositionTimestampDisposition.Rejected)
var owned = ImmutableArray.CreateBuilder<
RuntimeInitialCreateTailAction>(actions.Length);
foreach (RuntimeInitialCreateTailAction action in actions)
{
return default;
owned.Add(RuntimeInitialCreateAdmissionFreezer.Freeze(action));
}
RuntimeInitialCreateResidenceLease current;
Entry? active = null;
CompletedEntry? completed = null;
if (_entries.TryGetValue(key, out active)
&& ReferenceEquals(active.Record, record)
&& active.Lease.Token == prior.Token
&& IsCurrent(active))
{
current = active.Lease;
}
else if (_completed.TryGetValue(key, out completed)
&& ReferenceEquals(completed.Record, record)
&& completed.Lease.Token == prior.Token
&& IsCompletedCurrent(completed))
{
current = completed.Lease;
}
else
{
return default;
}
if (current.Continuations.Length == int.MaxValue
|| completed is not null
&& completed.Receipt.Adoption.Revision == ulong.MaxValue)
return default;
RuntimePositionEntityKind entityKind = isLocalPlayer
? RuntimePositionEntityKind.LocalPlayer
: (record.FinalPhysicsState & PhysicsStateFlags.Missile) != 0
? RuntimePositionEntityKind.Projectile
: RuntimePositionEntityKind.Remote;
CreateObject.ServerPosition acceptedPosition =
accepted.Position ?? update.Position;
ushort previousTeleport = current.Continuations.IsEmpty
? current.Route.Authority.AcceptedTeleportSequence
: current.Continuations[^1].AcceptedTeleportSequence;
ulong sequence = (ulong)current.Continuations.Length + 1UL;
var continuation = new RuntimeInitialCreateResidenceContinuation(
sequence,
entityKind,
update.InstanceSequence,
update.PositionSequence,
previousTeleport,
update.TeleportSequence,
update.ForcePositionSequence,
timestamps.Teleport,
timestamps.ForcePosition,
disposition,
acceptedPosition,
update.Velocity,
accepted.Physics?.Velocity,
forcePositionRotation,
currentLocalVelocity,
projectionRequiresTeleportHook,
accepted.PlacementId ?? 0u,
record.PositionAuthorityVersion);
if (!continuation.IsValid)
return default;
RuntimeInitialCreateResidenceLease revised = current with
{
Continuations = current.Continuations.Add(continuation),
};
if (active is not null)
{
active.Lease = revised;
}
else
{
completed!.Lease = revised;
RuntimeInitialCreateResidenceAdoptionToken revisedAdoption =
completed.Receipt.Adoption with
{
Revision = completed.Receipt.Adoption.Revision + 1UL,
};
completed.Receipt = completed.Receipt with
{
Adoption = revisedAdoption,
Continuations = revised.Continuations,
};
}
return revised;
return Enqueue(
record,
prior,
new RuntimeInitialCreateResidenceContinuation(
NextSequence(prior),
kind,
record.Incarnation,
positionSource,
owned.MoveToImmutable()));
}
internal bool CanEnqueueAcceptedPosition(
internal bool CanEnqueue(
RuntimeEntityRecord record,
in RuntimeInitialCreateResidenceLease prior,
in WorldSession.EntityPositionUpdate update)
in RuntimeInitialCreateResidenceLease prior)
{
ArgumentNullException.ThrowIfNull(record);
if (record.Key is not { } key
|| update.Guid != record.ServerGuid
|| !RuntimeAuthoritativePositionRouteClassifier
.IsValidCreateWirePosition(update.Position))
{
if (record.Key is not { } key)
return false;
}
if (_entries.TryGetValue(key, out Entry? entry))
{
return ReferenceEquals(entry.Record, record)
@ -393,6 +547,61 @@ internal sealed class RuntimeInitialCreateResidenceState
&& completed.Receipt.Adoption.Revision < ulong.MaxValue;
}
private RuntimeInitialCreateResidenceLease Enqueue(
RuntimeEntityRecord record,
in RuntimeInitialCreateResidenceLease prior,
in RuntimeInitialCreateResidenceContinuation continuation)
{
ArgumentNullException.ThrowIfNull(record);
if (!continuation.IsValid
|| continuation.InstanceSequence != record.Incarnation
|| !CanEnqueue(record, prior))
{
return default;
}
RuntimeEntityKey key = record.Key!.Value;
Entry? active = null;
CompletedEntry? completed = null;
RuntimeInitialCreateResidenceLease current;
if (_entries.TryGetValue(key, out active))
current = active.Lease;
else if (_completed.TryGetValue(key, out completed))
current = completed.Lease;
else
return default;
if (continuation.Sequence != NextSequence(current))
return default;
RuntimeInitialCreateResidenceLease revised = current with
{
Continuations = current.Continuations.Add(continuation),
};
if (active is not null)
{
active.Lease = revised;
}
else
{
completed!.Lease = revised;
RuntimeInitialCreateResidenceAdoptionToken adoption =
completed.Receipt.Adoption with
{
Revision = completed.Receipt.Adoption.Revision + 1UL,
};
completed.Receipt = completed.Receipt with
{
Adoption = adoption,
Continuations = revised.Continuations,
};
}
return revised;
}
private static ulong NextSequence(
in RuntimeInitialCreateResidenceLease lease) =>
(ulong)lease.Continuations.Length + 1UL;
internal bool TryGetTransaction(
RuntimeEntityRecord record,
out RuntimeInitialCreateResidenceLease lease)
@ -457,6 +666,7 @@ internal sealed class RuntimeInitialCreateResidenceState
token,
route,
placement,
RuntimeInitialCreateAdmissionFreezer.Freeze(record.Snapshot),
ImmutableArray<RuntimeInitialCreateResidenceContinuation>.Empty);
_entries.Add(key, new Entry
{
@ -600,6 +810,12 @@ internal sealed class RuntimeInitialCreateResidenceState
Retire(current);
return false;
}
// Admission-only checkpoint: a completed initial placement remains
// owned until the next slice's continuation executor has drained the
// exact FIFO revision. Letting a host acknowledge here would silently
// discard accepted packets.
if (!current.Lease.Continuations.IsEmpty)
return false;
if (current.Lease.Route.PerformsSetPosition
&& !_setPosition.ConsumeAcknowledgedPlacement(
current.Lease.Placement,