feat(runtime): seal dormant SetPosition evaluations
This commit is contained in:
parent
22651c823d
commit
99f867f053
16 changed files with 2298 additions and 62 deletions
|
|
@ -1,3 +1,5 @@
|
|||
using System.Collections.Immutable;
|
||||
using AcDream.Core.Items;
|
||||
using AcDream.Core.Physics;
|
||||
using AcDream.Runtime.Entities;
|
||||
|
||||
|
|
@ -1042,6 +1044,7 @@ public sealed class RuntimePhysicsState : IDisposable
|
|||
private bool _suppressCollisionOwnerJournal;
|
||||
private long _nextCollisionPreparationSequence;
|
||||
private long _latestCollisionPreparationStartSequence;
|
||||
private ulong _collisionWorldAuthority = 1UL;
|
||||
private readonly List<Action<RuntimeCollisionGenerationCommitted>>
|
||||
_collisionGenerationCommittedObservers = new();
|
||||
private bool _disposed;
|
||||
|
|
@ -1898,6 +1901,7 @@ public sealed class RuntimePhysicsState : IDisposable
|
|||
EnsureNotDisposed();
|
||||
EnsureCollisionMutationThread();
|
||||
uint canonical = CanonicalLandblock(landblockId);
|
||||
AdvanceCollisionWorldAuthority();
|
||||
if (_collisionAdmissions.Remove(
|
||||
canonical,
|
||||
out RuntimeCollisionAdmission? superseded))
|
||||
|
|
@ -2013,6 +2017,7 @@ public sealed class RuntimePhysicsState : IDisposable
|
|||
admission.Generation);
|
||||
_collisionGenerations[admission.LandblockId] = checked(
|
||||
admission.Generation + 1UL);
|
||||
AdvanceCollisionWorldAuthority();
|
||||
}
|
||||
TrimCollisionOwnerJournal();
|
||||
}
|
||||
|
|
@ -2226,6 +2231,7 @@ public sealed class RuntimePhysicsState : IDisposable
|
|||
try
|
||||
{
|
||||
Engine.CommitLandblockReplacement(replacement);
|
||||
AdvanceCollisionWorldAuthority();
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
@ -2496,6 +2502,7 @@ public sealed class RuntimePhysicsState : IDisposable
|
|||
|
||||
private void InvalidateCollisionAdmission(uint landblockId)
|
||||
{
|
||||
AdvanceCollisionWorldAuthority();
|
||||
ulong currentGeneration = _collisionGenerations.TryGetValue(
|
||||
landblockId,
|
||||
out ulong current)
|
||||
|
|
@ -2540,6 +2547,130 @@ public sealed class RuntimePhysicsState : IDisposable
|
|||
: 1UL;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exact collision-prefix generation authority used by private
|
||||
/// SetPosition evaluations. Beginning a replacement generation advances
|
||||
/// this authority immediately, so a receipt cannot survive a prepared
|
||||
/// world replacement and later observe different collision rows.
|
||||
/// </summary>
|
||||
internal ulong CollisionGenerationAuthority(uint exactCellId)
|
||||
{
|
||||
uint landblockId = CanonicalLandblock(exactCellId);
|
||||
return landblockId != 0u
|
||||
&& _collisionGenerations.TryGetValue(
|
||||
landblockId,
|
||||
out ulong generation)
|
||||
? generation
|
||||
: 0UL;
|
||||
}
|
||||
|
||||
internal ulong CollisionWorldAuthority => _collisionWorldAuthority;
|
||||
|
||||
internal ulong ShadowWorldAuthority =>
|
||||
Engine.ShadowObjects.MutationRevision;
|
||||
|
||||
internal ClientObjectTable? ObjectTable => Engine.Objects;
|
||||
|
||||
internal ulong ObjectTableBindingAuthority =>
|
||||
Engine.ObjectsBindingRevision;
|
||||
|
||||
internal ulong ObjectTableAuthority =>
|
||||
ObjectTable?.MutationRevision ?? 0UL;
|
||||
|
||||
private void AdvanceCollisionWorldAuthority() =>
|
||||
_collisionWorldAuthority = checked(_collisionWorldAuthority + 1UL);
|
||||
|
||||
internal bool TrySealCollisionEvaluationAuthority(
|
||||
in PhysicsSetPositionResult result,
|
||||
ulong expectedCollisionWorldAuthority,
|
||||
ulong expectedShadowWorldAuthority,
|
||||
ClientObjectTable? expectedObjectTable,
|
||||
ulong expectedObjectTableBindingAuthority,
|
||||
ulong expectedObjectTableAuthority,
|
||||
out RuntimeCollisionEvaluationAuthority authority)
|
||||
{
|
||||
authority = default;
|
||||
if (_collisionWorldAuthority != expectedCollisionWorldAuthority
|
||||
|| ShadowWorldAuthority != expectedShadowWorldAuthority
|
||||
|| !ReferenceEquals(ObjectTable, expectedObjectTable)
|
||||
|| ObjectTableBindingAuthority
|
||||
!= expectedObjectTableBindingAuthority
|
||||
|| ObjectTableAuthority != expectedObjectTableAuthority)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var prefixes = new HashSet<uint>();
|
||||
var authorities = ImmutableArray.CreateBuilder<
|
||||
RuntimeCollisionGenerationAuthority>();
|
||||
void Add(uint cellId)
|
||||
{
|
||||
uint landblock = CanonicalLandblock(cellId);
|
||||
if (landblock == 0u || !prefixes.Add(landblock))
|
||||
return;
|
||||
authorities.Add(new RuntimeCollisionGenerationAuthority(
|
||||
landblock,
|
||||
CollisionGenerationAuthority(landblock)));
|
||||
}
|
||||
|
||||
Add(result.CellId);
|
||||
if (!result.QueriedCellIds.IsDefaultOrEmpty)
|
||||
{
|
||||
foreach (uint cellId in result.QueriedCellIds)
|
||||
Add(cellId);
|
||||
}
|
||||
foreach (uint prefix in prefixes)
|
||||
{
|
||||
if (_collisionAdmissions.ContainsKey(prefix))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_collisionWorldAuthority != expectedCollisionWorldAuthority
|
||||
|| ShadowWorldAuthority != expectedShadowWorldAuthority
|
||||
|| !ReferenceEquals(ObjectTable, expectedObjectTable)
|
||||
|| ObjectTableBindingAuthority
|
||||
!= expectedObjectTableBindingAuthority
|
||||
|| ObjectTableAuthority != expectedObjectTableAuthority)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
authority = new RuntimeCollisionEvaluationAuthority(
|
||||
expectedCollisionWorldAuthority,
|
||||
expectedShadowWorldAuthority,
|
||||
expectedObjectTable,
|
||||
expectedObjectTableBindingAuthority,
|
||||
expectedObjectTableAuthority,
|
||||
authorities.ToImmutable());
|
||||
return true;
|
||||
}
|
||||
|
||||
internal bool IsCollisionEvaluationAuthorityCurrent(
|
||||
in RuntimeCollisionEvaluationAuthority authority)
|
||||
{
|
||||
if (!authority.IsValid
|
||||
|| _collisionWorldAuthority != authority.CollisionWorldAuthority
|
||||
|| ShadowWorldAuthority != authority.ShadowWorldAuthority
|
||||
|| !ReferenceEquals(ObjectTable, authority.ObjectTable)
|
||||
|| ObjectTableBindingAuthority
|
||||
!= authority.ObjectTableBindingAuthority
|
||||
|| ObjectTableAuthority != authority.ObjectTableAuthority)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
foreach (RuntimeCollisionGenerationAuthority generation
|
||||
in authority.Generations)
|
||||
{
|
||||
if (generation.LandblockId == 0u
|
||||
|| _collisionAdmissions.ContainsKey(generation.LandblockId)
|
||||
|| CollisionGenerationAuthority(generation.LandblockId)
|
||||
!= generation.Generation)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
internal bool HandleSetPositionCollisions(
|
||||
RuntimeEntityRecord record,
|
||||
ulong positionAuthorityVersion,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue