< Summary

Line coverage
100%
Covered lines: 1017
Uncovered lines: 0
Coverable lines: 1017
Total lines: 1609
Line coverage: 100%
Branch coverage
100%
Covered branches: 370
Total branches: 370
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
File 1: .ctor(...)100%44100%
File 1: .ctor(...)100%11100%
File 1: .ctor(...)100%11100%
File 1: get_RetainedBytes()100%11100%
File 1: get_PersistentPageCount()100%11100%
File 1: get_AdditionalExclusiveRetainedBytes()100%2424100%
File 1: get_AdditionalExclusivePersistentPages()100%2020100%
File 1: Advance(...)100%2424100%
File 1: AdvanceOverlaySequence(...)100%1818100%
File 1: CompleteSequenceChange()100%11100%
File 1: FindDelta(...)100%66100%
File 1: ApplyCellOperation(...)100%1818100%
File 1: ShouldAllocateDynamicSlot(...)100%44100%
File 1: HasSameSemanticState(...)100%3030100%
File 1: RecordPersistentCopies(...)100%11100%
File 1: GetAdditionalRootBytes(...)100%44100%
File 1: GetAdditionalRootPages(...)100%44100%
File 2: .ctor(...)100%11100%
File 2: get_MapId()100%11100%
File 2: get_IsMaterialized()100%11100%
File 2: get_BakedSlotCount()100%11100%
File 2: get_DynamicSlotCount()100%11100%
File 2: get_DynamicAddresses()100%11100%
File 2: get_AddressCount()100%11100%
File 2: get_PreparedMapRetainedBytes()100%11100%
File 2: get_BakedCellLookup()100%11100%
File 2: get_LookupKind()100%11100%
File 2: get_PersistentPageCount()100%11100%
File 2: TryGetSlot(...)100%44100%
File 2: GetSlotIndex(...)100%11100%
File 2: TryGetEffectiveCell(...)100%1212100%
File 2: TryGetSemanticState(...)100%22100%
File 2: TryGetPhysicalState(...)100%22100%
File 2: GetEffectiveMedia(...)100%44100%
File 2: IsPhysicallyPresent(...)100%22100%
File 2: GetPageDependency(...)100%44100%
File 2: Apply(...)100%2020100%
File 2: ApplyBatch(...)100%66100%
File 2: Materialize(...)100%1010100%
File 2: MaterializeDelta(...)100%88100%
File 2: FailClosed(...)100%11100%
File 2: CreateDiagnostic(...)100%44100%
File 2: CreateMaterialized(...)100%11100%
File 2: AppendPhysicalBaselinePages(...)100%88100%
File 2: CopyCanonicalAddressChunk(...)100%88100%
File 2: CopyCanonicalAddresses(...)100%22100%
File 2: TryCopyNewCanonicalAddresses(...)100%66100%
File 2: MakeDormant(...)100%44100%
File 2: TryGetDefaultBaselineSeedSlot(...)100%22100%
File 2: TryGetDynamicSlot(...)100%11100%
File 2: CreateDefaultBaselineSeed(...)100%22100%
File 2: AppendDefaultBaselineStates(...)100%1616100%
File 2: CompleteDefaultBaseline(...)100%22100%
File 2: get_DefaultBaselineRetainedBytes()100%11100%
File 2: get_DefaultBaselinePersistentPages()100%11100%
File 2: WithPhysicalState(...)100%22100%
File 2: ApplyPhysicalState(...)100%1212100%
File 2: ApplyPhysicalSegment(...)100%3434100%
File 2: CountTouchedPages(...)100%44100%
File 2: FillDynamicBaselineCapturedChangeSequences(...)100%22100%
File 2: GetBaselineCapturedChangeSequence(...)100%22100%
File 2: ApplySemanticOperation(...)100%44100%
File 2: BuildPhysicalPages(...)100%11100%
File 2: FindSemanticPage(...)100%11100%
File 2: GetSemanticSource(...)100%1616100%
File 2: FindPhysicalPage(...)100%11100%
File 2: IsBroad(...)100%66100%
File 2: EstimateRetainedBytes()100%11100%
File 2: WithGridLastChangeSequence(...)100%22100%
File 3: TryGetSlotIndex(...)100%22100%

File(s)

/home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Graph/NavigationMapInstance.ComposeWork.cs

#LineLine coverage
 1//=======================================================================
 2// NavigationMapInstance.ComposeWork.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 GridForge.Spatial;
 10
 11namespace Trailblazer.Pathing;
 12
 13internal sealed partial class NavigationMapInstance
 14{
 15    /// <summary>Rebuilds replacement-map semantic pages under the shared maintenance meter.</summary>
 16    internal sealed class ComposeWork
 17    {
 18        private readonly NavigationOperationCandidate.MapState _state;
 19        private readonly NavigationMapInstance? _previous;
 20        private readonly NavigationMapOverlayDelta? _delta;
 21        private readonly NavigationOperationFrameChange[]? _changes;
 22        private readonly int _changeCount;
 23        private readonly string? _mapId;
 24        private readonly bool _isOverlayCompose;
 25        private readonly long _version;
 26        private PersistentVoxelIndexMap<NavigationDynamicCellSlot> _dynamicSlots;
 27        private PersistentIntMap<VoxelIndex> _dynamicSlotIndexes;
 28        private PersistentIntMap<ulong> _dynamicBaselineCapturedChangeSequences;
 29        private int _nextDynamicSlot;
 30        private PersistentIntMap<NavigationSemanticPage> _semanticPages;
 31        private PersistentIntMap<NavigationPhysicalPage> _physicalPages;
 32        private NavigationGridGenerationIdentity _gridIdentity;
 33        private ulong _baselineCapturedChangeSequence;
 34        private ulong _gridLastChangeSequence;
 35        private int _copiedSemanticPages;
 36        private int _retainedCopiedSemanticPages;
 37        private int _newAddressCount;
 38        private int _cellIndex;
 39        private int _changeIndex;
 40        private bool _changeDebited;
 41        private bool _lookupDebited;
 42        private NavigationMapOverlayDelta? _activeDelta;
 199643        private int _lastCopiedSemanticPageIndex = -1;
 44        private long _copiedPersistentBytes;
 45        private int _copiedPersistentPages;
 46
 178347        internal ComposeWork(
 178348            NavigationOperationCandidate.MapState state,
 178349            NavigationMapInstance? previous,
 178350            long version)
 51        {
 178352            _state = state;
 178353            _previous = previous;
 178354            _version = version;
 178355            _semanticPages = PersistentIntMap<NavigationSemanticPage>.Empty;
 178356            _physicalPages = PersistentIntMap<NavigationPhysicalPage>.Empty;
 178357            if (previous != null
 178358                && previous.DynamicSlotGeneration == state.DynamicSlotGeneration)
 59            {
 60                // PreserveAndRevalidate keeps the exact logical dynamic-address set. Reuse its
 61                // Reverse and captured-sequence roots; only baked ordinals can force
 62                // semantic-page rebuilds.
 3663                _dynamicSlots = previous._dynamicSlots;
 3664                _dynamicSlotIndexes = previous._dynamicSlotIndexes;
 3665                _dynamicBaselineCapturedChangeSequences =
 3666                    previous._dynamicBaselineCapturedChangeSequences;
 3667                _nextDynamicSlot = previous._nextDynamicSlot;
 68            }
 69            else
 70            {
 174771                _dynamicSlots = PersistentVoxelIndexMap<NavigationDynamicCellSlot>.Empty;
 174772                _dynamicSlotIndexes = PersistentIntMap<VoxelIndex>.Empty;
 174773                _dynamicBaselineCapturedChangeSequences = PersistentIntMap<ulong>.Empty;
 174774                _nextDynamicSlot = DynamicSlotBase;
 75            }
 174776        }
 77
 1178        internal ComposeWork(
 1179            NavigationOperationCandidate.MapState state,
 1180            NavigationMapInstance previous,
 1181            NavigationMapOverlayDelta delta,
 1182            long version)
 83        {
 1184            _state = state;
 1185            _previous = previous;
 1186            _delta = delta;
 1187            _isOverlayCompose = true;
 1188            _version = version;
 1189            _dynamicSlots = previous._dynamicSlots;
 1190            _dynamicSlotIndexes = previous._dynamicSlotIndexes;
 1191            _dynamicBaselineCapturedChangeSequences =
 1192                previous._dynamicBaselineCapturedChangeSequences;
 1193            _nextDynamicSlot = previous._nextDynamicSlot;
 1194            _semanticPages = previous._semanticPages;
 1195            _physicalPages = previous._physicalPages;
 1196            _gridIdentity = previous.GridIdentity;
 1197            _baselineCapturedChangeSequence = previous.BaselineCapturedChangeSequence;
 1198            _gridLastChangeSequence = previous.GridLastChangeSequence;
 1199        }
 100
 202101        internal ComposeWork(
 202102            NavigationOperationCandidate.MapState state,
 202103            NavigationMapInstance previous,
 202104            NavigationOperationFrameChange[] changes,
 202105            int changeCount,
 202106            string mapId,
 202107            long version)
 108        {
 202109            _state = state;
 202110            _previous = previous;
 202111            _changes = changes;
 202112            _changeCount = changeCount;
 202113            _mapId = mapId;
 202114            _isOverlayCompose = true;
 202115            _version = version;
 202116            _dynamicSlots = previous._dynamicSlots;
 202117            _dynamicSlotIndexes = previous._dynamicSlotIndexes;
 202118            _dynamicBaselineCapturedChangeSequences =
 202119                previous._dynamicBaselineCapturedChangeSequences;
 202120            _nextDynamicSlot = previous._nextDynamicSlot;
 202121            _semanticPages = previous._semanticPages;
 202122            _physicalPages = previous._physicalPages;
 202123            _gridIdentity = previous.GridIdentity;
 202124            _baselineCapturedChangeSequence = previous.BaselineCapturedChangeSequence;
 202125            _gridLastChangeSequence = previous.GridLastChangeSequence;
 202126        }
 127
 128        internal NavigationMapInstance Result { get; private set; } = null!;
 129
 3130        internal long RetainedBytes => checked(96L + AdditionalExclusiveRetainedBytes);
 131
 3132        internal int PersistentPageCount => checked(1 + AdditionalExclusivePersistentPages);
 133
 1989134        internal long AdditionalExclusiveRetainedBytes => checked(
 1989135            200L
 1989136            + GetAdditionalRootBytes(
 1989137                _dynamicSlots,
 1989138                _previous?._dynamicSlots,
 1989139                _dynamicSlots.RetainedBytes,
 1989140                _previous?._dynamicSlots.RetainedBytes ?? 0L)
 1989141            + GetAdditionalRootBytes(
 1989142                _dynamicSlotIndexes,
 1989143                _previous?._dynamicSlotIndexes,
 1989144                _dynamicSlotIndexes.RetainedBytes,
 1989145                _previous?._dynamicSlotIndexes.RetainedBytes ?? 0L)
 1989146            + GetAdditionalRootBytes(
 1989147                _dynamicBaselineCapturedChangeSequences,
 1989148                _previous?._dynamicBaselineCapturedChangeSequences,
 1989149                _dynamicBaselineCapturedChangeSequences.RetainedBytes,
 1989150                _previous?._dynamicBaselineCapturedChangeSequences.RetainedBytes ?? 0L)
 1989151            + GetAdditionalRootBytes(
 1989152                _semanticPages,
 1989153                _previous?._semanticPages,
 1989154                checked(_semanticPages.RetainedBytes + ((long)_semanticPages.Count * 4_400L)),
 1989155                checked((_previous?._semanticPages.RetainedBytes ?? 0L)
 1989156                    + ((long)(_previous?._semanticPages.Count ?? 0) * 4_400L)))
 1989157            + GetAdditionalRootBytes(
 1989158                _physicalPages,
 1989159                _previous?._physicalPages,
 1989160                checked(_physicalPages.RetainedBytes + ((long)_physicalPages.Count * 320L)),
 1989161                checked((_previous?._physicalPages.RetainedBytes ?? 0L)
 1989162                    + ((long)(_previous?._physicalPages.Count ?? 0) * 320L)))
 1989163            + _copiedPersistentBytes
 1989164            + ((long)_retainedCopiedSemanticPages * 4_400L));
 165
 1990166        internal int AdditionalExclusivePersistentPages => checked(
 1990167            6
 1990168            + GetAdditionalRootPages(
 1990169                _dynamicSlots,
 1990170                _previous?._dynamicSlots,
 1990171                _dynamicSlots.PersistentNodeCount,
 1990172                _previous?._dynamicSlots.PersistentNodeCount ?? 0)
 1990173            + GetAdditionalRootPages(
 1990174                _dynamicSlotIndexes,
 1990175                _previous?._dynamicSlotIndexes,
 1990176                _dynamicSlotIndexes.PersistentNodeCount,
 1990177                _previous?._dynamicSlotIndexes.PersistentNodeCount ?? 0)
 1990178            + GetAdditionalRootPages(
 1990179                _dynamicBaselineCapturedChangeSequences,
 1990180                _previous?._dynamicBaselineCapturedChangeSequences,
 1990181                _dynamicBaselineCapturedChangeSequences.PersistentNodeCount,
 1990182                _previous?._dynamicBaselineCapturedChangeSequences.PersistentNodeCount ?? 0)
 1990183            + GetAdditionalRootPages(
 1990184                _semanticPages,
 1990185                _previous?._semanticPages,
 1990186                checked(_semanticPages.PersistentNodeCount * 2),
 1990187                checked((_previous?._semanticPages.PersistentNodeCount ?? 0) * 2))
 1990188            + GetAdditionalRootPages(
 1990189                _physicalPages,
 1990190                _previous?._physicalPages,
 1990191                checked(_physicalPages.PersistentNodeCount * 2),
 1990192                checked((_previous?._physicalPages.PersistentNodeCount ?? 0) * 2))
 1990193            + _copiedPersistentPages
 1990194            + _retainedCopiedSemanticPages);
 195
 196        internal bool Advance(MaintenanceWorkMeter meter)
 197        {
 2054198            if (Result != null)
 1199                return true;
 2053200            if (_changes != null)
 201            {
 258202                if (!AdvanceOverlaySequence(meter))
 56203                    return false;
 204            }
 205            else
 206            {
 1795207                int cellCount = _delta?.Cells.Count ?? _state.Overlay.CellCount;
 1900208                while (_cellIndex < cellCount)
 209                {
 109210                    if (!meter.TryConsumeOverlaySlots(1))
 4211                        return false;
 105212                    NavigationCellOverlayOperation operation = _delta == null
 105213                        ? _state.Overlay.GetCellAt(_cellIndex++)
 105214                        : _delta.Cells[_cellIndex++];
 105215                    ApplyCellOperation(operation);
 216                }
 217            }
 1993218            if (_isOverlayCompose && _newAddressCount > 0)
 219            {
 81220                _gridIdentity = default;
 81221                _baselineCapturedChangeSequence = 0;
 81222                _gridLastChangeSequence = 0;
 81223                _physicalPages = PersistentIntMap<NavigationPhysicalPage>.Empty;
 224            }
 1993225            Result = new NavigationMapInstance(
 1993226                _state.Map,
 1993227                _state.BakeVersion,
 1993228                _state.Overlay,
 1993229                _state.DynamicSlotGeneration,
 1993230                _dynamicSlots,
 1993231                _dynamicSlotIndexes,
 1993232                _nextDynamicSlot,
 1993233                _semanticPages,
 1993234                _physicalPages,
 1993235                _dynamicBaselineCapturedChangeSequences,
 1993236                _state.BakedCellLookup,
 1993237                _state.PreparedMapRetainedBytes,
 1993238                _gridIdentity,
 1993239                _baselineCapturedChangeSequence,
 1993240                _gridLastChangeSequence,
 1993241                _version,
 1993242                semanticVersion: _version,
 1993243                physicalVersion: _isOverlayCompose && _newAddressCount == 0
 1993244                    ? _previous!.PhysicalVersion
 1993245                    : _version,
 1993246                lastBaselineAddressCount: _newAddressCount,
 1993247                lastCopiedSemanticPages: !_isOverlayCompose
 1993248                    ? _semanticPages.Count
 1993249                    : _copiedSemanticPages,
 1993250                lastCopiedPhysicalPages: 0,
 1993251                dynamicAddresses: _state.DynamicAddresses);
 1993252            return true;
 253        }
 254
 255        private bool AdvanceOverlaySequence(MaintenanceWorkMeter meter)
 256        {
 469257            while (_changeIndex < _changeCount)
 258            {
 267259                if (!_changeDebited)
 260                {
 254261                    if (!meter.TryConsumeComponentNodes(1))
 43262                        return false;
 211263                    _changeDebited = true;
 264                }
 224265                NavigationOperationFrameChange change = _changes![_changeIndex];
 224266                if (change.Kind != NavigationOperationFrameChangeKind.Overlay)
 267                {
 2268                    CompleteSequenceChange();
 2269                    continue;
 270                }
 222271                if (!_lookupDebited)
 272                {
 210273                    if (!meter.TryConsumeDependencyEntries(1))
 1274                        return false;
 209275                    _lookupDebited = true;
 209276                    _activeDelta = FindDelta(
 209277                        change.PreparedOverlay!.Transaction.MapSpan,
 209278                        _mapId!);
 279                }
 221280                if (_activeDelta == null)
 281                {
 3282                    CompleteSequenceChange();
 3283                    continue;
 284                }
 16792285                while (_cellIndex < _activeDelta.Cells.Count)
 286                {
 16586287                    if (!meter.TryConsumeOverlaySlots(1))
 12288                        return false;
 16574289                    ApplyCellOperation(_activeDelta.Cells[_cellIndex++]);
 290                }
 206291                CompleteSequenceChange();
 292            }
 202293            return true;
 294        }
 295
 296        private void CompleteSequenceChange()
 297        {
 211298            _changeIndex++;
 211299            _cellIndex = 0;
 211300            _changeDebited = false;
 211301            _lookupDebited = false;
 211302            _activeDelta = null;
 211303        }
 304
 305        private static NavigationMapOverlayDelta? FindDelta(
 306            ReadOnlySpan<NavigationMapOverlayDelta> deltas,
 307            string mapId)
 308        {
 209309            int lower = 0;
 209310            int upper = deltas.Length - 1;
 256311            while (lower <= upper)
 312            {
 253313                int middle = lower + ((upper - lower) >> 1);
 253314                NavigationMapOverlayDelta delta = deltas[middle];
 253315                int comparison = string.CompareOrdinal(delta.MapId, mapId);
 253316                if (comparison == 0)
 206317                    return delta;
 47318                if (comparison < 0)
 21319                    lower = middle + 1;
 320                else
 26321                    upper = middle - 1;
 322            }
 3323            return null;
 324        }
 325
 326        private void ApplyCellOperation(NavigationCellOverlayOperation operation)
 327        {
 16679328            int slot = _state.BakedCellLookup.Find(operation.Index);
 16679329            if (slot < 0
 16679330                && _dynamicSlots.TryGetValue(
 16679331                    operation.Index,
 16679332                    out NavigationDynamicCellSlot dynamicSlot))
 333            {
 46334                slot = dynamicSlot.Slot;
 335            }
 16679336            if (slot < 0
 16679337                && ShouldAllocateDynamicSlot(
 16679338                    operation.Kind,
 16679339                    _state.Map.DefaultCell.HasValue))
 340            {
 16552341                slot = _nextDynamicSlot++;
 16552342                var addedDynamicSlot = new NavigationDynamicCellSlot(operation.Index, slot);
 16552343                _dynamicSlots = _dynamicSlots.Set(
 16552344                    operation.Index,
 16552345                    addedDynamicSlot,
 16552346                    out int slotCopies);
 16552347                RecordPersistentCopies(slotCopies, 64L);
 16552348                _dynamicSlotIndexes = _dynamicSlotIndexes.Set(
 16552349                    slot,
 16552350                    operation.Index,
 16552351                    out int indexCopies);
 16552352                RecordPersistentCopies(indexCopies, 72L);
 16552353                _newAddressCount++;
 354            }
 16679355            if (slot < 0)
 2356                return;
 16677357            if (HasSameSemanticState(slot, operation))
 3358                return;
 16674359            PersistentIntMap<NavigationSemanticPage> updated = ApplySemanticOperation(
 16674360                _semanticPages,
 16674361                slot,
 16674362                operation,
 16674363                _version,
 16674364                out int semanticCopies);
 365            System.Diagnostics.Debug.Assert(!ReferenceEquals(updated, _semanticPages));
 16674366            RecordPersistentCopies(semanticCopies, 72L);
 16674367            int pageIndex = slot / NavigationSemanticPage.SlotCount;
 16674368            if (pageIndex != _lastCopiedSemanticPageIndex)
 369            {
 466370                _copiedSemanticPages++;
 466371                if (_previous != null
 466372                    && _previous._semanticPages.TryGetValue(pageIndex, out _))
 373                {
 52374                    _retainedCopiedSemanticPages++;
 375                }
 466376                _lastCopiedSemanticPageIndex = pageIndex;
 377            }
 16674378            _semanticPages = updated;
 16674379        }
 380
 381        internal static bool ShouldAllocateDynamicSlot(
 382            NavigationCellOverlayOperationKind kind,
 16560383            bool hasDefaultCell) => kind == NavigationCellOverlayOperationKind.Set
 16560384            || hasDefaultCell && kind == NavigationCellOverlayOperationKind.Suppress;
 385
 386        private bool HasSameSemanticState(
 387            int slot,
 388            NavigationCellOverlayOperation operation)
 389        {
 16677390            bool dynamic = slot >= _state.Map.CellSpan.Length;
 16677391            _semanticPages.TryGetValue(
 16677392                slot / NavigationSemanticPage.SlotCount,
 16677393                out NavigationSemanticPage? page);
 16677394            int offset = slot % NavigationSemanticPage.SlotCount;
 395            NavigationCellSemanticSource currentSource;
 396            bool currentHasCell;
 397            NavigationCell currentCell;
 16677398            if (page != null && page.IsSuppressed[offset])
 399            {
 7400                currentSource = NavigationCellSemanticSource.OverlaySuppressed;
 7401                currentHasCell = false;
 7402                currentCell = default;
 403            }
 16670404            else if (page != null && page.HasOverride[offset])
 405            {
 45406                currentSource = dynamic
 45407                    ? NavigationCellSemanticSource.DynamicOverlaySet
 45408                    : NavigationCellSemanticSource.OverlaySet;
 45409                currentHasCell = true;
 45410                currentCell = page.Cells[offset];
 411            }
 16625412            else if (dynamic)
 413            {
 16557414                currentSource = _state.Map.DefaultCell.HasValue
 16557415                    ? NavigationCellSemanticSource.Baked
 16557416                    : NavigationCellSemanticSource.DynamicInactive;
 16557417                currentHasCell = _state.Map.DefaultCell.HasValue;
 16557418                currentCell = _state.Map.DefaultCell.GetValueOrDefault();
 419            }
 420            else
 421            {
 68422                currentSource = NavigationCellSemanticSource.Baked;
 68423                currentHasCell = true;
 68424                currentCell = _state.Map.CellSpan[slot].Cell;
 425            }
 426
 427            NavigationCellSemanticSource nextSource;
 428            bool nextHasCell;
 429            NavigationCell nextCell;
 16677430            if (operation.Kind == NavigationCellOverlayOperationKind.Set)
 431            {
 16586432                nextSource = dynamic
 16586433                    ? NavigationCellSemanticSource.DynamicOverlaySet
 16586434                    : NavigationCellSemanticSource.OverlaySet;
 16586435                nextHasCell = true;
 16586436                nextCell = operation.Cell;
 437            }
 91438            else if (operation.Kind == NavigationCellOverlayOperationKind.Suppress)
 439            {
 45440                nextSource = NavigationCellSemanticSource.OverlaySuppressed;
 45441                nextHasCell = false;
 45442                nextCell = default;
 443            }
 46444            else if (dynamic)
 445            {
 37446                nextSource = _state.Map.DefaultCell.HasValue
 37447                    ? NavigationCellSemanticSource.Baked
 37448                    : NavigationCellSemanticSource.DynamicInactive;
 37449                nextHasCell = _state.Map.DefaultCell.HasValue;
 37450                nextCell = _state.Map.DefaultCell.GetValueOrDefault();
 451            }
 452            else
 453            {
 9454                nextSource = NavigationCellSemanticSource.Baked;
 9455                nextHasCell = true;
 9456                nextCell = _state.Map.CellSpan[slot].Cell;
 457            }
 16677458            return currentSource == nextSource
 16677459                && currentHasCell == nextHasCell
 16677460                && (!currentHasCell || currentCell.Equals(nextCell));
 461        }
 462
 463        private void RecordPersistentCopies(int copiedNodes, long bytesPerNode)
 464        {
 49778465            _copiedPersistentPages = checked(_copiedPersistentPages + copiedNodes);
 49778466            _copiedPersistentBytes = checked(
 49778467                _copiedPersistentBytes + (copiedNodes * bytesPerNode));
 49778468        }
 469
 470        private long GetAdditionalRootBytes(
 471            object current,
 472            object? previous,
 473            long currentBytes,
 474            long previousBytes)
 475        {
 9945476            if (ReferenceEquals(current, previous))
 1819477                return 0;
 8126478            return !_isOverlayCompose
 8126479                ? currentBytes
 8126480                : checked(32L + System.Math.Max(0L, currentBytes - previousBytes));
 481        }
 482
 483        private int GetAdditionalRootPages(
 484            object current,
 485            object? previous,
 486            int currentPages,
 487            int previousPages)
 488        {
 9950489            if (ReferenceEquals(current, previous))
 1819490                return 0;
 8131491            return !_isOverlayCompose
 8131492                ? currentPages
 8131493                : System.Math.Max(0, currentPages - previousPages);
 494        }
 495    }
 496}

/home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Graph/NavigationMapInstance.cs

#LineLine coverage
 1//=======================================================================
 2// NavigationMapInstance.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 GridForge.Grids;
 10using GridForge.Spatial;
 11
 12namespace Trailblazer.Pathing;
 13
 14/// <summary>Stores one immutable composed map instance without retaining GridForge voxels.</summary>
 15internal sealed partial class NavigationMapInstance
 16{
 17    private const int DynamicSlotBase = 1_000_000_000;
 18    private readonly PersistentVoxelIndexMap<NavigationDynamicCellSlot> _dynamicSlots;
 19    private readonly PersistentVoxelIndexMap<byte> _dynamicAddresses;
 20    private readonly PersistentIntMap<VoxelIndex> _dynamicSlotIndexes;
 21    private readonly int _nextDynamicSlot;
 22    private readonly PersistentIntMap<NavigationSemanticPage> _semanticPages;
 23    private readonly PersistentIntMap<NavigationPhysicalPage> _physicalPages;
 24    private readonly PersistentIntMap<ulong> _dynamicBaselineCapturedChangeSequences;
 25    private readonly NavigationBakedCellLookup _bakedLookup;
 26    private readonly long _preparedMapRetainedBytes;
 27
 397328    private NavigationMapInstance(
 397329        NavigationMap map,
 397330        long bakeVersion,
 397331        NavigationMapOverlayState overlay,
 397332        long dynamicSlotGeneration,
 397333        PersistentVoxelIndexMap<NavigationDynamicCellSlot> dynamicSlots,
 397334        PersistentIntMap<VoxelIndex> dynamicSlotIndexes,
 397335        int nextDynamicSlot,
 397336        PersistentIntMap<NavigationSemanticPage> semanticPages,
 397337        PersistentIntMap<NavigationPhysicalPage> physicalPages,
 397338        PersistentIntMap<ulong> dynamicBaselineCapturedChangeSequences,
 397339        NavigationBakedCellLookup bakedLookup,
 397340        long preparedMapRetainedBytes,
 397341        NavigationGridGenerationIdentity gridIdentity,
 397342        ulong baselineCapturedChangeSequence,
 397343        ulong gridLastChangeSequence,
 397344        long instanceVersion,
 397345        long semanticVersion,
 397346        long physicalVersion,
 397347        int lastBaselineAddressCount,
 397348        int lastCopiedSemanticPages,
 397349        int lastCopiedPhysicalPages,
 397350        PersistentVoxelIndexMap<byte> dynamicAddresses)
 51    {
 397352        Map = map;
 397353        BakeVersion = bakeVersion;
 397354        Overlay = overlay;
 397355        DynamicSlotGeneration = dynamicSlotGeneration;
 397356        _dynamicSlots = dynamicSlots;
 397357        _dynamicAddresses = dynamicAddresses;
 397358        _dynamicSlotIndexes = dynamicSlotIndexes;
 397359        _nextDynamicSlot = nextDynamicSlot;
 397360        _semanticPages = semanticPages;
 397361        _physicalPages = physicalPages;
 397362        _dynamicBaselineCapturedChangeSequences = dynamicBaselineCapturedChangeSequences;
 397363        _bakedLookup = bakedLookup;
 397364        _preparedMapRetainedBytes = preparedMapRetainedBytes;
 397365        GridIdentity = gridIdentity;
 397366        BaselineCapturedChangeSequence = baselineCapturedChangeSequence;
 397367        GridLastChangeSequence = gridLastChangeSequence;
 397368        InstanceVersion = instanceVersion;
 397369        SemanticVersion = semanticVersion;
 397370        PhysicalVersion = physicalVersion;
 397371        LastBaselineAddressCount = lastBaselineAddressCount;
 397372        LastCopiedSemanticPages = lastCopiedSemanticPages;
 397373        LastCopiedPhysicalPages = lastCopiedPhysicalPages;
 397374        RetainedBytes = EstimateRetainedBytes();
 397375    }
 76
 77    internal NavigationMap Map { get; }
 78
 533704779    internal string MapId => Map.MapId;
 80
 81    internal long BakeVersion { get; }
 82
 83    internal NavigationMapOverlayState Overlay { get; }
 84
 85    internal long DynamicSlotGeneration { get; }
 86
 87    internal NavigationGridGenerationIdentity GridIdentity { get; }
 88
 89    internal ulong BaselineCapturedChangeSequence { get; }
 90
 91    internal ulong GridLastChangeSequence { get; }
 92
 93    internal long InstanceVersion { get; }
 94
 95    internal long SemanticVersion { get; }
 96
 97    internal long PhysicalVersion { get; }
 98
 99    internal int LastBaselineAddressCount { get; }
 100
 101    internal int LastCopiedSemanticPages { get; }
 102
 103    internal int LastCopiedPhysicalPages { get; }
 104
 20549105    internal bool IsMaterialized => GridIdentity.IsValid;
 106
 8679314107    internal int BakedSlotCount => Map.CellSpan.Length;
 108
 2271621109    internal int DynamicSlotCount => _dynamicSlots.Count;
 110
 23111    internal PersistentVoxelIndexMap<byte> DynamicAddresses => _dynamicAddresses;
 112
 2191071113    internal int AddressCount => BakedSlotCount + DynamicSlotCount;
 114
 115    internal long RetainedBytes { get; }
 116
 1117    internal long PreparedMapRetainedBytes => _preparedMapRetainedBytes;
 118
 23119    internal NavigationBakedCellLookup BakedCellLookup => _bakedLookup;
 120
 14635121    internal NavigationCellLookupKind LookupKind => _bakedLookup.Kind;
 122
 4434123    internal int PersistentPageCount => 6
 4434124        + Overlay.PersistentNodeCount
 4434125        + _dynamicSlots.PersistentNodeCount
 4434126        + _dynamicAddresses.PersistentNodeCount
 4434127        + _dynamicSlotIndexes.PersistentNodeCount
 4434128        + (_semanticPages.PersistentNodeCount * 2)
 4434129        + (_physicalPages.PersistentNodeCount * 2)
 4434130        + _dynamicBaselineCapturedChangeSequences.PersistentNodeCount;
 131
 132    internal bool TryGetSlot(VoxelIndex index, out int slot)
 133    {
 4515871134        int baked = _bakedLookup.Find(index);
 4515871135        if (baked >= 0)
 136        {
 1157711137            slot = baked;
 1157711138            return true;
 139        }
 140
 3358160141        if (_dynamicSlots.TryGetValue(index, out NavigationDynamicCellSlot dynamicSlot))
 142        {
 3125613143            slot = dynamicSlot.Slot;
 3125613144            return true;
 145        }
 146
 232547147        slot = -1;
 232547148        return false;
 149    }
 150
 151    internal VoxelIndex GetSlotIndex(int slot)
 152    {
 2145039153        bool found = TryGetSlotIndex(slot, out VoxelIndex index);
 154        System.Diagnostics.Debug.Assert(found, "Diagnostics enumerate only addressed slots.");
 2145039155        return index;
 156    }
 157
 158    internal bool TryGetEffectiveCell(int slot, out NavigationCell cell)
 159    {
 7072314160        NavigationSemanticPage? page = FindSemanticPage(slot / NavigationSemanticPage.SlotCount);
 7072314161        int offset = slot % NavigationSemanticPage.SlotCount;
 7072314162        if (page != null && page.IsSuppressed[offset])
 163        {
 299164            cell = default;
 299165            return false;
 166        }
 7072015167        if (page != null && page.HasOverride[offset])
 168        {
 5359595169            cell = page.Cells[offset];
 5359595170            return true;
 171        }
 1712420172        if ((uint)slot < (uint)Map.CellSpan.Length)
 173        {
 1709609174            cell = Map.CellSpan[slot].Cell;
 1709609175            return true;
 176        }
 177
 2811178        if (Map.DefaultCell.HasValue)
 179        {
 2515180            cell = Map.DefaultCell.Value;
 2515181            return true;
 182        }
 183
 296184        cell = default;
 296185        return false;
 186    }
 187
 188    internal bool TryGetSemanticState(
 189        VoxelIndex index,
 190        out NavigationCellSemanticSource source,
 191        out bool hasCell,
 192        out NavigationCell cell)
 193    {
 113972194        if (!TryGetSlot(index, out int slot))
 195        {
 98775196            source = default;
 98775197            hasCell = false;
 98775198            cell = default;
 98775199            return false;
 200        }
 15197201        source = GetSemanticSource(slot);
 15197202        hasCell = TryGetEffectiveCell(slot, out cell);
 15197203        return true;
 204    }
 205
 206    internal bool TryGetPhysicalState(int slot, out bool isPresent, out byte obstacleCount)
 207    {
 3110148208        NavigationPhysicalPage? page = FindPhysicalPage(slot / NavigationPhysicalPage.SlotCount);
 3110148209        if (page == null)
 210        {
 2131032211            isPresent = false;
 2131032212            obstacleCount = 0;
 2131032213            return false;
 214        }
 215
 979116216        int offset = slot % NavigationPhysicalPage.SlotCount;
 979116217        isPresent = page.IsPresent[offset];
 979116218        obstacleCount = page.ObstacleCounts[offset];
 979116219        return true;
 220    }
 221
 222    internal TraversalMedia GetEffectiveMedia(VoxelIndex index) =>
 5023223        TryGetSlot(index, out int slot)
 5023224        && TryGetEffectiveCell(slot, out NavigationCell cell)
 5023225            ? cell.Media
 5023226            : TraversalMedia.None;
 227
 228    internal bool IsPhysicallyPresent(VoxelIndex index) =>
 840229        TryGetSlot(index, out int slot)
 840230        && TryGetPhysicalState(slot, out bool isPresent, out _)
 840231        && isPresent;
 232
 233    internal GraphPageDependency GetPageDependency(int pageIndex, long transitionVersion = 0)
 234    {
 32909235        _semanticPages.TryGetValue(pageIndex, out NavigationSemanticPage? semantic);
 32909236        _physicalPages.TryGetValue(pageIndex, out NavigationPhysicalPage? physical);
 32909237        return new GraphPageDependency(
 32909238            MapId,
 32909239            BakeVersion,
 32909240            DynamicSlotGeneration,
 32909241            pageIndex,
 32909242            semantic?.Version ?? 0,
 32909243            physical?.Version ?? 0,
 32909244            transitionVersion);
 245    }
 246
 247    internal NavigationMapInstance Apply(
 248        long worldSpawnToken,
 249        in GridEventInfo eventInfo,
 250        long instanceVersion)
 251    {
 33252        if (eventInfo.WorldSpawnToken != worldSpawnToken)
 1253            return this;
 254
 32255        if (eventInfo.ChangeKind == GridEventKind.WorldReset)
 1256            return MakeDormant(instanceVersion);
 257
 31258        if (eventInfo.ChangeKind == GridEventKind.GridAdded
 31259            || eventInfo.ChangeKind == GridEventKind.GridChanged)
 260        {
 3261            if (!eventInfo.Configuration.ToGridKey().Equals(Map.GridBinding.Key))
 1262                return this;
 2263            return MakeDormant(instanceVersion);
 264        }
 265
 28266        if (!GridIdentity.Matches(
 28267                eventInfo.WorldSpawnToken,
 28268                eventInfo.GridIndex,
 28269                eventInfo.GridSpawnToken))
 270        {
 10271            return this;
 272        }
 273
 18274        if (eventInfo.ChangeKind == GridEventKind.GridRemoved)
 11275            return MakeDormant(instanceVersion);
 7276        if (!eventInfo.HasVoxelState
 7277            || !TryGetSlot(eventInfo.VoxelIndex, out int slot)
 7278            || eventInfo.ChangeSequence <= GetBaselineCapturedChangeSequence(slot))
 279        {
 4280            return WithGridLastChangeSequence(eventInfo.ChangeSequence, instanceVersion);
 281        }
 282
 3283        return WithPhysicalState(
 3284            slot,
 3285            eventInfo.IsVoxelPresent,
 3286            eventInfo.ObstacleCount,
 3287            instanceVersion,
 3288            eventInfo.ChangeSequence);
 289    }
 290
 291    internal NavigationMapInstance ApplyBatch(
 292        long worldSpawnToken,
 293        ReadOnlySpan<GridEventInfo> events,
 294        bool resnapshotAll,
 295        long instanceVersion)
 296    {
 263297        NavigationMapInstance next = resnapshotAll ? MakeDormant(instanceVersion) : this;
 263298        int segmentStart = 0;
 740299        for (int i = 0; i < events.Length; i++)
 300        {
 107301            if (!IsBroad(events[i].ChangeKind))
 302                continue;
 20303            next = next.ApplyPhysicalSegment(events.Slice(segmentStart, i - segmentStart), instanceVersion);
 20304            next = next.Apply(worldSpawnToken, events[i], instanceVersion);
 20305            segmentStart = i + 1;
 306        }
 263307        return next.ApplyPhysicalSegment(events.Slice(segmentStart), instanceVersion);
 308    }
 309
 310    internal NavigationMapInstance Materialize(
 311        in NavigationGridBaselineCapture capture,
 312        long instanceVersion)
 313    {
 1833314        GridNavigationBaseline? baseline = capture.Baseline;
 1833315        if (!capture.IsRequested
 1833316            || !capture.HasBaseline)
 317        {
 226318            return MakeDormant(instanceVersion);
 319        }
 320
 1607321        NavigationMapInstance materializing = capture.PreparedInstance ?? this;
 1607322        PersistentIntMap<NavigationPhysicalPage> pages = capture.PreparedPages
 1607323            ?? (baseline == null
 1607324                ? materializing._physicalPages
 1607325                : materializing.BuildPhysicalPages(baseline.VoxelStates));
 1607326        return materializing.CreateMaterialized(
 1607327            capture,
 1607328            pages,
 1607329            materializing.BakedSlotCount + materializing.DynamicSlotCount,
 1607330            instanceVersion);
 331    }
 332
 333    internal NavigationMapInstance MaterializeDelta(
 334        NavigationMapInstance previous,
 335        in NavigationGridBaselineCapture capture,
 336        long instanceVersion)
 337    {
 122338        GridNavigationBaseline? baseline = capture.Baseline;
 122339        if (!capture.IsRequested
 122340            || !capture.IsDelta)
 341        {
 86342            return Materialize(capture, instanceVersion);
 343        }
 36344        if (baseline == null)
 345        {
 1346            return MakeDormant(instanceVersion);
 347        }
 348
 35349        PersistentIntMap<NavigationPhysicalPage> pages = previous._physicalPages;
 35350        PersistentIntMap<ulong> dynamicCapturedChangeSequences =
 35351            _dynamicBaselineCapturedChangeSequences;
 35352        var capturedAddresses = new VoxelIndex[capture.AddressCount];
 142353        for (int i = 0; i < capture.AddressCount; i++)
 354        {
 36355            VoxelIndex address = baseline.VoxelStates[i].VoxelIndex;
 356            System.Diagnostics.Debug.Assert(!previous.TryGetSlot(address, out _));
 36357            bool found = TryGetSlot(address, out int slot);
 358            System.Diagnostics.Debug.Assert(found);
 359            System.Diagnostics.Debug.Assert(slot >= DynamicSlotBase);
 36360            NavigationBaselineVoxelState physical = baseline.VoxelStates[i];
 36361            pages = ApplyPhysicalState(
 36362                pages,
 36363                slot,
 36364                physical.IsPresent,
 36365                physical.ObstacleCount,
 36366                instanceVersion);
 36367            dynamicCapturedChangeSequences = dynamicCapturedChangeSequences.Set(
 36368                slot,
 36369                baseline.CapturedChangeSequence);
 36370            capturedAddresses[i] = address;
 371        }
 372        System.Diagnostics.Debug.Assert(capture.AddressCount > 0);
 373
 35374        return new NavigationMapInstance(
 35375            Map,
 35376            BakeVersion,
 35377            Overlay,
 35378            DynamicSlotGeneration,
 35379            _dynamicSlots,
 35380            _dynamicSlotIndexes,
 35381            _nextDynamicSlot,
 35382            _semanticPages,
 35383            pages,
 35384            dynamicCapturedChangeSequences,
 35385            _bakedLookup,
 35386            _preparedMapRetainedBytes,
 35387            new NavigationGridGenerationIdentity(
 35388                baseline.WorldSpawnToken,
 35389                baseline.GridIndex,
 35390                baseline.GridSpawnToken,
 35391                baseline.ConfigurationKey),
 35392            previous.BaselineCapturedChangeSequence,
 35393            baseline.GridLastChangeSequence,
 35394            instanceVersion,
 35395            SemanticVersion,
 35396            physicalVersion: instanceVersion,
 35397            lastBaselineAddressCount: capture.AddressCount,
 35398            lastCopiedSemanticPages: LastCopiedSemanticPages,
 35399            lastCopiedPhysicalPages: CountTouchedPages(
 35400                capturedAddresses,
 35401                capture.AddressCount,
 35402                _dynamicSlots),
 35403            dynamicAddresses: _dynamicAddresses);
 404    }
 405
 406    internal NavigationMapInstance FailClosed(long instanceVersion) =>
 44407        MakeDormant(instanceVersion);
 408
 409    internal NavigationGraphMapDiagnostic CreateDiagnostic(
 410        int maximumCells,
 411        int componentId,
 412        long componentVersion,
 413        int incidentEdgeCount,
 414        out bool truncated)
 415    {
 14635416        int addressedCount = BakedSlotCount + DynamicSlotCount;
 14635417        int count = Math.Min(addressedCount, maximumCells);
 14635418        truncated = count < addressedCount;
 14635419        var cells = new NavigationGraphCellDiagnostic[count];
 4319348420        for (int ordinal = 0; ordinal < count; ordinal++)
 421        {
 2145039422            int slot = ordinal < BakedSlotCount
 2145039423                ? ordinal
 2145039424                : _dynamicSlots.GetValueAt(ordinal - BakedSlotCount).Slot;
 2145039425            bool hasCell = TryGetEffectiveCell(slot, out NavigationCell cell);
 2145039426            TryGetPhysicalState(slot, out bool isPresent, out byte obstacleCount);
 2145039427            cells[ordinal] = new NavigationGraphCellDiagnostic(
 2145039428                GetSlotIndex(slot),
 2145039429                slot,
 2145039430                GetSemanticSource(slot),
 2145039431                hasCell,
 2145039432                cell,
 2145039433                isPresent,
 2145039434                obstacleCount);
 435        }
 436
 14635437        return new NavigationGraphMapDiagnostic(
 14635438            MapId,
 14635439            BakeVersion,
 14635440            InstanceVersion,
 14635441            Overlay.HighWaterSequence,
 14635442            PhysicalVersion,
 14635443            componentId,
 14635444            componentVersion,
 14635445            incidentEdgeCount,
 14635446            IsMaterialized,
 14635447            GridIdentity.WorldSpawnToken,
 14635448            GridIdentity.GridSpawnToken,
 14635449            Map.GridBinding.Key,
 14635450            Map.GridBinding.Configuration.TopologyKind,
 14635451            Map.GridBinding.Configuration.StorageKind,
 14635452            LookupKind,
 14635453            BakedSlotCount,
 14635454            DynamicSlotCount,
 14635455            RetainedBytes,
 14635456            LastBaselineAddressCount,
 14635457            LastCopiedSemanticPages,
 14635458            LastCopiedPhysicalPages,
 14635459            cells);
 460    }
 461
 462    private NavigationMapInstance CreateMaterialized(
 463        in NavigationGridBaselineCapture capture,
 464        PersistentIntMap<NavigationPhysicalPage> pages,
 465        int addressCount,
 466        long instanceVersion) =>
 1607467        new NavigationMapInstance(
 1607468            Map,
 1607469            BakeVersion,
 1607470            Overlay,
 1607471            DynamicSlotGeneration,
 1607472            _dynamicSlots,
 1607473            _dynamicSlotIndexes,
 1607474            _nextDynamicSlot,
 1607475            _semanticPages,
 1607476            pages,
 1607477            FillDynamicBaselineCapturedChangeSequences(capture.CapturedChangeSequence),
 1607478            _bakedLookup,
 1607479            _preparedMapRetainedBytes,
 1607480            new NavigationGridGenerationIdentity(
 1607481                capture.WorldSpawnToken,
 1607482                capture.GridIndex,
 1607483                capture.GridSpawnToken,
 1607484                capture.ConfigurationKey),
 1607485            capture.CapturedChangeSequence,
 1607486            capture.GridLastChangeSequence,
 1607487            instanceVersion,
 1607488            SemanticVersion,
 1607489            physicalVersion: instanceVersion,
 1607490            lastBaselineAddressCount: addressCount,
 1607491            lastCopiedSemanticPages: 0,
 1607492            lastCopiedPhysicalPages: pages.Count,
 1607493            dynamicAddresses: _dynamicAddresses);
 494
 495    internal PersistentIntMap<NavigationPhysicalPage> AppendPhysicalBaselinePages(
 496        PersistentIntMap<NavigationPhysicalPage> pages,
 497        ReadOnlySpan<NavigationBaselineVoxelState> states,
 498        long pageVersion)
 499    {
 28094500        for (int i = 0; i < states.Length; i++)
 501        {
 12472502            if (!states[i].IsPresent && states[i].ObstacleCount == 0)
 503                continue;
 11947504            bool found = TryGetSlot(states[i].VoxelIndex, out int slot);
 505            System.Diagnostics.Debug.Assert(found);
 11947506            int pageIndex = slot / NavigationPhysicalPage.SlotCount;
 11947507            if (!pages.TryGetValue(pageIndex, out NavigationPhysicalPage? page))
 508            {
 1611509                page = new NavigationPhysicalPage(pageIndex, pageVersion);
 1611510                pages = pages.Set(pageIndex, page);
 511            }
 11947512            int offset = slot % NavigationPhysicalPage.SlotCount;
 11947513            page!.IsPresent[offset] = states[i].IsPresent;
 11947514            page.ObstacleCounts[offset] = states[i].ObstacleCount;
 515        }
 1575516        return pages;
 517    }
 518
 519    internal void CopyCanonicalAddressChunk(
 520        ref int bakedCursor,
 521        ref int dynamicCursor,
 522        Span<VoxelIndex> destination)
 523    {
 2168765524        ReadOnlySpan<NavigationCellEntry> baked = Map.CellSpan;
 8797682525        for (int i = 0; i < destination.Length; i++)
 526        {
 2230076527            bool hasBaked = bakedCursor < baked.Length;
 2230076528            bool hasDynamic = dynamicCursor < _dynamicSlots.Count;
 2230076529            if (!hasDynamic
 2230076530                || (hasBaked
 2230076531                    && baked[bakedCursor].Index.CompareTo(
 2230076532                        _dynamicSlots.GetKeyAt(dynamicCursor)) < 0))
 533            {
 49729534                destination[i] = baked[bakedCursor++].Index;
 535            }
 536            else
 537            {
 2180347538                destination[i] = _dynamicSlots.GetKeyAt(dynamicCursor++);
 539            }
 540        }
 2168765541    }
 542
 543    internal int CopyCanonicalAddresses(Span<VoxelIndex> destination)
 544    {
 1028545        int count = AddressCount;
 1028546        if (count > destination.Length)
 1547            return 0;
 1027548        int bakedCursor = 0;
 1027549        int dynamicCursor = 0;
 1027550        CopyCanonicalAddressChunk(
 1027551            ref bakedCursor,
 1027552            ref dynamicCursor,
 1027553            destination.Slice(0, count));
 1027554        return count;
 555    }
 556
 557    internal bool TryCopyNewCanonicalAddresses(
 558        NavigationMapInstance previous,
 559        Span<VoxelIndex> destination,
 560        out int count)
 561    {
 36562        int bakedCursor = 0;
 36563        int dynamicCursor = 0;
 36564        count = 0;
 36565        Span<VoxelIndex> slot = stackalloc VoxelIndex[1];
 496566        for (int i = 0; i < AddressCount; i++)
 567        {
 213568            CopyCanonicalAddressChunk(ref bakedCursor, ref dynamicCursor, slot);
 213569            if (previous.TryGetSlot(slot[0], out _))
 570                continue;
 101571            if (count == destination.Length)
 1572                return false;
 100573            destination[count++] = slot[0];
 574        }
 35575        return true;
 576    }
 577
 578    private NavigationMapInstance MakeDormant(long instanceVersion)
 579    {
 286580        if (!IsMaterialized && _physicalPages.Count == 0)
 235581            return this;
 51582        return new NavigationMapInstance(
 51583            Map,
 51584            BakeVersion,
 51585            Overlay,
 51586            DynamicSlotGeneration,
 51587            _dynamicSlots,
 51588            _dynamicSlotIndexes,
 51589            _nextDynamicSlot,
 51590            _semanticPages,
 51591            PersistentIntMap<NavigationPhysicalPage>.Empty,
 51592            _dynamicBaselineCapturedChangeSequences,
 51593            _bakedLookup,
 51594            _preparedMapRetainedBytes,
 51595            default,
 51596            baselineCapturedChangeSequence: 0,
 51597            gridLastChangeSequence: 0,
 51598            instanceVersion,
 51599            SemanticVersion,
 51600            physicalVersion: instanceVersion,
 51601            lastBaselineAddressCount: 0,
 51602            lastCopiedSemanticPages: 0,
 51603            lastCopiedPhysicalPages: _physicalPages.Count,
 51604            dynamicAddresses: _dynamicAddresses);
 605    }
 606
 607    internal bool TryGetDefaultBaselineSeedSlot(
 608        int ordinal,
 609        out NavigationDynamicCellSlot slot,
 610        out bool retain)
 611    {
 103612        if ((uint)ordinal >= (uint)_dynamicSlots.Count)
 613        {
 2614            slot = default;
 2615            retain = false;
 2616            return false;
 617        }
 101618        VoxelIndex index = _dynamicSlots.GetKeyAt(ordinal);
 101619        slot = _dynamicSlots.GetValueAt(ordinal);
 101620        retain = _dynamicAddresses.TryGetValue(index, out _);
 101621        return true;
 622    }
 623
 624    internal bool TryGetDynamicSlot(
 625        VoxelIndex index,
 626        out NavigationDynamicCellSlot slot) =>
 753627        _dynamicSlots.TryGetValue(index, out slot);
 628
 629    internal NavigationMapInstance CreateDefaultBaselineSeed(
 630        long instanceVersion,
 631        PersistentVoxelIndexMap<NavigationDynamicCellSlot> dynamicSlots,
 632        PersistentIntMap<VoxelIndex> dynamicSlotIndexes)
 633    {
 78634        if (!Map.DefaultCell.HasValue)
 1635            return this;
 636
 77637        return new NavigationMapInstance(
 77638            Map,
 77639            BakeVersion,
 77640            Overlay,
 77641            DynamicSlotGeneration,
 77642            dynamicSlots,
 77643            dynamicSlotIndexes,
 77644            _nextDynamicSlot,
 77645            _semanticPages,
 77646            PersistentIntMap<NavigationPhysicalPage>.Empty,
 77647            PersistentIntMap<ulong>.Empty,
 77648            _bakedLookup,
 77649            _preparedMapRetainedBytes,
 77650            default,
 77651            baselineCapturedChangeSequence: 0,
 77652            gridLastChangeSequence: 0,
 77653            instanceVersion,
 77654            SemanticVersion,
 77655            physicalVersion: instanceVersion,
 77656            lastBaselineAddressCount: 0,
 77657            lastCopiedSemanticPages: LastCopiedSemanticPages,
 77658            lastCopiedPhysicalPages: 0,
 77659            dynamicAddresses: _dynamicAddresses);
 660    }
 661
 662    internal NavigationMapInstance AppendDefaultBaselineStates(
 663        NavigationMapInstance source,
 664        ReadOnlySpan<NavigationBaselineVoxelState> states,
 665        ulong capturedChangeSequence,
 666        long instanceVersion)
 667    {
 78668        PersistentVoxelIndexMap<NavigationDynamicCellSlot> dynamicSlots = _dynamicSlots;
 78669        PersistentIntMap<VoxelIndex> dynamicSlotIndexes = _dynamicSlotIndexes;
 78670        PersistentIntMap<NavigationPhysicalPage> physicalPages = _physicalPages;
 78671        PersistentIntMap<ulong> dynamicCapturedChangeSequences =
 78672            _dynamicBaselineCapturedChangeSequences;
 78673        int nextDynamicSlot = _nextDynamicSlot;
 908674        for (int i = 0; i < states.Length; i++)
 675        {
 376676            NavigationBaselineVoxelState state = states[i];
 376677            int slot = _bakedLookup.Find(state.VoxelIndex);
 376678            if (slot < 0
 376679                && dynamicSlots.TryGetValue(
 376680                    state.VoxelIndex,
 376681                    out NavigationDynamicCellSlot existing))
 682            {
 21683                slot = existing.Slot;
 684            }
 376685            if (slot < 0 && state.IsPresent)
 686            {
 176687                if (source._dynamicSlots.TryGetValue(
 176688                        state.VoxelIndex,
 176689                        out NavigationDynamicCellSlot prior))
 690                {
 51691                    slot = prior.Slot;
 692                }
 693                else
 694                {
 125695                    slot = nextDynamicSlot++;
 696                }
 176697                var added = new NavigationDynamicCellSlot(state.VoxelIndex, slot);
 176698                dynamicSlots = dynamicSlots.Set(state.VoxelIndex, added);
 176699                dynamicSlotIndexes = dynamicSlotIndexes.Set(slot, state.VoxelIndex);
 700            }
 376701            if (slot < 0)
 702                continue;
 327703            physicalPages = ApplyPhysicalState(
 327704                physicalPages,
 327705                slot,
 327706                state.IsPresent,
 327707                state.ObstacleCount,
 327708                instanceVersion);
 327709            if (slot >= DynamicSlotBase)
 197710                dynamicCapturedChangeSequences = dynamicCapturedChangeSequences.Set(
 197711                    slot,
 197712                    capturedChangeSequence);
 713        }
 714
 78715        return new NavigationMapInstance(
 78716            Map,
 78717            BakeVersion,
 78718            Overlay,
 78719            DynamicSlotGeneration,
 78720            dynamicSlots,
 78721            dynamicSlotIndexes,
 78722            nextDynamicSlot,
 78723            _semanticPages,
 78724            physicalPages,
 78725            dynamicCapturedChangeSequences,
 78726            _bakedLookup,
 78727            _preparedMapRetainedBytes,
 78728            default,
 78729            baselineCapturedChangeSequence: 0,
 78730            gridLastChangeSequence: 0,
 78731            instanceVersion,
 78732            SemanticVersion,
 78733            physicalVersion: instanceVersion,
 78734            lastBaselineAddressCount: 0,
 78735            lastCopiedSemanticPages: LastCopiedSemanticPages,
 78736            lastCopiedPhysicalPages: physicalPages.Count,
 78737            dynamicAddresses: _dynamicAddresses);
 738    }
 739
 740    internal NavigationMapInstance CompleteDefaultBaseline(
 741        long instanceVersion,
 742        bool hasSameDynamicSlots)
 743    {
 70744        long dynamicSlotGeneration = hasSameDynamicSlots
 70745            ? DynamicSlotGeneration
 70746            : instanceVersion;
 70747        return new NavigationMapInstance(
 70748            Map,
 70749            BakeVersion,
 70750            Overlay,
 70751            dynamicSlotGeneration,
 70752            _dynamicSlots,
 70753            _dynamicSlotIndexes,
 70754            _nextDynamicSlot,
 70755            _semanticPages,
 70756            _physicalPages,
 70757            _dynamicBaselineCapturedChangeSequences,
 70758            _bakedLookup,
 70759            _preparedMapRetainedBytes,
 70760            default,
 70761            baselineCapturedChangeSequence: 0,
 70762            gridLastChangeSequence: 0,
 70763            instanceVersion,
 70764            SemanticVersion,
 70765            physicalVersion: instanceVersion,
 70766            lastBaselineAddressCount: AddressCount,
 70767            lastCopiedSemanticPages: LastCopiedSemanticPages,
 70768            lastCopiedPhysicalPages: _physicalPages.Count,
 70769            dynamicAddresses: _dynamicAddresses);
 770    }
 771
 620772    internal long DefaultBaselineRetainedBytes => checked(
 620773        200L
 620774        + _dynamicSlots.RetainedBytes
 620775        + _dynamicSlotIndexes.RetainedBytes
 620776        + _physicalPages.RetainedBytes
 620777        + ((long)_physicalPages.Count * 320L)
 620778        + _dynamicBaselineCapturedChangeSequences.RetainedBytes);
 779
 618780    internal int DefaultBaselinePersistentPages => checked(
 618781        4
 618782        + _dynamicSlots.PersistentNodeCount
 618783        + _dynamicSlotIndexes.PersistentNodeCount
 618784        + (_physicalPages.PersistentNodeCount * 2)
 618785        + _dynamicBaselineCapturedChangeSequences.PersistentNodeCount);
 786
 787    private NavigationMapInstance WithPhysicalState(
 788        int slot,
 789        bool isPresent,
 790        byte obstacleCount,
 791        long instanceVersion,
 792        ulong gridLastChangeSequence)
 793    {
 3794        PersistentIntMap<NavigationPhysicalPage> pages = ApplyPhysicalState(
 3795            _physicalPages,
 3796            slot,
 3797            isPresent,
 3798            obstacleCount,
 3799            instanceVersion);
 3800        if (ReferenceEquals(pages, _physicalPages))
 1801            return WithGridLastChangeSequence(gridLastChangeSequence, instanceVersion);
 802
 2803        return new NavigationMapInstance(
 2804            Map,
 2805            BakeVersion,
 2806            Overlay,
 2807            DynamicSlotGeneration,
 2808            _dynamicSlots,
 2809            _dynamicSlotIndexes,
 2810            _nextDynamicSlot,
 2811            _semanticPages,
 2812            pages,
 2813            _dynamicBaselineCapturedChangeSequences,
 2814            _bakedLookup,
 2815            _preparedMapRetainedBytes,
 2816            GridIdentity,
 2817            BaselineCapturedChangeSequence,
 2818            gridLastChangeSequence,
 2819            instanceVersion,
 2820            SemanticVersion,
 2821            physicalVersion: instanceVersion,
 2822            lastBaselineAddressCount: 0,
 2823            lastCopiedSemanticPages: 0,
 2824            lastCopiedPhysicalPages: 1,
 2825            dynamicAddresses: _dynamicAddresses);
 826    }
 827
 828    private static PersistentIntMap<NavigationPhysicalPage> ApplyPhysicalState(
 829        PersistentIntMap<NavigationPhysicalPage> pages,
 830        int slot,
 831        bool isPresent,
 832        byte obstacleCount,
 833        long version)
 834    {
 366835        int pageIndex = slot / NavigationPhysicalPage.SlotCount;
 366836        int offset = slot % NavigationPhysicalPage.SlotCount;
 366837        pages.TryGetValue(pageIndex, out NavigationPhysicalPage? current);
 366838        if (current != null
 366839            && current.IsPresent[offset] == isPresent
 366840            && current.ObstacleCounts[offset] == obstacleCount)
 841        {
 23842            return pages;
 843        }
 844
 343845        NavigationPhysicalPage page = current?.Clone(version)
 343846            ?? new NavigationPhysicalPage(pageIndex, version);
 343847        page.IsPresent[offset] = isPresent;
 343848        page.ObstacleCounts[offset] = isPresent ? obstacleCount : (byte)0;
 343849        return pages.Set(pageIndex, page);
 850    }
 851
 852    private NavigationMapInstance ApplyPhysicalSegment(
 853        ReadOnlySpan<GridEventInfo> events,
 854        long instanceVersion)
 855    {
 283856        if (!IsMaterialized || events.IsEmpty)
 223857            return this;
 858
 60859        PersistentIntMap<NavigationPhysicalPage>? pages = null;
 60860        ulong gridLastChangeSequence = GridLastChangeSequence;
 60861        int copiedPhysicalPages = 0;
 294862        for (int i = 0; i < events.Length; i++)
 863        {
 87864            GridEventInfo eventInfo = events[i];
 87865            if (!GridIdentity.Matches(
 87866                    eventInfo.WorldSpawnToken,
 87867                    eventInfo.GridIndex,
 87868                    eventInfo.GridSpawnToken))
 869            {
 870                continue;
 871            }
 67872            if (eventInfo.ChangeSequence > gridLastChangeSequence)
 51873                gridLastChangeSequence = eventInfo.ChangeSequence;
 67874            if (!eventInfo.HasVoxelState
 67875                || !TryGetSlot(eventInfo.VoxelIndex, out int slot)
 67876                || eventInfo.ChangeSequence <= GetBaselineCapturedChangeSequence(slot))
 877            {
 878                continue;
 879            }
 880
 63881            int pageIndex = slot / NavigationPhysicalPage.SlotCount;
 63882            pages ??= _physicalPages;
 63883            pages.TryGetValue(pageIndex, out NavigationPhysicalPage? page);
 63884            if (page == null)
 885            {
 2886                page = new NavigationPhysicalPage(pageIndex, instanceVersion);
 2887                pages = pages.Set(pageIndex, page);
 2888                copiedPhysicalPages++;
 889            }
 61890            else if (_physicalPages.TryGetValue(pageIndex, out NavigationPhysicalPage? original)
 61891                && ReferenceEquals(page, original))
 892            {
 51893                page = page.Clone(instanceVersion);
 51894                pages = pages.Set(pageIndex, page);
 51895                copiedPhysicalPages++;
 896            }
 897
 63898            int offset = slot % NavigationPhysicalPage.SlotCount;
 63899            page.IsPresent[offset] = eventInfo.IsVoxelPresent;
 63900            page.ObstacleCounts[offset] = eventInfo.IsVoxelPresent
 63901                ? eventInfo.ObstacleCount
 63902                : (byte)0;
 903        }
 904
 60905        return pages == null && gridLastChangeSequence == GridLastChangeSequence
 60906            ? this
 60907            : new NavigationMapInstance(
 60908                Map,
 60909                BakeVersion,
 60910                Overlay,
 60911                DynamicSlotGeneration,
 60912                _dynamicSlots,
 60913                _dynamicSlotIndexes,
 60914                _nextDynamicSlot,
 60915                _semanticPages,
 60916                pages ?? _physicalPages,
 60917                _dynamicBaselineCapturedChangeSequences,
 60918                _bakedLookup,
 60919                _preparedMapRetainedBytes,
 60920                GridIdentity,
 60921                BaselineCapturedChangeSequence,
 60922                gridLastChangeSequence,
 60923                instanceVersion,
 60924                SemanticVersion,
 60925                physicalVersion: pages == null ? PhysicalVersion : instanceVersion,
 60926                lastBaselineAddressCount: 0,
 60927                lastCopiedSemanticPages: 0,
 60928                lastCopiedPhysicalPages: copiedPhysicalPages,
 60929                dynamicAddresses: _dynamicAddresses);
 930    }
 931
 932    private static int CountTouchedPages(
 933        VoxelIndex[] addresses,
 934        int count,
 935        PersistentVoxelIndexMap<NavigationDynamicCellSlot> slots)
 936    {
 35937        int pages = 0;
 35938        int priorPage = -1;
 142939        for (int i = 0; i < count; i++)
 940        {
 36941            bool found = slots.TryGetValue(addresses[i], out NavigationDynamicCellSlot slot);
 942            System.Diagnostics.Debug.Assert(found);
 36943            int page = slot.Slot / NavigationPhysicalPage.SlotCount;
 36944            if (page != priorPage)
 945            {
 35946                pages++;
 35947                priorPage = page;
 948            }
 949        }
 35950        return pages;
 951    }
 952
 953    private PersistentIntMap<ulong> FillDynamicBaselineCapturedChangeSequences(
 954        ulong capturedChangeSequence)
 955    {
 1607956        PersistentIntMap<ulong> result = PersistentIntMap<ulong>.Empty;
 3608957        for (int i = 0; i < _dynamicSlots.Count; i++)
 197958            result = result.Set(
 197959                _dynamicSlots.GetValueAt(i).Slot,
 197960                capturedChangeSequence);
 1607961        return result;
 962    }
 963
 964    private ulong GetBaselineCapturedChangeSequence(int slot)
 965    {
 67966        if (slot < BakedSlotCount)
 59967            return BaselineCapturedChangeSequence;
 8968        bool found = _dynamicBaselineCapturedChangeSequences.TryGetValue(
 8969            slot,
 8970            out ulong capturedChangeSequence);
 971        System.Diagnostics.Debug.Assert(found);
 8972        return capturedChangeSequence;
 973    }
 974
 975    private static PersistentIntMap<NavigationSemanticPage> ApplySemanticOperation(
 976        PersistentIntMap<NavigationSemanticPage> pages,
 977        int slot,
 978        NavigationCellOverlayOperation operation,
 979        long version,
 980        out int copiedNodeCount)
 981    {
 16674982        int pageIndex = slot / NavigationSemanticPage.SlotCount;
 983        NavigationSemanticPage page;
 16674984        if (pages.TryGetValue(pageIndex, out NavigationSemanticPage? existing))
 985        {
 16256986            page = existing!.Clone(version);
 987        }
 988        else
 989        {
 418990            page = new NavigationSemanticPage(pageIndex, version);
 991        }
 992
 16674993        int offset = slot % NavigationSemanticPage.SlotCount;
 16674994        page.HasOverride[offset] = operation.Kind == NavigationCellOverlayOperationKind.Set;
 16674995        page.IsSuppressed[offset] = operation.Kind == NavigationCellOverlayOperationKind.Suppress;
 16674996        page.Cells[offset] = operation.Cell;
 16674997        return page.IsEmpty()
 16674998            ? pages.Remove(pageIndex, out copiedNodeCount)
 16674999            : pages.Set(pageIndex, page, out copiedNodeCount);
 1000    }
 1001
 1002    private PersistentIntMap<NavigationPhysicalPage> BuildPhysicalPages(
 1003        ReadOnlySpan<NavigationBaselineVoxelState> states) =>
 9121004        AppendPhysicalBaselinePages(
 9121005            PersistentIntMap<NavigationPhysicalPage>.Empty,
 9121006            states,
 9121007            InstanceVersion);
 1008
 1009    private NavigationSemanticPage? FindSemanticPage(int pageIndex)
 1010    {
 92325501011        _semanticPages.TryGetValue(pageIndex, out NavigationSemanticPage? page);
 92325501012        return page;
 1013    }
 1014
 1015    private NavigationCellSemanticSource GetSemanticSource(int slot)
 1016    {
 21602361017        NavigationSemanticPage? page = FindSemanticPage(slot / NavigationSemanticPage.SlotCount);
 21602361018        int offset = slot % NavigationSemanticPage.SlotCount;
 21602361019        if (page != null && page.IsSuppressed[offset])
 421020            return NavigationCellSemanticSource.OverlaySuppressed;
 21601941021        if (page != null && page.HasOverride[offset])
 1022        {
 21384021023            return slot >= BakedSlotCount
 21384021024                ? NavigationCellSemanticSource.DynamicOverlaySet
 21384021025                : NavigationCellSemanticSource.OverlaySet;
 1026        }
 217921027        if (slot >= BakedSlotCount && Map.DefaultCell.HasValue)
 251028            return NavigationCellSemanticSource.Baked;
 217671029        return slot >= BakedSlotCount
 217671030            ? NavigationCellSemanticSource.DynamicInactive
 217671031            : NavigationCellSemanticSource.Baked;
 1032    }
 1033
 1034    private NavigationPhysicalPage? FindPhysicalPage(int pageIndex)
 1035    {
 31101481036        _physicalPages.TryGetValue(pageIndex, out NavigationPhysicalPage? page);
 31101481037        return page;
 1038    }
 1039
 1040    private static bool IsBroad(GridEventKind kind) =>
 1071041        kind == GridEventKind.WorldReset
 1071042        || kind == GridEventKind.GridAdded
 1071043        || kind == GridEventKind.GridRemoved
 1071044        || kind == GridEventKind.GridChanged;
 1045
 39731046    private long EstimateRetainedBytes() => checked(
 39731047        200L
 39731048        + Overlay.RetainedBytes
 39731049        + _dynamicSlots.RetainedBytes
 39731050        + _dynamicAddresses.RetainedBytes
 39731051        + _dynamicSlotIndexes.RetainedBytes
 39731052        + _semanticPages.RetainedBytes
 39731053        + ((long)_semanticPages.Count * 4_400L)
 39731054        + _physicalPages.RetainedBytes
 39731055        + ((long)_physicalPages.Count * 320L)
 39731056        + _dynamicBaselineCapturedChangeSequences.RetainedBytes
 39731057        + _preparedMapRetainedBytes);
 1058
 1059    private NavigationMapInstance WithGridLastChangeSequence(
 1060        ulong gridLastChangeSequence,
 1061        long instanceVersion)
 1062    {
 51063        if (gridLastChangeSequence <= GridLastChangeSequence)
 11064            return this;
 41065        return new NavigationMapInstance(
 41066            Map,
 41067            BakeVersion,
 41068            Overlay,
 41069            DynamicSlotGeneration,
 41070            _dynamicSlots,
 41071            _dynamicSlotIndexes,
 41072            _nextDynamicSlot,
 41073            _semanticPages,
 41074            _physicalPages,
 41075            _dynamicBaselineCapturedChangeSequences,
 41076            _bakedLookup,
 41077            _preparedMapRetainedBytes,
 41078            GridIdentity,
 41079            BaselineCapturedChangeSequence,
 41080            gridLastChangeSequence,
 41081            instanceVersion,
 41082            SemanticVersion,
 41083            PhysicalVersion,
 41084            lastBaselineAddressCount: 0,
 41085            lastCopiedSemanticPages: 0,
 41086            lastCopiedPhysicalPages: 0,
 41087            dynamicAddresses: _dynamicAddresses);
 1088    }
 1089}

/home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Graph/NavigationMapInstance.NodeRefs.cs

#LineLine coverage
 1//=======================================================================
 2// NavigationMapInstance.NodeRefs.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 GridForge.Spatial;
 9
 10namespace Trailblazer.Pathing;
 11
 12internal sealed partial class NavigationMapInstance
 13{
 14    internal bool TryGetSlotIndex(int slot, out VoxelIndex index)
 15    {
 577617916        if ((uint)slot < (uint)Map.CellSpan.Length)
 17        {
 252846318            index = Map.CellSpan[slot].Index;
 252846319            return true;
 20        }
 21
 324771622        return _dynamicSlotIndexes.TryGetValue(slot, out index);
 23    }
 24}

Methods/Properties

.ctor(Trailblazer.Pathing.NavigationOperationCandidate/MapState,Trailblazer.Pathing.NavigationMapInstance,System.Int64)
.ctor(Trailblazer.Pathing.NavigationOperationCandidate/MapState,Trailblazer.Pathing.NavigationMapInstance,Trailblazer.Pathing.NavigationMapOverlayDelta,System.Int64)
.ctor(Trailblazer.Pathing.NavigationOperationCandidate/MapState,Trailblazer.Pathing.NavigationMapInstance,Trailblazer.Pathing.NavigationOperationFrameChange[],System.Int32,System.String,System.Int64)
get_RetainedBytes()
get_PersistentPageCount()
get_AdditionalExclusiveRetainedBytes()
get_AdditionalExclusivePersistentPages()
Advance(Trailblazer.Pathing.MaintenanceWorkMeter)
AdvanceOverlaySequence(Trailblazer.Pathing.MaintenanceWorkMeter)
CompleteSequenceChange()
FindDelta(System.ReadOnlySpan`1<Trailblazer.Pathing.NavigationMapOverlayDelta>,System.String)
ApplyCellOperation(Trailblazer.Pathing.NavigationCellOverlayOperation)
ShouldAllocateDynamicSlot(Trailblazer.Pathing.NavigationCellOverlayOperationKind,System.Boolean)
HasSameSemanticState(System.Int32,Trailblazer.Pathing.NavigationCellOverlayOperation)
RecordPersistentCopies(System.Int32,System.Int64)
GetAdditionalRootBytes(System.Object,System.Object,System.Int64,System.Int64)
GetAdditionalRootPages(System.Object,System.Object,System.Int32,System.Int32)
.ctor(Trailblazer.Pathing.NavigationMap,System.Int64,Trailblazer.Pathing.NavigationMapOverlayState,System.Int64,Trailblazer.Pathing.PersistentVoxelIndexMap`1<Trailblazer.Pathing.NavigationDynamicCellSlot>,Trailblazer.Pathing.PersistentIntMap`1<GridForge.Spatial.VoxelIndex>,System.Int32,Trailblazer.Pathing.PersistentIntMap`1<Trailblazer.Pathing.NavigationSemanticPage>,Trailblazer.Pathing.PersistentIntMap`1<Trailblazer.Pathing.NavigationPhysicalPage>,Trailblazer.Pathing.PersistentIntMap`1<System.UInt64>,Trailblazer.Pathing.NavigationBakedCellLookup,System.Int64,Trailblazer.Pathing.NavigationGridGenerationIdentity,System.UInt64,System.UInt64,System.Int64,System.Int64,System.Int64,System.Int32,System.Int32,System.Int32,Trailblazer.Pathing.PersistentVoxelIndexMap`1<System.Byte>)
get_MapId()
get_IsMaterialized()
get_BakedSlotCount()
get_DynamicSlotCount()
get_DynamicAddresses()
get_AddressCount()
get_PreparedMapRetainedBytes()
get_BakedCellLookup()
get_LookupKind()
get_PersistentPageCount()
TryGetSlot(GridForge.Spatial.VoxelIndex,System.Int32&)
GetSlotIndex(System.Int32)
TryGetEffectiveCell(System.Int32,Trailblazer.Pathing.NavigationCell&)
TryGetSemanticState(GridForge.Spatial.VoxelIndex,Trailblazer.Pathing.NavigationCellSemanticSource&,System.Boolean&,Trailblazer.Pathing.NavigationCell&)
TryGetPhysicalState(System.Int32,System.Boolean&,System.Byte&)
GetEffectiveMedia(GridForge.Spatial.VoxelIndex)
IsPhysicallyPresent(GridForge.Spatial.VoxelIndex)
GetPageDependency(System.Int32,System.Int64)
Apply(System.Int64,GridForge.Grids.GridEventInfo&,System.Int64)
ApplyBatch(System.Int64,System.ReadOnlySpan`1<GridForge.Grids.GridEventInfo>,System.Boolean,System.Int64)
Materialize(Trailblazer.Pathing.NavigationGridBaselineCapture&,System.Int64)
MaterializeDelta(Trailblazer.Pathing.NavigationMapInstance,Trailblazer.Pathing.NavigationGridBaselineCapture&,System.Int64)
FailClosed(System.Int64)
CreateDiagnostic(System.Int32,System.Int32,System.Int64,System.Int32,System.Boolean&)
CreateMaterialized(Trailblazer.Pathing.NavigationGridBaselineCapture&,Trailblazer.Pathing.PersistentIntMap`1<Trailblazer.Pathing.NavigationPhysicalPage>,System.Int32,System.Int64)
AppendPhysicalBaselinePages(Trailblazer.Pathing.PersistentIntMap`1<Trailblazer.Pathing.NavigationPhysicalPage>,System.ReadOnlySpan`1<GridForge.Grids.NavigationBaselineVoxelState>,System.Int64)
CopyCanonicalAddressChunk(System.Int32&,System.Int32&,System.Span`1<GridForge.Spatial.VoxelIndex>)
CopyCanonicalAddresses(System.Span`1<GridForge.Spatial.VoxelIndex>)
TryCopyNewCanonicalAddresses(Trailblazer.Pathing.NavigationMapInstance,System.Span`1<GridForge.Spatial.VoxelIndex>,System.Int32&)
MakeDormant(System.Int64)
TryGetDefaultBaselineSeedSlot(System.Int32,Trailblazer.Pathing.NavigationDynamicCellSlot&,System.Boolean&)
TryGetDynamicSlot(GridForge.Spatial.VoxelIndex,Trailblazer.Pathing.NavigationDynamicCellSlot&)
CreateDefaultBaselineSeed(System.Int64,Trailblazer.Pathing.PersistentVoxelIndexMap`1<Trailblazer.Pathing.NavigationDynamicCellSlot>,Trailblazer.Pathing.PersistentIntMap`1<GridForge.Spatial.VoxelIndex>)
AppendDefaultBaselineStates(Trailblazer.Pathing.NavigationMapInstance,System.ReadOnlySpan`1<GridForge.Grids.NavigationBaselineVoxelState>,System.UInt64,System.Int64)
CompleteDefaultBaseline(System.Int64,System.Boolean)
get_DefaultBaselineRetainedBytes()
get_DefaultBaselinePersistentPages()
WithPhysicalState(System.Int32,System.Boolean,System.Byte,System.Int64,System.UInt64)
ApplyPhysicalState(Trailblazer.Pathing.PersistentIntMap`1<Trailblazer.Pathing.NavigationPhysicalPage>,System.Int32,System.Boolean,System.Byte,System.Int64)
ApplyPhysicalSegment(System.ReadOnlySpan`1<GridForge.Grids.GridEventInfo>,System.Int64)
CountTouchedPages(GridForge.Spatial.VoxelIndex[],System.Int32,Trailblazer.Pathing.PersistentVoxelIndexMap`1<Trailblazer.Pathing.NavigationDynamicCellSlot>)
FillDynamicBaselineCapturedChangeSequences(System.UInt64)
GetBaselineCapturedChangeSequence(System.Int32)
ApplySemanticOperation(Trailblazer.Pathing.PersistentIntMap`1<Trailblazer.Pathing.NavigationSemanticPage>,System.Int32,Trailblazer.Pathing.NavigationCellOverlayOperation,System.Int64,System.Int32&)
BuildPhysicalPages(System.ReadOnlySpan`1<GridForge.Grids.NavigationBaselineVoxelState>)
FindSemanticPage(System.Int32)
GetSemanticSource(System.Int32)
FindPhysicalPage(System.Int32)
IsBroad(GridForge.Grids.GridEventKind)
EstimateRetainedBytes()
WithGridLastChangeSequence(System.UInt64,System.Int64)
TryGetSlotIndex(System.Int32,GridForge.Spatial.VoxelIndex&)