< Summary

Information
Class: GridForge.Grids.Voxel
Assembly: GridForge
File(s): /home/runner/work/GridForge/GridForge/src/GridForge/Grids/Nodes/Voxel.cs
Line coverage
100%
Covered lines: 208
Uncovered lines: 0
Coverable lines: 208
Total lines: 626
Line coverage: 100%
Branch coverage
100%
Covered branches: 98
Total branches: 98
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/GridForge/GridForge/src/GridForge/Grids/Nodes/Voxel.cs

#LineLine coverage
 1//=======================================================================
 2// Voxel.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024–present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System;
 9using System.Runtime.CompilerServices;
 10using FixedMathSharp;
 11using GridForge.Grids.Topology;
 12using GridForge.Spatial;
 13using SwiftCollections;
 14using SwiftCollections.Pool;
 15
 16namespace GridForge.Grids;
 17
 18/// <summary>
 19/// Represents a voxel within a 3D grid, handling spatial positioning, obstacles, occupants, and neighbor relationships.
 20/// </summary>
 21public class Voxel : IEquatable<Voxel>
 22{
 23    #region Properties & Fields
 24
 25    /// <summary>
 26    /// The world-scoped runtime identity of this voxel within the grid system.
 27    /// </summary>
 28    public WorldVoxelIndex WorldIndex { get; set; }
 29
 30    /// <summary>
 31    /// The world-local index of the grid this voxel belongs to.
 32    /// </summary>
 5333    public ushort GridIndex => WorldIndex.GridIndex;
 34
 35    /// <summary>
 36    /// The local coordinates of this voxel within its grid.
 37    /// </summary>
 1102238    public VoxelIndex Index => WorldIndex.VoxelIndex;
 39
 40    /// <summary>
 41    /// The grid-local key of the scan cell that this voxel belongs to.
 42    /// </summary>
 43    public int ScanCellKey { get; private set; }
 44
 45    /// <summary>
 46    /// The world-space position of this voxel.
 47    /// </summary>
 48    public Vector3d WorldPosition { get; private set; }
 49
 50    /// <summary>
 51    /// Stores the process-unique identity of each obstacle registration added to this voxel.
 52    /// </summary>
 53    public SwiftHashSet<ObstacleToken>? ObstacleTracker { get; internal set; }
 54
 55    /// <summary>
 56    /// The current number of obstacles on this voxel.
 57    /// </summary>
 58    public byte ObstacleCount { get; internal set; }
 59
 60    /// <summary>
 61    /// The current number of occupants on this voxel.
 62    /// </summary>
 63    public byte OccupantCount { get; internal set; }
 64
 65    /// <summary>
 66    /// Handles management of partitioned data.
 67    /// </summary>
 10807268    private readonly PartitionProvider<IVoxelPartition> _partitionProvider = new();
 69
 70    /// <summary>
 71    /// Indicates whether this voxel has any active partitions.
 72    /// </summary>
 880673    public bool IsPartioned => !_partitionProvider.IsEmpty;
 74
 10807275    private readonly object _partitionLock = new();
 76
 77    /// <summary>
 78    /// Determines if this voxel is a boundary voxel.
 79    /// </summary>
 80    public bool IsBoundaryVoxel { get; private set; }
 81
 82    /// <summary>
 83    /// The current version of the grid at the time this voxel was created.
 84    /// </summary>
 85    public uint CachedGridVersion { get; internal set; }
 86
 87    /// <summary>
 88    /// Indicates whether this voxel is allocated within a grid.
 89    /// </summary>
 90    public bool IsAllocated { get; private set; }
 91
 92    /// <summary>
 93    /// Determines whether this voxel is blocked due to obstacles.
 94    /// </summary>
 1841495    public bool IsBlocked => IsAllocated && ObstacleCount > 0;
 96
 97    /// <summary>
 98    /// Determines if this voxel can accept additional obstacles.
 99    /// </summary>
 1084100    public bool IsBlockable => IsAllocated
 1084101        && ObstacleCount < GridObstacleManager.MaxObstacleCount
 1084102        && !IsOccupied;
 103
 104    /// <summary>
 105    /// Determines whether this voxel is occupied by entities.
 106    /// </summary>
 18825107    public bool IsOccupied => IsAllocated && OccupantCount > 0;
 108
 109    /// <summary>
 110    /// Checks if this voxel has open slots for new occupants.
 111    /// </summary>
 739112    public bool HasVacancy => !IsBlocked && OccupantCount < GridOccupantManager.MaxOccupantCount;
 113
 114    internal bool HasEventSubscribers =>
 13115        _onObstacleAdded != null
 13116        || _onObstacleRemoved != null
 13117        || _onObstaclesCleared != null
 13118        || _onOccupantAdded != null
 13119        || _onOccupantRemoved != null;
 120
 121    #endregion
 122
 123    #region Events
 124
 125    /// <summary>
 126    /// Event triggered when an obstacle is added.
 127    /// </summary>
 128    private Action<ObstacleEventInfo>? _onObstacleAdded;
 129
 130    /// <inheritdoc cref="_onObstacleAdded"/>
 131    public event Action<ObstacleEventInfo> OnObstacleAdded
 132    {
 3133        add => _onObstacleAdded += value;
 3134        remove => _onObstacleAdded -= value;
 135    }
 136
 137    /// <summary>
 138    /// Event triggered when an obstacle is removed.
 139    /// </summary>
 140    private Action<ObstacleEventInfo>? _onObstacleRemoved;
 141
 142    /// <inheritdoc cref="_onObstacleRemoved"/>
 143    public event Action<ObstacleEventInfo> OnObstacleRemoved
 144    {
 2145        add => _onObstacleRemoved += value;
 2146        remove => _onObstacleRemoved -= value;
 147    }
 148
 149    /// <summary>
 150    /// Event triggered when all obstacles on the voxel are cleared at once.
 151    /// </summary>
 152    private Action<ObstacleClearEventInfo>? _onObstaclesCleared;
 153
 154    /// <inheritdoc cref="_onObstaclesCleared"/>
 155    public event Action<ObstacleClearEventInfo> OnObstaclesCleared
 156    {
 2157        add => _onObstaclesCleared += value;
 2158        remove => _onObstaclesCleared -= value;
 159    }
 160
 161    /// <summary>
 162    /// Event triggered when an occupant is added.
 163    /// </summary>
 164    private Action<OccupantEventInfo>? _onOccupantAdded;
 165
 166    /// <inheritdoc cref="_onOccupantAdded"/>
 167    public event Action<OccupantEventInfo> OnOccupantAdded
 168    {
 2169        add => _onOccupantAdded += value;
 2170        remove => _onOccupantAdded -= value;
 171    }
 172
 173    /// <summary>
 174    /// Event triggered when an occupant is removed.
 175    /// </summary>
 176    private Action<OccupantEventInfo>? _onOccupantRemoved;
 177
 178    /// <inheritdoc cref="_onOccupantRemoved"/>
 179    public event Action<OccupantEventInfo> OnOccupantRemoved
 180    {
 2181        add => _onOccupantRemoved += value;
 2182        remove => _onOccupantRemoved -= value;
 183    }
 184
 185    #endregion
 186
 187    #region Initialization & Reset
 188
 189    /// <summary>
 190    /// Configures the voxel with its position, grid version, and boundary status.
 191    /// </summary>
 192    internal void Initialize(
 193        WorldVoxelIndex worldVoxelIndex,
 194        Vector3d worldPosition,
 195        int scanCellKey,
 196        bool isBoundaryVoxel,
 197        uint gridVersion)
 198    {
 122222199        ScanCellKey = scanCellKey;
 122222200        IsBoundaryVoxel = isBoundaryVoxel;
 201
 122222202        WorldIndex = worldVoxelIndex;
 122222203        WorldPosition = worldPosition;
 204
 122222205        CachedGridVersion = gridVersion;
 122222206        IsAllocated = true;
 122222207    }
 208
 209    /// <summary>
 210    /// Resets the voxel, clearing all allocated data and returning it to pools.
 211    /// </summary>
 212    internal void Reset(VoxelGrid? ownerGrid = null)
 213    {
 244390214        if (!IsAllocated)
 122187215            return;
 216
 122203217        RemovePartitions();
 122203218        ReleaseObstacleState(ownerGrid);
 122203219        ClearRuntimeState();
 122203220    }
 221
 222    private void RemovePartitions()
 223    {
 122203224        if (!_partitionProvider.IsEmpty)
 225        {
 11226            lock (_partitionLock)
 227            {
 11228                PartitionProvider<IVoxelPartition>.Enumerator partitions = _partitionProvider.GetEnumerator();
 25229                while (partitions.MoveNext())
 230                {
 14231                    IVoxelPartition partition = partitions.Current;
 232                    try
 233                    {
 14234                        partition.OnRemoveFromVoxel(this);
 13235                    }
 1236                    catch (Exception ex)
 237                    {
 1238                        GridForgeLogger.Channel.Error(
 1239                            $"Attempting to call {nameof(partition.OnRemoveFromVoxel)} on {partition.GetType().Name}: {e
 1240                    }
 241                }
 242
 11243                _partitionProvider.Clear();
 11244            }
 245        }
 122203246    }
 247
 248    private void ReleaseObstacleState(VoxelGrid? ownerGrid)
 249    {
 122203250        if (ownerGrid != null && ObstacleCount > 0)
 552251            ownerGrid.ClearObstacles(this);
 121651252        else if (ObstacleTracker != null)
 2253            SwiftHashSetPool<ObstacleToken>.Shared.Release(ObstacleTracker);
 254
 122203255        ObstacleTracker = null;
 122203256        ObstacleCount = 0;
 122203257    }
 258
 259    private void ClearRuntimeState()
 260    {
 122203261        IsBoundaryVoxel = false;
 262
 122203263        ScanCellKey = 0;
 122203264        WorldIndex = default;
 265
 122203266        OccupantCount = 0;
 122203267        _onObstacleAdded = null;
 122203268        _onObstacleRemoved = null;
 122203269        _onObstaclesCleared = null;
 122203270        _onOccupantAdded = null;
 122203271        _onOccupantRemoved = null;
 272
 122203273        IsAllocated = false;
 122203274    }
 275
 276    #endregion
 277
 278    #region Notifications
 279
 280    internal void NotifyObstacleAdded(ObstacleEventInfo eventInfo)
 281    {
 1012282        Action<ObstacleEventInfo>? handlers = _onObstacleAdded;
 1012283        if (handlers == null)
 1010284            return;
 285
 2286        var handlerDelegates = handlers.GetInvocationList();
 12287        for (int i = 0; i < handlerDelegates.Length; i++)
 288        {
 289            try
 290            {
 4291                ((Action<ObstacleEventInfo>)handlerDelegates[i])(eventInfo);
 2292            }
 2293            catch (Exception ex)
 294            {
 2295                GridForgeLogger.Channel.Error($"[Voxel {WorldIndex}] Obstacle add error: {ex.Message}");
 2296            }
 297        }
 2298    }
 299
 300    internal void NotifyObstacleRemoved(ObstacleEventInfo eventInfo)
 301    {
 88302        Action<ObstacleEventInfo>? handlers = _onObstacleRemoved;
 88303        if (handlers == null)
 87304            return;
 305
 1306        var handlerDelegates = handlers.GetInvocationList();
 6307        for (int i = 0; i < handlerDelegates.Length; i++)
 308        {
 309            try
 310            {
 2311                ((Action<ObstacleEventInfo>)handlerDelegates[i])(eventInfo);
 1312            }
 1313            catch (Exception ex)
 314            {
 1315                GridForgeLogger.Channel.Error($"[Voxel {WorldIndex}] Obstacle remove error: {ex.Message}");
 1316            }
 317        }
 1318    }
 319
 320    internal void NotifyObstaclesCleared(ObstacleClearEventInfo eventInfo)
 321    {
 555322        Action<ObstacleClearEventInfo>? handlers = _onObstaclesCleared;
 555323        if (handlers == null)
 554324            return;
 325
 1326        var handlerDelegates = handlers.GetInvocationList();
 6327        for (int i = 0; i < handlerDelegates.Length; i++)
 328        {
 329            try
 330            {
 2331                ((Action<ObstacleClearEventInfo>)handlerDelegates[i])(eventInfo);
 1332            }
 1333            catch (Exception ex)
 334            {
 1335                GridForgeLogger.Channel.Error($"[Voxel {WorldIndex}] Obstacle clear error: {ex.Message}");
 1336            }
 337        }
 1338    }
 339
 340    internal void NotifyOccupantAdded(OccupantEventInfo eventInfo)
 341    {
 669342        Action<OccupantEventInfo>? handlers = _onOccupantAdded;
 669343        if (handlers == null)
 668344            return;
 345
 1346        var handlerDelegates = handlers.GetInvocationList();
 6347        for (int i = 0; i < handlerDelegates.Length; i++)
 348        {
 349            try
 350            {
 2351                ((Action<OccupantEventInfo>)handlerDelegates[i])(eventInfo);
 1352            }
 1353            catch (Exception ex)
 354            {
 1355                GridForgeLogger.Channel.Error($"[Voxel {WorldIndex}] Occupant add error: {ex.Message}");
 1356            }
 357        }
 1358    }
 359
 360    internal void NotifyOccupantRemoved(OccupantEventInfo eventInfo)
 361    {
 155362        Action<OccupantEventInfo>? handlers = _onOccupantRemoved;
 155363        if (handlers == null)
 154364            return;
 365
 1366        var handlerDelegates = handlers.GetInvocationList();
 6367        for (int i = 0; i < handlerDelegates.Length; i++)
 368        {
 369            try
 370            {
 2371                ((Action<OccupantEventInfo>)handlerDelegates[i])(eventInfo);
 1372            }
 1373            catch (Exception ex)
 374            {
 1375                GridForgeLogger.Channel.Error($"[Voxel {WorldIndex}] Occupant remove error: {ex.Message}");
 1376            }
 377        }
 1378    }
 379
 380    #endregion
 381
 382    #region Partition Management
 383
 384    /// <summary>
 385    /// Adds a partition to this voxel, allowing specialized behaviors.
 386    /// </summary>
 387    public bool TryAddPartition(IVoxelPartition partition)
 388    {
 70389        if (partition == null)
 1390            return false;
 391
 69392        Type partitionType = partition.GetType();
 393
 69394        lock (_partitionLock)
 395        {
 69396            if (!_partitionProvider.TryAdd(partitionType, partition))
 2397                return false;
 67398        }
 399
 400        try
 401        {
 67402            partition.SetParentIndex(WorldIndex);
 67403            partition.OnAddToVoxel(this);
 66404            return true;
 405        }
 1406        catch (Exception ex)
 407        {
 1408            lock (_partitionLock)
 1409                _partitionProvider.TryRemove(partitionType, out _);
 410
 1411            string partitionName = partitionType.Name;
 1412            GridForgeLogger.Channel.Error($"Error attempting to attach partition {partitionName}: {ex.Message}");
 1413            return false;
 414        }
 69415    }
 416
 417    /// <summary>
 418    /// Removes a partition from this voxel.
 419    /// </summary>
 420    public bool TryRemovePartition<T>() where T : IVoxelPartition
 421    {
 54422        Type partitionType = typeof(T);
 423
 54424        IVoxelPartition? partition = null;
 54425        lock (_partitionLock)
 54426            _partitionProvider.TryRemove(partitionType, out partition);
 427
 54428        if (partition == null)
 429        {
 2430            string partitionName = partitionType.Name;
 2431            GridForgeLogger.Channel.Warn($"Partition {partitionName} not found on this voxel.");
 2432            return false;
 433        }
 434
 435        try
 436        {
 52437            partition.OnRemoveFromVoxel(this);
 51438        }
 1439        catch (Exception ex)
 440        {
 1441            string partitionName = partitionType.Name;
 1442            GridForgeLogger.Channel.Error($"Attempting to call {nameof(partition.OnRemoveFromVoxel)} on {partitionName}:
 1443        }
 444
 52445        return true;
 446    }
 447
 448    /// <summary>
 449    /// Checks whether or not this voxel contains a specific partition.
 450    /// </summary>
 451    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 452    public bool HasPartition<T>() where T : IVoxelPartition
 453    {
 8454        lock (_partitionLock)
 8455            return _partitionProvider.Has<T>();
 8456    }
 457
 458    /// <summary>
 459    /// Retrieves a partition from the voxel by type.
 460    /// </summary>
 461    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 462    public bool TryGetPartition<T>(out T? partition) where T : IVoxelPartition
 463    {
 1049464        lock (_partitionLock)
 1049465            return _partitionProvider.TryGet(out partition);
 1049466    }
 467
 468    /// <summary>
 469    /// Retrieves a partition from the voxel by type and returns null if it doesn't exist.
 470    /// </summary>
 471    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 472    public T? GetPartitionOrDefault<T>() where T : class, IVoxelPartition
 473    {
 6474        lock (_partitionLock)
 6475            return _partitionProvider.TryGet(out T? partition)
 6476                ? partition
 6477                : null;
 6478    }
 479
 480    #endregion
 481
 482    #region Neighbor Handling
 483
 484    /// <summary>
 485    /// Clears and fills caller-owned storage with neighboring voxels whose
 486    /// world-space voxel footprints touch this voxel's footprint.
 487    /// </summary>
 488    /// <param name="ownerGrid">The active grid that owns this voxel.</param>
 489    /// <param name="results">Caller-owned storage cleared and filled with contact neighbors.</param>
 490    /// <param name="scope">The grid groups included by the contact query.</param>
 491    /// <param name="tolerance">Optional fixed-point tolerance applied to footprint contact checks.</param>
 492    public void GetNeighborsInto(
 493        VoxelGrid ownerGrid,
 494        SwiftList<Voxel> results,
 495        VoxelNeighborScope scope = VoxelNeighborScope.All,
 496        Fixed64? tolerance = null)
 497    {
 31498        SwiftThrowHelper.ThrowIfNull(results, nameof(results));
 499
 31500        results.Clear();
 31501        if (!IsValidOwnerGrid(ownerGrid))
 1502            return;
 503
 30504        VoxelNeighborResolver.AddContactNeighbors(this, ownerGrid, results, scope, tolerance);
 30505    }
 506
 507    /// <summary>
 508    /// Determines whether this voxel has at least one footprint-contact neighbor in the requested scope.
 509    /// </summary>
 510    /// <param name="ownerGrid">The active grid that owns this voxel.</param>
 511    /// <param name="scope">The grid groups included by the contact query.</param>
 512    /// <param name="tolerance">Optional fixed-point tolerance applied to footprint contact checks.</param>
 513    /// <returns>True when at least one contact exists; otherwise false.</returns>
 514    public bool HasNeighbor(
 515        VoxelGrid ownerGrid,
 516        VoxelNeighborScope scope = VoxelNeighborScope.All,
 517        Fixed64? tolerance = null)
 518    {
 10519        if (!IsValidOwnerGrid(ownerGrid))
 1520            return false;
 521
 9522        return VoxelNeighborResolver.HasContactNeighbor(this, ownerGrid, scope, tolerance);
 523    }
 524
 525    /// <summary>
 526    /// Retrieves the rectangular-prism neighbor voxel in the supplied topology-local direction.
 527    /// </summary>
 528    /// <param name="ownerGrid">The active grid that owns this voxel.</param>
 529    /// <param name="direction">The rectangular-prism direction to resolve.</param>
 530    /// <param name="neighbor">The resolved same-topology neighbor when found.</param>
 531    /// <returns>True when a same-topology neighbor exists in the supplied direction; otherwise false.</returns>
 532    public bool TryGetNeighbor(
 533        VoxelGrid ownerGrid,
 534        RectangularDirection direction,
 535        out Voxel? neighbor)
 536    {
 75537        neighbor = null;
 75538        if (!IsValidOwnerGrid(ownerGrid))
 4539            return false;
 540
 71541        return VoxelNeighborResolver.TryGetNeighbor(this, ownerGrid, direction, out neighbor);
 542    }
 543
 544    /// <summary>
 545    /// Retrieves the hex-prism neighbor voxel in the supplied topology-local direction.
 546    /// </summary>
 547    /// <param name="ownerGrid">The active grid that owns this voxel.</param>
 548    /// <param name="direction">The hex-prism direction to resolve.</param>
 549    /// <param name="neighbor">The resolved same-topology neighbor when found.</param>
 550    /// <returns>True when a same-topology neighbor exists in the supplied direction; otherwise false.</returns>
 551    public bool TryGetNeighbor(
 552        VoxelGrid ownerGrid,
 553        HexDirection direction,
 554        out Voxel? neighbor)
 555    {
 6556        neighbor = null;
 6557        if (!IsValidOwnerGrid(ownerGrid))
 1558            return false;
 559
 5560        return VoxelNeighborResolver.TryGetNeighbor(this, ownerGrid, direction, out neighbor);
 561    }
 562
 563    /// <summary>
 564    /// Clears and fills caller-owned storage with rectangular-prism neighbors in deterministic direction order.
 565    /// </summary>
 566    /// <param name="ownerGrid">The active grid that owns this voxel.</param>
 567    /// <param name="results">Caller-owned storage cleared and filled with direction-labeled neighbors.</param>
 568    public void GetRectangularNeighborsInto(
 569        VoxelGrid ownerGrid,
 570        SwiftList<(RectangularDirection Direction, Voxel Voxel)> results)
 571    {
 9572        SwiftThrowHelper.ThrowIfNull(results, nameof(results));
 573
 9574        results.Clear();
 9575        if (!IsValidOwnerGrid(ownerGrid))
 1576            return;
 577
 8578        VoxelNeighborResolver.AddRectangularNeighbors(this, ownerGrid, results);
 8579    }
 580
 581    /// <summary>
 582    /// Clears and fills caller-owned storage with hex-prism neighbors in deterministic direction order.
 583    /// </summary>
 584    /// <param name="ownerGrid">The active grid that owns this voxel.</param>
 585    /// <param name="results">Caller-owned storage cleared and filled with direction-labeled neighbors.</param>
 586    public void GetHexNeighborsInto(
 587        VoxelGrid ownerGrid,
 588        SwiftList<(HexDirection Direction, Voxel Voxel)> results)
 589    {
 4590        SwiftThrowHelper.ThrowIfNull(results, nameof(results));
 591
 4592        results.Clear();
 4593        if (!IsValidOwnerGrid(ownerGrid))
 1594            return;
 595
 3596        VoxelNeighborResolver.AddHexNeighbors(this, ownerGrid, results);
 3597    }
 598
 599    private bool IsValidOwnerGrid(VoxelGrid? ownerGrid)
 600    {
 135601        return ownerGrid != null
 135602            && ownerGrid.IsActive
 135603            && ownerGrid.GridIndex == WorldIndex.GridIndex
 135604            && ownerGrid.SpawnToken == WorldIndex.GridSpawnToken
 135605            && ownerGrid.World != null
 135606            && ownerGrid.World.SpawnToken == WorldIndex.WorldSpawnToken;
 607    }
 608
 609    #endregion
 610
 611    #region Utility
 612
 613    /// <inheritdoc/>
 1941614    public override int GetHashCode() => RuntimeHelpers.GetHashCode(this);
 615
 616    /// <inheritdoc/>
 1617    public override string ToString() => WorldIndex.ToString();
 618
 619    /// <inheritdoc/>
 189620    public bool Equals(Voxel? other) => ReferenceEquals(this, other);
 621
 622    /// <inheritdoc/>
 2623    public override bool Equals(object? obj) => ReferenceEquals(this, obj);
 624
 625    #endregion
 626}

Methods/Properties

get_GridIndex()
get_Index()
.ctor()
get_IsPartioned()
get_IsBlocked()
get_IsBlockable()
get_IsOccupied()
get_HasVacancy()
get_HasEventSubscribers()
add_OnObstacleAdded(System.Action`1<GridForge.Grids.ObstacleEventInfo>)
remove_OnObstacleAdded(System.Action`1<GridForge.Grids.ObstacleEventInfo>)
add_OnObstacleRemoved(System.Action`1<GridForge.Grids.ObstacleEventInfo>)
remove_OnObstacleRemoved(System.Action`1<GridForge.Grids.ObstacleEventInfo>)
add_OnObstaclesCleared(System.Action`1<GridForge.Grids.ObstacleClearEventInfo>)
remove_OnObstaclesCleared(System.Action`1<GridForge.Grids.ObstacleClearEventInfo>)
add_OnOccupantAdded(System.Action`1<GridForge.Grids.OccupantEventInfo>)
remove_OnOccupantAdded(System.Action`1<GridForge.Grids.OccupantEventInfo>)
add_OnOccupantRemoved(System.Action`1<GridForge.Grids.OccupantEventInfo>)
remove_OnOccupantRemoved(System.Action`1<GridForge.Grids.OccupantEventInfo>)
Initialize(GridForge.Spatial.WorldVoxelIndex,FixedMathSharp.Vector3d,System.Int32,System.Boolean,System.UInt32)
Reset(GridForge.Grids.VoxelGrid)
RemovePartitions()
ReleaseObstacleState(GridForge.Grids.VoxelGrid)
ClearRuntimeState()
NotifyObstacleAdded(GridForge.Grids.ObstacleEventInfo)
NotifyObstacleRemoved(GridForge.Grids.ObstacleEventInfo)
NotifyObstaclesCleared(GridForge.Grids.ObstacleClearEventInfo)
NotifyOccupantAdded(GridForge.Grids.OccupantEventInfo)
NotifyOccupantRemoved(GridForge.Grids.OccupantEventInfo)
TryAddPartition(GridForge.Spatial.IVoxelPartition)
TryRemovePartition()
HasPartition()
TryGetPartition(T&)
GetPartitionOrDefault()
GetNeighborsInto(GridForge.Grids.VoxelGrid,SwiftCollections.SwiftList`1<GridForge.Grids.Voxel>,GridForge.Spatial.VoxelNeighborScope,System.Nullable`1<FixedMathSharp.Fixed64>)
HasNeighbor(GridForge.Grids.VoxelGrid,GridForge.Spatial.VoxelNeighborScope,System.Nullable`1<FixedMathSharp.Fixed64>)
TryGetNeighbor(GridForge.Grids.VoxelGrid,GridForge.Spatial.RectangularDirection,GridForge.Grids.Voxel&)
TryGetNeighbor(GridForge.Grids.VoxelGrid,GridForge.Spatial.HexDirection,GridForge.Grids.Voxel&)
GetRectangularNeighborsInto(GridForge.Grids.VoxelGrid,SwiftCollections.SwiftList`1<System.ValueTuple`2<GridForge.Spatial.RectangularDirection,GridForge.Grids.Voxel>>)
GetHexNeighborsInto(GridForge.Grids.VoxelGrid,SwiftCollections.SwiftList`1<System.ValueTuple`2<GridForge.Spatial.HexDirection,GridForge.Grids.Voxel>>)
IsValidOwnerGrid(GridForge.Grids.VoxelGrid)
GetHashCode()
ToString()
Equals(GridForge.Grids.Voxel)
Equals(System.Object)