86 lines
3.8 KiB
C#
86 lines
3.8 KiB
C#
using System.Collections.Concurrent;
|
|
using AcDream.Core.World.Cells;
|
|
|
|
namespace AcDream.Core.Physics;
|
|
|
|
/// <summary>
|
|
/// One exclusive-by-ownership collision-world root. A preparation mutates only
|
|
/// its private root; activation transfers the complete root through one volatile
|
|
/// reference publication shared by every collision facade.
|
|
/// </summary>
|
|
internal sealed class CollisionWorldState
|
|
{
|
|
internal Dictionary<uint, PhysicsEngine.LandblockPhysics> Landblocks { get; } = new();
|
|
internal List<uint> LandblockSlots { get; } = new();
|
|
internal Dictionary<uint, int> LandblockIndices { get; } = new();
|
|
internal Stack<int> LandblockFreeSlots { get; } = new();
|
|
internal ConcurrentDictionary<uint, CellPhysics> CellStruct { get; } = new();
|
|
internal ConcurrentDictionary<uint, FlatCellStructureCollisionAsset>
|
|
FlatCellStruct { get; } = new();
|
|
internal ConcurrentDictionary<uint, FlatEnvCellTopology> FlatEnvCell { get; } = new();
|
|
internal ConcurrentDictionary<uint, BuildingPhysics> Buildings { get; } = new();
|
|
internal ConcurrentDictionary<uint, EnvCell> EnvCells { get; } = new();
|
|
internal ConcurrentDictionary<uint, CellGraphTerrain> Terrain { get; } = new();
|
|
internal ConcurrentDictionary<uint, ObjCell> OutdoorCells { get; } = new();
|
|
internal Dictionary<uint, List<ShadowEntry>> ShadowCells { get; } = new();
|
|
internal Dictionary<uint, List<uint>> ShadowEntityCells { get; } = new();
|
|
internal HashSet<uint> SuspendedShadowEntities { get; } = new();
|
|
internal Dictionary<uint, HashSet<uint>> WithdrawnPrefixesByOwner { get; } = new();
|
|
internal Dictionary<uint, IReadOnlyList<ShadowShape>> ShadowEntityShapes { get; } = new();
|
|
internal Dictionary<uint, ShadowObjectRegistry.RegistrationRecord>
|
|
ShadowEntityRegistrations { get; } = new();
|
|
internal Dictionary<uint, ulong> ShadowOwnerVersions { get; } = new();
|
|
internal Dictionary<uint, HashSet<uint>> ShadowOwnerPrefixes { get; } = new();
|
|
internal Dictionary<uint, List<uint>> ShadowPrefixOwnerSlots { get; } = new();
|
|
internal Dictionary<uint, Dictionary<uint, int>> ShadowPrefixOwnerIndices { get; } = new();
|
|
internal Dictionary<uint, Stack<int>> ShadowPrefixFreeSlots { get; } = new();
|
|
internal List<uint> ShadowOwnerSlots { get; } = new();
|
|
internal Dictionary<uint, int> ShadowOwnerIndices { get; } = new();
|
|
internal Stack<int> ShadowOwnerFreeSlots { get; } = new();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stable indirection shared by PhysicsEngine, PhysicsDataCache, CellGraph,
|
|
/// and ShadowObjectRegistry. Readers observe either complete root, never a
|
|
/// mixture assembled by several facade assignments.
|
|
/// </summary>
|
|
internal sealed class CollisionWorldStateSlot
|
|
{
|
|
private CollisionWorldState? _current = new();
|
|
private bool _revoked;
|
|
|
|
internal CollisionWorldStateSlot()
|
|
{
|
|
}
|
|
|
|
internal CollisionWorldStateSlot(CollisionWorldState current)
|
|
{
|
|
_current = current ?? throw new ArgumentNullException(nameof(current));
|
|
}
|
|
|
|
internal CollisionWorldState Current
|
|
{
|
|
get
|
|
{
|
|
if (_revoked)
|
|
throw new ObjectDisposedException("Transferred collision generation");
|
|
return Volatile.Read(ref _current)
|
|
?? throw new ObjectDisposedException("Transferred collision generation");
|
|
}
|
|
}
|
|
|
|
internal CollisionWorldState TransferTo(CollisionWorldStateSlot destination)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(destination);
|
|
if (_revoked)
|
|
throw new ObjectDisposedException("Transferred collision generation");
|
|
CollisionWorldState transferred = _current
|
|
?? throw new ObjectDisposedException("Transferred collision generation");
|
|
_revoked = true;
|
|
Volatile.Write(ref destination._current, transferred);
|
|
_current = null;
|
|
return transferred;
|
|
}
|
|
|
|
internal CollisionWorldState Capture() => Current;
|
|
}
|