feat(runtime): commit dormant SetPosition activation

This commit is contained in:
Erik 2026-08-01 14:25:02 +02:00
parent 99f867f053
commit 5785a07b3e
13 changed files with 4674 additions and 111 deletions

View file

@ -4,6 +4,7 @@ using AcDream.Core.Items;
using AcDream.Core.Net.Messages;
using AcDream.Core.Physics;
using AcDream.Runtime.Entities;
using AcDream.Runtime.Gameplay;
namespace AcDream.Runtime.Physics;
@ -29,6 +30,7 @@ internal enum RuntimeEntityPlacementStage
AwaitingPreparation,
AwaitingWithdrawalAcknowledgement,
AwaitingCell,
AwaitingFinalShadowPreparation,
AwaitingCommitAcknowledgement,
CancelledAwaitingAcknowledgement,
}
@ -109,6 +111,65 @@ internal readonly record struct RuntimeDormantSetPositionEvaluation(
&& CollisionAuthority.IsValid;
}
internal enum RuntimeDormantSetPositionCommitStatus : byte
{
None,
AwaitingFinalShadowPreparation,
Committed,
DeferredCell,
RejectedPlacement,
RejectedAuthority,
}
internal sealed class PreparedDormantSetPositionCommit
{
internal required RuntimeDormantSetPositionEvaluation Evaluation
{ get; init; }
internal required RuntimeEntityKey Entity { get; init; }
internal required ulong OperationId { get; init; }
internal required ulong ExpectedProjectionSequence { get; init; }
internal required ShadowObjectRegistry.PreparedSetPositionShadowCommit?
Shadow { get; init; }
internal required RuntimeCollisionReportingState
.PreparedSetPositionCollisionBatch? Collision { get; init; }
internal required RuntimePlacementProjectionSnapshot Projection
{ get; init; }
internal required SortedDictionary<ulong, RuntimePlacementProjectionSnapshot>?
PendingProjection { get; init; }
internal required ulong DeferredCollisionGeneration { get; init; }
internal required List<RuntimeEntityKey>? DeferredBucket { get; init; }
internal required bool DeferredBucketIsNew { get; init; }
}
internal sealed class PreparedDormantActivationFinalCommit
{
internal required RuntimeEntityKey Entity { get; init; }
internal required ulong OperationId { get; init; }
internal required ulong ExpectedProjectionSequence { get; init; }
internal required ShadowObjectRegistry.PreparedSetPositionShadowCommit
Shadow { get; init; }
internal required RuntimePlacementProjectionSnapshot Projection
{ get; init; }
internal required SortedDictionary<ulong, RuntimePlacementProjectionSnapshot>
PendingProjection { get; init; }
}
internal readonly record struct RuntimeDormantSetPositionCommitReceipt(
RuntimeDormantSetPositionCommitStatus Status,
RuntimeEntityKey Entity,
ulong OperationId,
RuntimePlacementProjectionSnapshot Projection,
RuntimeCollisionReportingState.SetPositionCollisionBatchReceipt Collision,
ShadowObjectRegistry.SetPositionShadowCommitReceipt Shadow,
RuntimeCollisionEvaluationAuthority CollisionAuthority,
ulong SourceVectorAuthorityVersion,
bool HitGround,
bool LeaveGround)
{
internal bool IsCommitted => Status
is RuntimeDormantSetPositionCommitStatus.Committed;
}
public readonly record struct RuntimePlacementProjectionToken(
ulong Sequence,
ulong Revision,
@ -258,6 +319,7 @@ internal sealed class RuntimeSetPositionState : IDisposable
internal List<RuntimeEntityKey>? LostFamilyKeys { get; set; }
internal bool InheritedLostDeadline { get; set; }
internal bool EnteringWorldFromCelllessResidence { get; set; }
internal bool DormantLocalActivation { get; set; }
internal RuntimeSetPositionCommand? PreparedCommandAwaitingWithdrawalAck
{
get;
@ -289,7 +351,7 @@ internal sealed class RuntimeSetPositionState : IDisposable
private readonly Dictionary<RuntimeEntityKey, Operation> _operations = [];
private readonly Dictionary<CellGenerationKey, List<RuntimeEntityKey>>
_deferredByCellGeneration = [];
private readonly SortedDictionary<ulong, RuntimePlacementProjectionSnapshot>
private SortedDictionary<ulong, RuntimePlacementProjectionSnapshot>
_pendingProjection = [];
private readonly List<CellGenerationKey> _deferredBucketOrder = [];
private readonly Dictionary<uint, List<RuntimeEntityKey>>
@ -558,8 +620,12 @@ internal sealed class RuntimeSetPositionState : IDisposable
if (!token.IsValid
|| !_operations.TryGetValue(token.Entity, out Operation? operation)
|| operation.Token != token
|| operation.Stage
is not RuntimeEntityPlacementStage.AwaitingPreparation
|| operation.Stage is not (
RuntimeEntityPlacementStage.AwaitingPreparation
or RuntimeEntityPlacementStage.AwaitingCell)
|| operation.Stage is RuntimeEntityPlacementStage.AwaitingCell
&& (!operation.DormantLocalActivation
|| !operation.WakeableLostCell)
|| !IsCurrent(operation)
|| !_moverPreparationAuthorities.TryGetValue(
token.Entity,
@ -641,6 +707,20 @@ internal sealed class RuntimeSetPositionState : IDisposable
ArgumentNullException.ThrowIfNull(record);
ArgumentNullException.ThrowIfNull(body);
evaluation = default;
if (!IsExactDormantLocalActivationCurrent(
record,
body,
token,
command,
out _)
&& !TryRearmDeferredDormantLocalActivation(
record,
body,
token,
command))
{
return false;
}
if (!IsExactDormantLocalActivationCurrent(
record,
body,
@ -716,6 +796,779 @@ internal sealed class RuntimeSetPositionState : IDisposable
&& _physics.IsCollisionEvaluationAuthorityCurrent(
evaluation.CollisionAuthority);
internal bool IsDormantLocalActivationLeaseCurrent(
RuntimeEntityRecord record,
PhysicsBody body,
in RuntimeEntityPlacementToken token,
in RuntimeSetPositionCommand command) =>
IsExactDormantLocalActivationCurrent(
record,
body,
token,
command,
out _,
allowDeferredLease: true);
internal bool IsDormantLocalActivationAwaitingCell(
RuntimeEntityRecord record,
PhysicsBody body,
in RuntimeEntityPlacementToken token,
in RuntimeSetPositionCommand command)
{
return IsExactDormantLocalActivationCurrent(
record,
body,
token,
command,
out Operation? operation,
allowDeferredLease: true)
&& operation is not null
&& operation.Stage is RuntimeEntityPlacementStage.AwaitingCell
&& operation.DormantLocalActivation
&& operation.WakeableLostCell;
}
private bool TryRearmDeferredDormantLocalActivation(
RuntimeEntityRecord record,
PhysicsBody body,
in RuntimeEntityPlacementToken token,
in RuntimeSetPositionCommand command)
{
if (!IsExactDormantLocalActivationCurrent(
record,
body,
token,
command,
out Operation? operation,
allowDeferredLease: true)
|| operation is null
|| operation.Stage is not RuntimeEntityPlacementStage.AwaitingCell
|| !operation.DormantLocalActivation
|| !operation.WakeableLostCell
|| !operation.CollisionGenerationReady
|| operation.ProjectionSequence != 0UL
|| operation.CollisionGeneration != _physics
.ExpectedCollisionGeneration(operation.ExactCellId)
|| !_physics.Engine.IsSpawnCellReady(operation.ExactCellId))
{
return false;
}
UnindexDeferred(operation);
operation.WakeableLostCell = false;
operation.CollisionGenerationReady = false;
operation.Stage = RuntimeEntityPlacementStage.AwaitingPreparation;
return true;
}
internal bool TryPrepareDormantLocalActivationCommit(
RuntimeEntityRecord record,
PhysicsBody body,
in RuntimeDormantSetPositionEvaluation evaluation,
bool provenShapeless,
out PreparedDormantSetPositionCommit? prepared)
{
EnsureNotDisposed();
ArgumentNullException.ThrowIfNull(record);
ArgumentNullException.ThrowIfNull(body);
prepared = null;
if (!IsDormantLocalEvaluationCurrent(record, body, evaluation)
|| !IsExactDormantLocalActivationCurrent(
record,
body,
evaluation.Placement,
evaluation.Command,
out Operation? operation,
allowCanonicalCommand: true)
|| operation is null)
{
return false;
}
PhysicsSetPositionResult result = evaluation.Result;
ShadowObjectRegistry.PreparedSetPositionShadowCommit? shadow = null;
RuntimeCollisionReportingState.PreparedSetPositionCollisionBatch?
collision = null;
RuntimePlacementProjectionSnapshot projection = default;
SortedDictionary<ulong, RuntimePlacementProjectionSnapshot>?
pendingProjection = null;
ulong deferredCollisionGeneration = 0UL;
List<RuntimeEntityKey>? deferredBucket = null;
bool deferredBucketIsNew = false;
if (!result.IsDeferred)
{
if (!_physics.CollisionReports.TryPrepareSetPositionBatch(
record,
body,
evaluation.Command.GameTime,
result.IsCommitted && operation.PreviousContact,
result.IsCommitted && operation.PreviousOnWalkable,
result.IsCommitted && result.OnWalkable,
result.CollidedWithEnvironment,
result.CollidedObjectIds,
out collision)
|| collision is null)
{
return false;
}
}
if (result.IsDeferred)
{
deferredCollisionGeneration = _physics
.ExpectedCollisionGeneration(result.CellId);
_preparedMovers.EnsureCapacity(_preparedMovers.Count + 1);
if (result.CellId != 0u && deferredCollisionGeneration != 0UL)
{
var bucketKey = new CellGenerationKey(
result.CellId,
deferredCollisionGeneration);
if (_deferredByCellGeneration.TryGetValue(
bucketKey,
out deferredBucket))
{
deferredBucket.EnsureCapacity(deferredBucket.Count + 1);
}
else
{
deferredBucket = [operation.Key];
deferredBucketIsNew = true;
_deferredByCellGeneration.EnsureCapacity(
_deferredByCellGeneration.Count + 1);
_deferredBucketOrder.EnsureCapacity(
_deferredBucketOrder.Count + 1);
}
}
if (!_physics.Engine.ShadowObjects.TryPrepareSetPosition(
operation.Key.LocalEntityId,
result.Position,
result.Orientation,
result.CellId,
evaluation.Command.ShadowWorldOffsetX,
evaluation.Command.ShadowWorldOffsetY,
PhysicsShadowCommitAction.Preserve,
ImmutableArray<uint>.Empty,
provenShapeless,
suspendOwner: true,
out shadow)
|| shadow is null)
{
return false;
}
}
ulong expectedProjectionSequence = _nextProjectionSequence;
if (result.IsCommitted)
{
_ = checked(record.ObjectClockEpoch + 1UL);
_ = checked(record.PlacementCommitVersion + 1UL);
if (record.FullCellId != result.CellId)
_ = checked(record.SpatialAuthorityVersion + 1UL);
if (!_physics.TryPrepareSpatialRootAdmission(record))
return false;
ulong sequence = checked(expectedProjectionSequence + 1UL);
ulong spatial = record.SpatialAuthorityVersion
+ (record.FullCellId == result.CellId ? 0UL : 1UL);
ulong placement = checked(record.PlacementCommitVersion + 1UL);
var token = new RuntimePlacementProjectionToken(
sequence,
Revision: 1UL,
operation.Key,
operation.PositionAuthorityVersion,
spatial,
placement,
operation.SessionLifetimeVersion,
result.CellId,
operation.CollisionGeneration,
evaluation.Command.Portal);
projection = new RuntimePlacementProjectionSnapshot(
token,
RuntimePlacementProjectionKind.Place,
result.Position,
result.Orientation,
result.CellLocalPosition,
result.InContact,
result.OnWalkable);
pendingProjection = new SortedDictionary<
ulong,
RuntimePlacementProjectionSnapshot>(_pendingProjection)
{
[sequence] = projection,
};
}
prepared = new PreparedDormantSetPositionCommit
{
Evaluation = evaluation,
Entity = operation.Key,
OperationId = operation.Token.OperationId,
ExpectedProjectionSequence = expectedProjectionSequence,
Shadow = shadow,
Collision = collision,
Projection = projection,
PendingProjection = pendingProjection,
DeferredCollisionGeneration = deferredCollisionGeneration,
DeferredBucket = deferredBucket,
DeferredBucketIsNew = deferredBucketIsNew,
};
return IsPreparedDormantCommitCurrent(record, body, prepared);
}
internal bool TryApplyDormantLocalActivationCommit(
RuntimeEntityRecord record,
PhysicsBody body,
PlayerMovementController controller,
EntityPhysicsHost physicsHost,
PreparedDormantSetPositionCommit prepared,
out RuntimeDormantSetPositionCommitReceipt receipt)
{
EnsureNotDisposed();
ArgumentNullException.ThrowIfNull(record);
ArgumentNullException.ThrowIfNull(body);
ArgumentNullException.ThrowIfNull(controller);
ArgumentNullException.ThrowIfNull(physicsHost);
ArgumentNullException.ThrowIfNull(prepared);
receipt = default;
if (!IsPreparedDormantCommitCurrent(record, body, prepared)
|| !_operations.TryGetValue(
prepared.Entity,
out Operation? operation))
{
return false;
}
PhysicsSetPositionResult result = prepared.Evaluation.Result;
operation.Body = body;
operation.DormantLocalActivation = true;
if (result.IsDeferred)
{
if (prepared.Shadow is null
|| !_physics.Engine.ShadowObjects.TryApplySetPosition(
prepared.Shadow,
out ShadowObjectRegistry.SetPositionShadowCommitReceipt
deferredShadowReceipt))
{
return false;
}
body.Orientation = result.Orientation;
body.StageDormantCellFrame(
result.CellId,
result.Position,
result.CellLocalPosition);
body.InWorld = false;
body.TransientState &= ~TransientStateFlags.Active;
operation.Result = result;
operation.ExactCellId = result.CellId;
operation.WakeableLostCell = true;
operation.CollisionGeneration = prepared
.DeferredCollisionGeneration;
operation.CollisionGenerationReady = false;
operation.Stage = RuntimeEntityPlacementStage.AwaitingCell;
_preparedMovers[operation.Key] = prepared.Evaluation.Command.Physics;
if (prepared.DeferredBucket is { } deferredBucket)
{
var bucketKey = new CellGenerationKey(
result.CellId,
prepared.DeferredCollisionGeneration);
if (prepared.DeferredBucketIsNew)
{
_deferredByCellGeneration.Add(bucketKey, deferredBucket);
_deferredBucketOrder.Add(bucketKey);
}
else if (!deferredBucket.Contains(operation.Key))
{
deferredBucket.Add(operation.Key);
}
}
receipt = new RuntimeDormantSetPositionCommitReceipt(
RuntimeDormantSetPositionCommitStatus.DeferredCell,
operation.Key,
operation.Token.OperationId,
default,
default,
deferredShadowReceipt,
prepared.Evaluation.CollisionAuthority,
operation.Record.VectorAuthorityVersion,
HitGround: false,
LeaveGround: false);
return true;
}
if (prepared.Collision is null
|| !_physics.CollisionReports.TryInstallSetPositionBatch(
prepared.Collision,
out RuntimeCollisionReportingState
.SetPositionCollisionBatchReceipt collisionReceipt))
{
return false;
}
if (!result.IsCommitted)
{
operation.Result = result;
receipt = new RuntimeDormantSetPositionCommitReceipt(
RuntimeDormantSetPositionCommitStatus.RejectedPlacement,
operation.Key,
operation.Token.OperationId,
default,
collisionReceipt,
default,
prepared.Evaluation.CollisionAuthority,
operation.Record.VectorAuthorityVersion,
HitGround: false,
LeaveGround: false);
return true;
}
bool previousOnWalkable = operation.PreviousOnWalkable;
bool hitGround = !previousOnWalkable
&& result.InContact
&& result.OnWalkable;
bool leaveGround = previousOnWalkable
&& !(result.InContact && result.OnWalkable);
UnindexDeferred(operation);
body.Orientation = result.Orientation;
body.StageDormantCellFrame(
result.CellId,
result.Position,
result.CellLocalPosition);
body.LastUpdateTime = prepared.Evaluation.Command.GameTime;
body.ContactPlaneValid = result.InContact;
body.ContactPlane = result.ContactPlane;
body.ContactPlaneCellId = result.ContactPlaneCellId;
body.ContactPlaneIsWater = result.ContactPlaneIsWater;
if (result.InContact)
body.GroundNormal = result.ContactPlane.Normal;
_ = PhysicsObjUpdate.CommitSetPositionContactPrefix(
body,
result.InContact,
result.OnWalkable,
previousOnWalkable);
operation.Result = result;
operation.ExactCellId = result.CellId;
operation.WakeableLostCell = false;
operation.CollisionGenerationReady = false;
operation.EnteringWorldFromCelllessResidence = false;
operation.Stage = RuntimeEntityPlacementStage
.AwaitingFinalShadowPreparation;
receipt = new RuntimeDormantSetPositionCommitReceipt(
RuntimeDormantSetPositionCommitStatus
.AwaitingFinalShadowPreparation,
operation.Key,
operation.Token.OperationId,
prepared.Projection,
collisionReceipt,
default,
prepared.Evaluation.CollisionAuthority,
operation.Record.VectorAuthorityVersion,
hitGround,
leaveGround);
return true;
}
internal SetPositionCollisionBatchDispatchResult
DispatchDormantLocalActivationCollision(
in RuntimeDormantSetPositionCommitReceipt receipt)
{
if (receipt.Status
is RuntimeDormantSetPositionCommitStatus.DeferredCell
or RuntimeDormantSetPositionCommitStatus.RejectedAuthority)
{
return new(
SetPositionCollisionBatchDispatchStatus.RejectedReceipt,
Reported: false);
}
SetPositionCollisionBatchDispatchResult dispatch = _physics
.CollisionReports.DispatchSetPositionBatchResult(receipt.Collision);
bool reported = dispatch.Reported;
if (receipt.Status
is RuntimeDormantSetPositionCommitStatus.RejectedPlacement
&& _operations.TryGetValue(receipt.Entity, out Operation? operation)
&& operation.Token.OperationId == receipt.OperationId
&& IsCurrent(operation)
&& !operation.Result.IsCommitted
&& !operation.Result.IsDeferred)
{
operation.Result = operation.Result with
{
Error = reported
? PhysicsSetPositionError.Collided
: PhysicsSetPositionError.NoValidPosition,
CollisionHandlerResult = reported,
};
}
return dispatch;
}
internal bool IsDormantLocalActivationPrephaseCurrent(
RuntimeEntityRecord record,
PhysicsBody body,
in RuntimeDormantSetPositionCommitReceipt receipt)
{
return receipt.Status is RuntimeDormantSetPositionCommitStatus
.AwaitingFinalShadowPreparation
&& _operations.TryGetValue(receipt.Entity, out Operation? operation)
&& operation.Token.OperationId == receipt.OperationId
&& operation.Stage is RuntimeEntityPlacementStage
.AwaitingFinalShadowPreparation
&& operation.DormantLocalActivation
&& IsCurrent(operation)
&& ReferenceEquals(operation.Record, record)
&& ReferenceEquals(record.PhysicsBody, body)
&& !body.InWorld
&& (body.TransientState & TransientStateFlags.Active) == 0
&& record.PhysicsHost is null
&& record.RemoteMotion is null
&& record.Projectile is null
&& !_physics.IsSpatialRoot(record)
&& _moverPreparationAuthorities.TryGetValue(
receipt.Entity,
out MoverPreparationAuthority authority)
&& authority.OperationId == receipt.OperationId
&& authority.Prepared
&& record.PositionAuthorityVersion
== authority.PositionAuthorityVersion
&& record.ObjDescAuthorityVersion
== authority.ObjDescAuthorityVersion
&& record.CreateIntegrationVersion
== authority.CreateIntegrationVersion
&& CanonicalSetupTableId(record) == authority.SetupTableId;
}
internal bool IsDormantLocalActivationResponseCurrent(
RuntimeEntityRecord record,
PhysicsBody body,
in RuntimeDormantSetPositionCommitReceipt receipt)
{
if (receipt.Status is RuntimeDormantSetPositionCommitStatus
.AwaitingFinalShadowPreparation)
return IsDormantLocalActivationPrephaseCurrent(record, body, receipt);
return receipt.Status is RuntimeDormantSetPositionCommitStatus
.RejectedPlacement
&& _operations.TryGetValue(receipt.Entity, out Operation? operation)
&& operation.Token.OperationId == receipt.OperationId
&& operation.DormantLocalActivation
&& IsCurrent(operation)
&& ReferenceEquals(operation.Record, record)
&& ReferenceEquals(record.PhysicsBody, body)
&& !operation.Result.IsCommitted
&& !operation.Result.IsDeferred
&& !body.InWorld
&& (body.TransientState & TransientStateFlags.Active) == 0
&& record.PhysicsHost is null
&& record.RemoteMotion is null
&& record.Projectile is null
&& !_physics.IsSpatialRoot(record);
}
internal bool CommitDormantLocalActivationPostGround(
RuntimeEntityRecord record,
PhysicsBody body,
in RuntimeDormantSetPositionCommitReceipt receipt)
{
if (!IsDormantLocalActivationPrephaseCurrent(record, body, receipt))
return false;
PhysicsObjUpdate.CommitSetPositionPostGround(body);
PhysicsSetPositionResult result = _operations[receipt.Entity].Result;
body.SlidingNormal = result.SlidingNormal;
if (result.SlidingNormalValid)
body.TransientState |= TransientStateFlags.Sliding;
else
body.TransientState &= ~TransientStateFlags.Sliding;
return IsDormantLocalActivationPrephaseCurrent(record, body, receipt);
}
internal bool CommitDormantLocalActivationPostCollision(
RuntimeEntityRecord record,
PhysicsBody body,
in RuntimeDormantSetPositionCommitReceipt receipt)
{
if (!_operations.TryGetValue(receipt.Entity, out Operation? operation)
|| operation.Token.OperationId != receipt.OperationId
|| !IsCurrent(operation)
|| !ReferenceEquals(operation.Record, record)
|| !ReferenceEquals(record.PhysicsBody, body))
{
return false;
}
if (receipt.Status is RuntimeDormantSetPositionCommitStatus
.AwaitingFinalShadowPreparation
&& !IsDormantLocalActivationPrephaseCurrent(record, body, receipt))
{
return false;
}
PhysicsSetPositionResult result = operation.Result;
body.FramesStationaryFall = result.FramesStationaryFall;
if (IsVelocityCurrent(operation))
{
PhysicsObjUpdate.HandleAllCollisions(
body,
result.CollisionNormalValid,
result.CollisionNormal,
operation.PreviousContact,
operation.PreviousOnWalkable,
body.OnWalkable);
}
CommitStationaryBits(body, result.FramesStationaryFall);
return IsCurrent(operation);
}
internal bool TryPrepareDormantLocalActivationFinalCommit(
RuntimeEntityRecord record,
PhysicsBody body,
in RuntimeDormantSetPositionCommitReceipt receipt,
bool provenShapeless,
out PreparedDormantActivationFinalCommit? prepared)
{
prepared = null;
if (!IsDormantLocalActivationPrephaseCurrent(record, body, receipt)
|| !_operations.TryGetValue(receipt.Entity, out Operation? operation))
{
return false;
}
PhysicsSetPositionResult result = operation.Result;
if (!_physics.Engine.ShadowObjects.TryPrepareSetPosition(
operation.Key.LocalEntityId,
result.Position,
result.Orientation,
result.CellId,
operation.Command.ShadowWorldOffsetX,
operation.Command.ShadowWorldOffsetY,
result.ShadowAction,
result.CrossCellIds,
provenShapeless,
suspendOwner: false,
out ShadowObjectRegistry.PreparedSetPositionShadowCommit? shadow)
|| shadow is null
|| _nextProjectionSequence + 1UL
!= receipt.Projection.Token.Sequence)
{
return false;
}
var pending = new SortedDictionary<
ulong,
RuntimePlacementProjectionSnapshot>(_pendingProjection)
{
[receipt.Projection.Token.Sequence] = receipt.Projection,
};
prepared = new PreparedDormantActivationFinalCommit
{
Entity = receipt.Entity,
OperationId = receipt.OperationId,
ExpectedProjectionSequence = _nextProjectionSequence,
Shadow = shadow,
Projection = receipt.Projection,
PendingProjection = pending,
};
bool current = IsDormantLocalActivationPrephaseCurrent(
record, body, receipt);
bool shadowCurrent = _physics.Engine.ShadowObjects
.IsPreparedSetPositionCurrent(shadow);
return current && shadowCurrent;
}
internal bool TryApplyDormantLocalActivationFinalCommit(
RuntimeEntityRecord record,
PhysicsBody body,
PlayerMovementController controller,
EntityPhysicsHost physicsHost,
in RuntimeDormantSetPositionCommitReceipt prephase,
PreparedDormantActivationFinalCommit prepared,
out RuntimeDormantSetPositionCommitReceipt committed)
{
committed = default;
if (prepared.Entity != prephase.Entity
|| prepared.OperationId != prephase.OperationId
|| prepared.ExpectedProjectionSequence != _nextProjectionSequence
|| prepared.Projection != prephase.Projection
|| !IsDormantLocalActivationPrephaseCurrent(record, body, prephase)
|| !_physics.Engine.ShadowObjects.TryApplySetPosition(
prepared.Shadow,
out ShadowObjectRegistry.SetPositionShadowCommitReceipt shadow))
{
return false;
}
Operation operation = _operations[prephase.Entity];
PhysicsSetPositionResult result = operation.Result;
if (record.FullCellId != result.CellId)
{
_entities.SetFullCell(record, result.CellId,
(result.CellId & 0xFFFF0000u) | 0xFFFFu);
}
operation.SpatialAuthorityVersion = record.SpatialAuthorityVersion;
_entities.AdvancePlacementCommit(record);
operation.PlacementCommitVersion = record.PlacementCommitVersion;
body.InWorld = true;
bool isStatic = (record.FinalPhysicsState & PhysicsStateFlags.Static) != 0;
if (!isStatic)
body.TransientState |= TransientStateFlags.Active;
_entities.SetPhysicsHost(record, physicsHost);
controller.CommitRuntimeActivationFrame();
_physics.Engine.UpdatePlayerCurrCell(result.CellId);
_physics.AcknowledgeSpatialProjection(record, spatial: true);
_entities.ResetObjectClockForEnterWorld(record, isStatic);
operation.Stage = RuntimeEntityPlacementStage.AwaitingCommitAcknowledgement;
operation.ProjectionSequence = prepared.Projection.Token.Sequence;
_pendingProjection = prepared.PendingProjection;
_nextProjectionSequence = prepared.Projection.Token.Sequence;
CancelLostFamilyDeadlines(operation);
controller.ActivateRuntimePublication();
committed = prephase with
{
Status = RuntimeDormantSetPositionCommitStatus.Committed,
Shadow = shadow,
};
return true;
}
internal void DispatchDormantLocalActivationShadow(
in RuntimeDormantSetPositionCommitReceipt receipt)
{
if (receipt.Status is not (
RuntimeDormantSetPositionCommitStatus.Committed
or RuntimeDormantSetPositionCommitStatus.DeferredCell))
return;
_physics.Engine.ShadowObjects.DispatchSetPositionCommit(receipt.Shadow);
}
internal void DispatchDormantLocalActivationPlacement(
in RuntimeDormantSetPositionCommitReceipt receipt)
{
if (!receipt.IsCommitted)
return;
PublishPlacement(receipt.Projection);
}
internal void DiscardDormantLocalActivationDispatches(
in RuntimeDormantSetPositionCommitReceipt receipt,
bool collisionAlreadyDispatched)
{
if (!collisionAlreadyDispatched)
_physics.CollisionReports.DiscardSetPositionBatch(receipt.Collision);
_physics.Engine.ShadowObjects.DiscardSetPositionCommit(receipt.Shadow);
}
internal void RetireDormantLocalActivation(
in RuntimeDormantSetPositionCommitReceipt receipt,
bool collisionAlreadyDispatched)
{
DiscardDormantLocalActivationDispatches(
receipt,
collisionAlreadyDispatched);
_physics.CollisionReports.RetireSetPositionBatchOwner(
receipt.Collision);
if (_operations.TryGetValue(receipt.Entity, out Operation? operation)
&& operation.Token.OperationId == receipt.OperationId)
{
_ = CancelCore(operation);
}
}
internal void RetireDormantLocalActivationToken(
RuntimeEntityRecord record,
in RuntimeEntityPlacementToken token)
{
if (!token.IsValid
|| record.Key != token.Entity
|| !_operations.TryGetValue(token.Entity, out Operation? operation)
|| operation.Token != token
|| !ReferenceEquals(operation.Record, record))
{
return;
}
_ = CancelCore(operation);
}
internal bool IsDormantLocalActivationCommitCurrent(
RuntimeEntityRecord record,
PhysicsBody body,
in RuntimeDormantSetPositionCommitReceipt receipt)
{
if (!receipt.IsCommitted
|| !receipt.Projection.Token.IsValid
|| record.Key != receipt.Projection.Token.Entity
|| !ReferenceEquals(record.PhysicsBody, body)
|| !_pendingProjection.TryGetValue(
receipt.Projection.Token.Sequence,
out RuntimePlacementProjectionSnapshot pending)
|| pending != receipt.Projection
|| !_operations.TryGetValue(
receipt.Projection.Token.Entity,
out Operation? operation)
|| operation.Stage is not RuntimeEntityPlacementStage
.AwaitingCommitAcknowledgement
|| operation.ProjectionSequence
!= receipt.Projection.Token.Sequence
|| !IsCurrent(operation)
|| !body.InWorld
|| !_physics.IsSpatialRoot(record))
{
return false;
}
return true;
}
internal bool TryCaptureDormantLocalActivationResult(
in RuntimeEntityPlacementToken token,
out PhysicsSetPositionResult result)
{
if (!_disposed
&& token.IsValid
&& _operations.TryGetValue(token.Entity, out Operation? operation)
&& operation.Token == token)
{
result = operation.Result;
return true;
}
result = default;
return false;
}
private bool IsPreparedDormantCommitCurrent(
RuntimeEntityRecord record,
PhysicsBody body,
PreparedDormantSetPositionCommit prepared)
{
if (_nextProjectionSequence != prepared.ExpectedProjectionSequence
|| !IsDormantLocalEvaluationCurrent(
record,
body,
prepared.Evaluation)
|| !_operations.TryGetValue(
prepared.Entity,
out Operation? operation)
|| operation.Token.OperationId != prepared.OperationId)
{
return false;
}
if (prepared.Collision is not null
&& !_physics.CollisionReports.IsPreparedSetPositionBatchCurrent(
prepared.Collision))
return false;
return prepared.Shadow is null
|| _physics.Engine.ShadowObjects.IsPreparedSetPositionCurrent(
prepared.Shadow);
}
private static void CommitStationaryBits(
PhysicsBody body,
int framesStationaryFall)
{
body.TransientState &= ~(TransientStateFlags.StationaryFall
| TransientStateFlags.StationaryStop
| TransientStateFlags.StationaryStuck);
body.TransientState |= framesStationaryFall switch
{
1 => TransientStateFlags.StationaryFall,
2 => TransientStateFlags.StationaryStop,
3 => TransientStateFlags.StationaryStuck,
_ => TransientStateFlags.None,
};
}
internal RuntimeSetPositionOutcome SubmitPreparedPlacement(
in RuntimeEntityPlacementToken token,
in RuntimeSetPositionCommand command) =>
@ -1559,6 +2412,12 @@ internal sealed class RuntimeSetPositionState : IDisposable
private void RetryDeferred(Operation operation)
{
// The local-player activation lease owns its dormant body/controller
// and must re-enter through the same sealed evaluation/commit path.
// A collision-generation wake only marks readiness; it must never
// bypass that path through the ordinary remote CommitCanonical tail.
if (operation.DormantLocalActivation)
return;
if (!IsCurrent(operation)
|| !operation.WakeableLostCell
|| operation.RequiresPreparation
@ -2006,7 +2865,8 @@ internal sealed class RuntimeSetPositionState : IDisposable
in RuntimeEntityPlacementToken token,
in RuntimeSetPositionCommand command,
out Operation? operation,
bool allowCanonicalCommand = false)
bool allowCanonicalCommand = false,
bool allowDeferredLease = false)
{
operation = null;
if (!token.IsValid
@ -2021,6 +2881,14 @@ internal sealed class RuntimeSetPositionState : IDisposable
|| operation.Token != token
|| operation.Stage
is not RuntimeEntityPlacementStage.AwaitingPreparation
&& !(allowDeferredLease
&& operation.DormantLocalActivation
&& (operation.Stage
is RuntimeEntityPlacementStage.AwaitingCell
&& operation.WakeableLostCell
|| operation.Stage is RuntimeEntityPlacementStage
.AwaitingFinalShadowPreparation)
&& operation.ProjectionSequence == 0UL)
|| !ReferenceEquals(operation.Record, record)
|| !IsCurrent(operation)
|| !ReferenceEquals(record.PhysicsBody, body)