feat(runtime): own initial create residence transaction
This commit is contained in:
parent
74103f75b5
commit
38fd4b8dc9
10 changed files with 3031 additions and 17 deletions
|
|
@ -180,6 +180,9 @@ internal static class RuntimeAuthoritativePositionRouteClassifier
|
|||
| PhysicsSetPositionFlags.Slide
|
||||
| PhysicsSetPositionFlags.SendPositionEvent;
|
||||
|
||||
internal static bool IsValidCreateWirePosition(
|
||||
in CreateObject.ServerPosition position) => ValidPosition(position);
|
||||
|
||||
internal static RuntimeAuthoritativePositionRoute ClassifyCreate(
|
||||
in RuntimeCreatePositionRouteRequest request)
|
||||
{
|
||||
|
|
@ -205,7 +208,10 @@ internal static class RuntimeAuthoritativePositionRouteClassifier
|
|||
0u,
|
||||
UnparentBeforeRouting: false,
|
||||
ApplyPlacementFrameBeforeRouting: false,
|
||||
LeaveWorld: true,
|
||||
// A fresh cellless CreateObject has never entered world.
|
||||
// Parent composition and later pickup events own their own
|
||||
// callbacks; initial residence invents no withdrawal edge.
|
||||
LeaveWorld: false,
|
||||
TeleportHookPhase: RuntimeTeleportHookPhase.None,
|
||||
StopInterpolating: false,
|
||||
ConstrainAfterRouting: false,
|
||||
|
|
@ -294,7 +300,7 @@ internal static class RuntimeAuthoritativePositionRouteClassifier
|
|||
{
|
||||
return new RuntimeAuthoritativePositionRoute(
|
||||
request.Authority,
|
||||
RuntimeAuthoritativePositionDisposition.SetPosition,
|
||||
RuntimeAuthoritativePositionDisposition.SetPositionSimple,
|
||||
operation,
|
||||
AuthoritativeTeleportFlags,
|
||||
placement,
|
||||
|
|
|
|||
|
|
@ -250,6 +250,8 @@ internal readonly record struct RuntimeSetPositionOwnershipSnapshot(
|
|||
int UnboundDeferredCellOrderCount,
|
||||
int PreparedMoverCount,
|
||||
int MoverPreparationAuthorityCount,
|
||||
int PlacementCompletionWatchCount,
|
||||
int AcknowledgedPlacementCompletionCount,
|
||||
int CollisionPrefixQuiescenceCount,
|
||||
int PendingQuiescenceProjectionCount)
|
||||
{
|
||||
|
|
@ -276,6 +278,8 @@ internal readonly record struct RuntimeSetPositionOwnershipSnapshot(
|
|||
&& UnboundDeferredCellOrderCount == 0
|
||||
&& PreparedMoverCount == 0
|
||||
&& MoverPreparationAuthorityCount == 0
|
||||
&& PlacementCompletionWatchCount == 0
|
||||
&& AcknowledgedPlacementCompletionCount == 0
|
||||
&& CollisionPrefixQuiescenceCount == 0
|
||||
&& PendingQuiescenceProjectionCount == 0;
|
||||
}
|
||||
|
|
@ -414,6 +418,10 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
_preparedMovers = [];
|
||||
private readonly Dictionary<RuntimeEntityKey, MoverPreparationAuthority>
|
||||
_moverPreparationAuthorities = [];
|
||||
private readonly HashSet<RuntimeEntityPlacementToken>
|
||||
_placementCompletionWatches = [];
|
||||
private readonly Dictionary<RuntimeEntityPlacementToken,
|
||||
RuntimePlacementProjectionToken> _acknowledgedPlacementCompletions = [];
|
||||
private readonly Dictionary<uint, CollisionPrefixQuiescence>
|
||||
_collisionPrefixQuiescence = [];
|
||||
private readonly LinkedList<RuntimeEntityKey> _expiredLostCells = [];
|
||||
|
|
@ -477,11 +485,15 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
_unboundDeferredCellOrder.Count,
|
||||
_preparedMovers.Count,
|
||||
_moverPreparationAuthorities.Count,
|
||||
_placementCompletionWatches.Count,
|
||||
_acknowledgedPlacementCompletions.Count,
|
||||
_collisionPrefixQuiescence.Count,
|
||||
pendingQuiescenceProjections);
|
||||
}
|
||||
|
||||
internal int PendingProjectionCount => _pendingProjection.Count;
|
||||
internal bool CanBeginAuthoredPlacementSequence =>
|
||||
_nextOperationId != ulong.MaxValue;
|
||||
|
||||
internal bool IsCollisionPrefixQuiescing(uint landblockId) =>
|
||||
_collisionPrefixQuiescence.ContainsKey(
|
||||
|
|
@ -812,6 +824,111 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
portal,
|
||||
captureMoverPreparationAuthority: true);
|
||||
|
||||
internal bool IsPlacementCurrent(
|
||||
in RuntimeEntityPlacementToken token)
|
||||
{
|
||||
EnsureNotDisposed();
|
||||
return token.IsValid
|
||||
&& _operations.TryGetValue(token.Entity, out Operation? operation)
|
||||
&& operation.Token == token
|
||||
&& IsCurrent(operation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reserves the exact acknowledgement edge for a higher-level Runtime
|
||||
/// transaction. Ordinary SetPosition operations retain no completion
|
||||
/// history; only explicitly watched tokens survive operation retirement.
|
||||
/// </summary>
|
||||
internal bool WatchPlacementCompletion(
|
||||
in RuntimeEntityPlacementToken token)
|
||||
{
|
||||
EnsureNotDisposed();
|
||||
return IsPlacementCurrent(token)
|
||||
&& _placementCompletionWatches.Add(token);
|
||||
}
|
||||
|
||||
internal bool IsPlacementCompletionTracked(
|
||||
in RuntimeEntityPlacementToken token)
|
||||
{
|
||||
EnsureNotDisposed();
|
||||
return token.IsValid
|
||||
&& (IsPlacementCurrent(token)
|
||||
&& _placementCompletionWatches.Contains(token)
|
||||
|| _acknowledgedPlacementCompletions.ContainsKey(token));
|
||||
}
|
||||
|
||||
internal bool TryPeekAcknowledgedPlacement(
|
||||
in RuntimeEntityPlacementToken token,
|
||||
out RuntimePlacementProjectionToken projection)
|
||||
{
|
||||
EnsureNotDisposed();
|
||||
if (token.IsValid
|
||||
&& _acknowledgedPlacementCompletions.TryGetValue(
|
||||
token,
|
||||
out projection))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
projection = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal bool ConsumeAcknowledgedPlacement(
|
||||
in RuntimeEntityPlacementToken token,
|
||||
in RuntimePlacementProjectionToken expected)
|
||||
{
|
||||
EnsureNotDisposed();
|
||||
return token.IsValid
|
||||
&& _acknowledgedPlacementCompletions.TryGetValue(
|
||||
token,
|
||||
out RuntimePlacementProjectionToken current)
|
||||
&& current == expected
|
||||
&& _acknowledgedPlacementCompletions.Remove(token);
|
||||
}
|
||||
|
||||
internal void ForgetPlacementCompletion(
|
||||
in RuntimeEntityPlacementToken token)
|
||||
{
|
||||
EnsureNotDisposed();
|
||||
ForgetPlacementCompletionCore(token);
|
||||
}
|
||||
|
||||
internal RuntimePlacementCancellationReceipt ForgetExactPlacement(
|
||||
in RuntimeEntityPlacementToken token)
|
||||
{
|
||||
EnsureNotDisposed();
|
||||
ForgetPlacementCompletionCore(token);
|
||||
if (!token.IsValid
|
||||
|| !_operations.TryGetValue(token.Entity, out Operation? operation)
|
||||
|| operation.Token != token)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
return CancelCore(operation);
|
||||
}
|
||||
|
||||
internal RuntimeEntityPlacementToken TryBeginExclusiveAuthoredPlacement(
|
||||
RuntimeEntityRecord record,
|
||||
ulong expectedPositionAuthorityVersion,
|
||||
RuntimeSetPositionOperationKind kind,
|
||||
RuntimePortalPlacementAuthority portal = default)
|
||||
{
|
||||
EnsureNotDisposed();
|
||||
ArgumentNullException.ThrowIfNull(record);
|
||||
if (record.Key is not { } key
|
||||
|| _operations.ContainsKey(key)
|
||||
|| HasRetainedCompletion(key))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
return BeginAcceptedPlacementCore(
|
||||
record,
|
||||
expectedPositionAuthorityVersion,
|
||||
kind,
|
||||
portal,
|
||||
captureMoverPreparationAuthority: true);
|
||||
}
|
||||
|
||||
internal void PrepareDormantLocalActivationOwnership(
|
||||
RuntimeEntityRecord record,
|
||||
PhysicsBody body,
|
||||
|
|
@ -853,6 +970,7 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
record.Snapshot.Physics?.Position ?? record.Snapshot.Position;
|
||||
if (record.Key is not { } key
|
||||
|| !_entities.IsCurrent(record)
|
||||
|| HasRetainedCompletion(key)
|
||||
|| record.PositionAuthorityVersion
|
||||
!= expectedPositionAuthorityVersion
|
||||
|| (captureMoverPreparationAuthority
|
||||
|
|
@ -947,6 +1065,17 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
return IsCurrent(replacement) ? token : default;
|
||||
}
|
||||
|
||||
private bool HasRetainedCompletion(RuntimeEntityKey key)
|
||||
{
|
||||
foreach (RuntimeEntityPlacementToken token
|
||||
in _acknowledgedPlacementCompletions.Keys)
|
||||
{
|
||||
if (token.Entity == key)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
internal RuntimeSetPositionMoverPreparationStatus PrepareMover(
|
||||
in RuntimeEntityPlacementToken token,
|
||||
in RuntimeSetPositionMoverPreparation preparation,
|
||||
|
|
@ -2206,6 +2335,12 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
operation.ProjectionSequence = 0UL;
|
||||
if (pending.Kind is RuntimePlacementProjectionKind.Place)
|
||||
{
|
||||
if (_placementCompletionWatches.Remove(operation.Token))
|
||||
{
|
||||
_acknowledgedPlacementCompletions.Add(
|
||||
operation.Token,
|
||||
pending.Token);
|
||||
}
|
||||
operation.Stage = RuntimeEntityPlacementStage.AwaitingCommitAcknowledgement;
|
||||
_moverPreparationAuthorities.Remove(operation.Key);
|
||||
return _operations.Remove(operation.Key);
|
||||
|
|
@ -3041,6 +3176,8 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
_lostDeadlineNodeIndex.Clear();
|
||||
_preparedMovers.Clear();
|
||||
_moverPreparationAuthorities.Clear();
|
||||
_placementCompletionWatches.Clear();
|
||||
_acknowledgedPlacementCompletions.Clear();
|
||||
_collisionPrefixQuiescence.Clear();
|
||||
_pendingProjection.Clear();
|
||||
_expiredLostCells.Clear();
|
||||
|
|
@ -3859,6 +3996,7 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
CancelExactLostKey(key);
|
||||
if (!_operations.Remove(key, out Operation? operation))
|
||||
return false;
|
||||
ForgetPlacementCompletionCore(operation.Token);
|
||||
_moverPreparationAuthorities.Remove(key);
|
||||
UnindexDeferred(operation);
|
||||
if (!preserveLostFamily && cancelLostFamily)
|
||||
|
|
@ -3929,6 +4067,15 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
: default;
|
||||
}
|
||||
|
||||
private void ForgetPlacementCompletionCore(
|
||||
in RuntimeEntityPlacementToken token)
|
||||
{
|
||||
if (!token.IsValid)
|
||||
return;
|
||||
_placementCompletionWatches.Remove(token);
|
||||
_acknowledgedPlacementCompletions.Remove(token);
|
||||
}
|
||||
|
||||
private void IndexDeferred(Operation operation)
|
||||
{
|
||||
if (operation.ExactCellId == 0u
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue