< Summary

Line coverage
100%
Covered lines: 1262
Uncovered lines: 0
Coverable lines: 1262
Total lines: 2158
Line coverage: 100%
Branch coverage
100%
Covered branches: 524
Total branches: 524
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%88100%
File 1: .ctor(...)100%11100%
File 1: CreateEmpty(...)100%11100%
File 1: get_ExplicitConnections()100%11100%
File 1: get_AutomaticSeams()100%11100%
File 1: get_TransitionPages()100%11100%
File 1: TryGetMapId(...)100%11100%
File 1: TryGetSeamPrism(...)100%44100%
File 1: HasEffectiveCell(...)100%44100%
File 1: TryGetSemanticState(...)100%22100%
File 1: EnumerateOutgoingTransitions(...)100%22100%
File 1: EnumerateOutgoingTransitionCandidates(...)100%22100%
File 1: EnumerateIncomingTransitions(...)100%22100%
File 1: EnumerateIncomingTransitionCandidates(...)100%22100%
File 1: GetPublishedTransition(...)100%11100%
File 1: IsTransitionActive(...)100%66100%
File 1: IsTransitionEndpoint(...)100%66100%
File 1: get_MapCount()100%11100%
File 1: TryGetCoveredAddressGeneration(...)100%22100%
File 1: TryGetCoveredAddressGeneration(...)100%44100%
File 1: TryGetSurfaceComponent(...)100%22100%
File 1: AreInSameSurfaceComponent(...)100%44100%
File 1: get_EmptyMapIndexRetainedBytes()100%11100%
File 1: get_EmptyMapIndexPersistentPageCount()100%11100%
File 1: get_EmptyClosedStructuralComponentsRetainedBytes()100%11100%
File 1: get_EmptyClosedStructuralComponentsPersistentPageCount()100%11100%
File 1: get_LeaseCount()100%11100%
File 1: GetInstance(...)100%11100%
File 1: IsWithinDynamicSlotCapacity(...)100%66100%
File 1: Checkout()100%11100%
File 1: Return()100%11100%
File 1: TryGetMap(...)100%11100%
File 1: IsSurfaceAddressClosed(...)100%66100%
File 1: IsSurfaceComponentClosed(...)100%44100%
File 1: WithSurfaceComponents(...)100%22100%
File 1: WithAutomaticSeams(...)100%22100%
File 1: WithTransitionPublication(...)100%44100%
File 1: WithClosedStructuralComponents(...)100%88100%
File 1: WithOwnedStructuralClosure(...)100%44100%
File 1: WithStructuralClosureFrom(...)100%11100%
File 1: get_HasClosedStructuralScope()100%44100%
File 1: get_ClosedStructuralComponents()100%11100%
File 1: RetainsClosedComponentRoot(...)100%22100%
File 1: GetClosedRootRetainedBytes()100%11100%
File 1: GetClosedRootPersistentPages()100%11100%
File 1: GetAdditionalClosedRootRetainedBytes(...)100%44100%
File 1: GetAdditionalClosedRootPersistentPages(...)100%44100%
File 1: get_AreAllStructuralComponentsClosed()100%11100%
File 1: ReopenStructuralScopes(...)100%66100%
File 1: CaptureMaintenanceSnapshot(...)100%7676100%
File 1: TryAddBaselineRebuild(...)100%88100%
File 1: RemoveBaselineRebuild(...)100%11100%
File 1: GetBaselineRebuildRegistryFootprint(...)100%44100%
File 1: ApplyMaintenanceSnapshot(...)100%2626100%
File 1: WithAreaCatalog(...)100%22100%
File 1: WithGraphVersion(...)100%22100%
File 1: TryGetDependencyStamp(...)100%11100%
File 1: TryGetDependencyStamp(...)100%2626100%
File 1: TryGetComponentDependency(...)100%44100%
File 1: TryGetPageDependency(...)100%11100%
File 1: TryGetPageDependency(...)100%1010100%
File 1: IsDependencyCurrent(...)100%2020100%
File 1: BuildMapIndex(...)100%22100%
File 1: FindMapOrdinal(...)100%66100%
File 1: CollectAffectedMaps(...)100%2020100%
File 1: MarkOperationChanges(...)100%88100%
File 1: MarkMapId(...)100%11100%
File 1: MarkConfiguration(...)100%22100%
File 1: TryMarkOrdinal(...)100%44100%
File 1: ContainsScope(...)100%44100%
File 1: EventsRequireBaseline(...)100%1414100%
File 1: IsOperationChanged(...)100%1212100%
File 1: IsCellOverlayOnlyChanged(...)100%1212100%
File 2: TryGetNodeRef(...)100%66100%
File 2: TryGetNodeRef(...)100%11100%
File 2: TryGetNodeAddress(...)100%22100%
File 2: TryGetNodeState(...)100%11100%
File 2: TryGetNodeState(...)100%66100%
File 2: TryGetRawNodeState(...)100%11100%
File 2: TryGetRawNodeState(...)100%44100%
File 2: GetCompleteDirectionCount(...)100%22100%
File 2: TryGetCompleteNeighbor(...)100%88100%
File 2: TryGetMediumStateRef(...)100%88100%
File 2: TryGetStructuralMediumStateRef(...)100%88100%
File 2: GetPrimaryDirectionCount(...)100%22100%
File 2: TryGetStructuralPrimaryMediumNeighbor(...)100%44100%
File 2: TryGetPrimaryNeighbor(...)100%66100%
File 2: EnumerateNativeSurfaceEdges(...)100%66100%
File 2: EnumerateStructuralNativeSurfaceEdges(...)100%22100%
File 2: EnumerateSurfaceEdges(...)100%11100%
File 2: EnumerateIncomingSurfaceEdges(...)100%11100%
File 2: EnumerateStructuralSurfaceEdges(...)100%11100%
File 2: EnumerateIncomingStructuralSurfaceEdges(...)100%11100%
File 2: EnumerateIncomingExplicitSurfaceEdges(...)100%11100%
File 2: TryGetNodeLocation(...)100%66100%
File 3: .ctor(...)100%11100%
File 3: get_IsComplete()100%11100%
File 3: get_RetainedBytes()100%88100%
File 3: get_PersistentPageCount()100%22100%
File 3: GetComposeAdditionalRetainedBytes()100%44100%
File 3: GetComposeAdditionalPersistentPages()100%44100%
File 3: Advance(...)100%1414100%
File 3: PrepareState(...)100%2424100%
File 3: AdvanceComposeAndAttach(...)100%2222100%
File 3: PrepareRemoval(...)100%88100%
File 3: ResetItem()100%11100%
File 3: RecordPersistentCopies(...)100%11100%

File(s)

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

#LineLine coverage
 1//=======================================================================
 2// NavigationWorldGraph.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.Threading;
 10using GridForge.Configuration;
 11using GridForge.Grids;
 12using GridForge.Grids.Topology;
 13using GridForge.Spatial;
 14
 15namespace Trailblazer.Pathing;
 16
 17/// <summary>Stores one immutable context-owned navigation graph root.</summary>
 18internal sealed partial class NavigationWorldGraph
 19{
 20    internal const long BaseRetainedBytes = 128L;
 21
 22    private readonly NavigationInstanceDirectory _instances;
 23    private readonly PersistentGridConfigurationMap<string> _mapIndex;
 24    private readonly NavigationSurfaceComponentKeySet _closedStructuralComponents;
 25    private readonly NavigationSurfaceComponentKeySet _additionalClosedStructuralComponents;
 26    private readonly bool _allStructuralComponentsClosed;
 27    private readonly NavigationExplicitConnectionIndex _explicitConnections;
 28    private readonly NavigationAutomaticSeamIndex _automaticSeams;
 29    private readonly NavigationTransitionPageRoot _transitionPages;
 30    private int _leaseCount;
 31
 64432    internal NavigationWorldGraph(
 64433        long graphVersion,
 64434        NavigationMapInstance[] instances,
 64435        NavigationAreaCatalog? areaCatalog = null,
 64436        NavigationExplicitConnectionIndex? explicitConnections = null,
 64437        NavigationSurfaceComponentIndex? surfaceComponents = null)
 38    {
 64439        GraphVersion = graphVersion;
 64440        _instances = NavigationInstanceDirectory.Create(instances);
 64441        AreaCatalog = areaCatalog ?? NavigationAreaCatalog.Empty;
 64442        _mapIndex = BuildMapIndex(instances);
 64443        _explicitConnections = explicitConnections ?? NavigationExplicitConnectionIndex.Empty;
 64444        _automaticSeams = NavigationAutomaticSeamIndex.Empty;
 64445        SurfaceComponents = surfaceComponents ?? NavigationSurfaceComponentIndex.Empty;
 64446        _transitionPages = NavigationTransitionPageRoot.Empty;
 64447        TransitionRules = NavigationTransitionRuleTable.Empty;
 64448        _closedStructuralComponents = NavigationSurfaceComponentKeySet.Empty;
 64449        _additionalClosedStructuralComponents = NavigationSurfaceComponentKeySet.Empty;
 64450        _allStructuralComponentsClosed = false;
 64451        long bytes = checked(
 64452            BaseRetainedBytes
 64453            + _instances.RetainedBytes
 64454            + _mapIndex.RetainedBytes
 64455            + _closedStructuralComponents.RetainedBytes
 64456            + SurfaceComponents.RetainedBytes
 64457            + _explicitConnections.RetainedBytes
 64458            + _automaticSeams.RetainedBytes
 64459            + _transitionPages.RetainedBytes
 64460            + TransitionRules.RetainedBytes
 64461            + AreaCatalog.RetainedBytes);
 64462        PersistentPageCount = _instances.PersistentPageCount
 64463            + 1 + _mapIndex.Count
 64464            + _closedStructuralComponents.PersistentPageCount
 64465            + SurfaceComponents.PersistentPageCount
 64466            + _explicitConnections.PersistentPageCount
 64467            + _automaticSeams.PersistentPageCount
 64468            + _transitionPages.PersistentPageCount
 64469            + TransitionRules.PersistentPageCount
 64470            + AreaCatalog.PersistentPageCount;
 259471        for (int i = 0; i < instances.Length; i++)
 72        {
 65373            bytes = checked(bytes + instances[i].RetainedBytes);
 65374            PersistentPageCount += instances[i].PersistentPageCount;
 75        }
 64476        RetainedBytes = bytes;
 64477    }
 78
 829579    private NavigationWorldGraph(
 829580        long graphVersion,
 829581        NavigationInstanceDirectory instances,
 829582        NavigationAreaCatalog areaCatalog,
 829583        PersistentGridConfigurationMap<string> mapIndex,
 829584        NavigationSurfaceComponentIndex surfaceComponents,
 829585        NavigationExplicitConnectionIndex explicitConnections,
 829586        NavigationAutomaticSeamIndex automaticSeams,
 829587        NavigationTransitionPageRoot transitionPages,
 829588        NavigationTransitionRuleTable transitionRules,
 829589        NavigationSurfaceComponentKeySet closedStructuralComponents,
 829590        NavigationSurfaceComponentKeySet additionalClosedStructuralComponents,
 829591        bool allStructuralComponentsClosed,
 829592        long retainedBytes,
 829593        int persistentPageCount)
 94    {
 829595        GraphVersion = graphVersion;
 829596        _instances = instances;
 829597        AreaCatalog = areaCatalog;
 829598        _mapIndex = mapIndex;
 829599        SurfaceComponents = surfaceComponents;
 8295100        _explicitConnections = explicitConnections;
 8295101        _automaticSeams = automaticSeams;
 8295102        _transitionPages = transitionPages;
 8295103        TransitionRules = transitionRules;
 8295104        _closedStructuralComponents = closedStructuralComponents;
 8295105        _additionalClosedStructuralComponents = additionalClosedStructuralComponents;
 8295106        _allStructuralComponentsClosed = allStructuralComponentsClosed;
 8295107        RetainedBytes = retainedBytes;
 8295108        PersistentPageCount = persistentPageCount;
 8295109    }
 110
 111    internal static NavigationWorldGraph Empty { get; } = new(0, Array.Empty<NavigationMapInstance>());
 112
 113    internal static NavigationWorldGraph CreateEmpty(long graphVersion) =>
 39114        new(graphVersion, Array.Empty<NavigationMapInstance>());
 115
 116    internal long GraphVersion { get; }
 117
 118    internal NavigationAreaCatalog AreaCatalog { get; }
 119
 120    internal NavigationSurfaceComponentIndex SurfaceComponents { get; }
 121
 762762122    internal NavigationExplicitConnectionIndex ExplicitConnections => _explicitConnections;
 123
 605201124    internal NavigationAutomaticSeamIndex AutomaticSeams => _automaticSeams;
 125
 126    internal NavigationTransitionRuleTable TransitionRules { get; }
 127
 4133128    internal NavigationTransitionPageRoot TransitionPages => _transitionPages;
 129
 130    internal bool TryGetMapId(GridConfigurationKey key, out string mapId) =>
 98776131        _mapIndex.TryGetValue(key, out mapId!);
 132
 133    internal bool TryGetSeamPrism(
 134        NavigationCellAddress address,
 135        out GridCellPrism prism)
 136    {
 294350137        if (_instances.TryGet(address.MapId, out NavigationMapInstance instance)
 294350138            && instance.Map.GridBinding.TryGetCellPrism(address.Index, out prism))
 139        {
 294349140            return true;
 141        }
 1142        prism = default;
 1143        return false;
 144    }
 145
 146    internal bool HasEffectiveCell(NavigationCellAddress address) =>
 2540247147        _instances.TryGet(address.MapId, out NavigationMapInstance instance)
 2540247148        && instance.TryGetSlot(address.Index, out int slot)
 2540247149        && instance.TryGetEffectiveCell(slot, out _);
 150
 151    internal bool TryGetSemanticState(
 152        NavigationCellAddress address,
 153        out NavigationCellSemanticSource source,
 154        out bool hasCell,
 155        out NavigationCell cell)
 156    {
 158075157        if (_instances.TryGet(address.MapId, out NavigationMapInstance instance))
 158        {
 113968159            return instance.TryGetSemanticState(
 113968160                address.Index,
 113968161                out source,
 113968162                out hasCell,
 113968163                out cell);
 164        }
 44107165        source = default;
 44107166        hasCell = false;
 44107167        cell = default;
 44107168        return false;
 169    }
 170
 171    internal NavigationTransitionPage.Enumerator EnumerateOutgoingTransitions(
 172        NavigationMediumStateRef source)
 173    {
 174        System.Diagnostics.Debug.Assert(
 175            TryGetNodeLocation(source.Node, out _, out _),
 176            "transition enumeration receives a state owned by this immutable graph");
 11177        NavigationMapInstance instance = _instances.Get(source.Node.MapOrdinal);
 11178        _transitionPages.TryGet(
 11179            new NavigationTransitionPageAddress(
 11180                instance.MapId,
 11181                source.Node.CellSlot / NavigationSemanticPage.SlotCount),
 11182            out NavigationTransitionPage page);
 11183        return page?.GetOutgoingEnumerator(this, source) ?? default;
 184    }
 185
 186    internal NavigationTransitionPage.Enumerator EnumerateOutgoingTransitionCandidates(
 187        NavigationMediumStateRef source)
 188    {
 189        System.Diagnostics.Debug.Assert(
 190            TryGetNodeLocation(source.Node, out _, out _),
 191            "transition enumeration receives a state owned by this immutable graph");
 231192        NavigationMapInstance instance = _instances.Get(source.Node.MapOrdinal);
 231193        _transitionPages.TryGet(
 231194            new NavigationTransitionPageAddress(
 231195                instance.MapId,
 231196                source.Node.CellSlot / NavigationSemanticPage.SlotCount),
 231197            out NavigationTransitionPage page);
 231198        return page?.GetOutgoingCandidateEnumerator(this, source) ?? default;
 199    }
 200
 201    internal NavigationTransitionPage.Enumerator EnumerateIncomingTransitions(
 202        NavigationMediumStateRef destination)
 203    {
 204        System.Diagnostics.Debug.Assert(
 205            TryGetNodeLocation(destination.Node, out _, out _),
 206            "transition enumeration receives a state owned by this immutable graph");
 6207        NavigationMapInstance instance = _instances.Get(destination.Node.MapOrdinal);
 6208        _transitionPages.TryGet(
 6209            new NavigationTransitionPageAddress(
 6210                instance.MapId,
 6211                destination.Node.CellSlot / NavigationSemanticPage.SlotCount),
 6212            out NavigationTransitionPage page);
 6213        return page?.GetIncomingEnumerator(this, destination) ?? default;
 214    }
 215
 216    internal NavigationTransitionPage.Enumerator EnumerateIncomingTransitionCandidates(
 217        NavigationMediumStateRef destination)
 218    {
 219        System.Diagnostics.Debug.Assert(
 220            TryGetNodeLocation(destination.Node, out _, out _),
 221            "transition enumeration receives a state owned by this immutable graph");
 45222        NavigationMapInstance instance = _instances.Get(destination.Node.MapOrdinal);
 45223        _transitionPages.TryGet(
 45224            new NavigationTransitionPageAddress(
 45225                instance.MapId,
 45226                destination.Node.CellSlot / NavigationSemanticPage.SlotCount),
 45227            out NavigationTransitionPage page);
 45228        return page?.GetIncomingCandidateEnumerator(this, destination) ?? default;
 229    }
 230
 231    internal NavigationPublishedTransition GetPublishedTransition(
 232        NavigationIncomingTransitionRef incoming)
 233    {
 64234        bool pageFound = _transitionPages.TryGet(
 64235            incoming.SourcePage,
 64236            out NavigationTransitionPage page);
 237        System.Diagnostics.Debug.Assert(pageFound,
 238            "incoming transition references retain their exact immutable source page");
 64239        NavigationPublishedTransition transition = default;
 64240        bool transitionFound = page.TryGetOutgoing(incoming.Owner, out transition);
 241        System.Diagnostics.Debug.Assert(transitionFound,
 242            "incoming transition references retain their exact immutable owner");
 64243        return transition;
 244    }
 245
 246    internal bool IsTransitionActive(
 247        NavigationPublishedTransition transition,
 248        NavigationMediumStateRef state,
 249        bool outgoing)
 250    {
 67251        if (!TryGetMediumStateRef(
 67252                transition.SourceAddress,
 67253                transition.Definition.SourceMedium,
 67254                out NavigationMediumStateRef source)
 67255            || !TryGetMediumStateRef(
 67256                transition.Definition.Destination,
 67257                transition.Definition.DestinationMedium,
 67258                out NavigationMediumStateRef destination))
 259        {
 2260            return false;
 261        }
 65262        return outgoing ? source.Equals(state) : destination.Equals(state);
 263    }
 264
 265    internal bool IsTransitionEndpoint(
 266        NavigationPublishedTransition transition,
 267        NavigationMediumStateRef state,
 268        bool outgoing)
 269    {
 289270        bool addressFound = TryGetNodeAddress(state.Node, out NavigationCellAddress address);
 271        System.Diagnostics.Debug.Assert(addressFound,
 272            "transition endpoint checks receive a state owned by this immutable graph");
 289273        return outgoing
 289274            ? state.Medium == transition.Definition.SourceMedium
 289275                && address.Equals(transition.SourceAddress)
 289276            : state.Medium == transition.Definition.DestinationMedium
 289277                && address.Equals(transition.Definition.Destination);
 278    }
 279
 55687280    internal int MapCount => _instances.Count;
 281
 282    internal bool TryGetCoveredAddressGeneration(
 283        int configurationOrdinal,
 284        out string mapId,
 285        out GridCoveredAddressGeneration generation)
 286    {
 949287        if ((uint)configurationOrdinal >= (uint)_mapIndex.Count)
 288        {
 1289            mapId = string.Empty;
 1290            generation = default;
 1291            return false;
 292        }
 948293        mapId = _mapIndex.GetValueAt(configurationOrdinal);
 948294        return TryGetCoveredAddressGeneration(mapId, out generation);
 295    }
 296
 297    internal bool TryGetCoveredAddressGeneration(
 298        string mapId,
 299        out GridCoveredAddressGeneration generation)
 300    {
 2195301        if (_instances.TryGet(mapId, out NavigationMapInstance instance)
 2195302            && instance.IsMaterialized)
 303        {
 2193304            NavigationGridGenerationIdentity identity = instance.GridIdentity;
 2193305            generation = new GridCoveredAddressGeneration(
 2193306                identity.ConfigurationKey,
 2193307                identity.GridIndex,
 2193308                identity.GridSpawnToken,
 2193309                instance.GridLastChangeSequence);
 2193310            return true;
 311        }
 2312        generation = default;
 2313        return false;
 314    }
 315
 316    internal bool TryGetSurfaceComponent(
 317        NavigationCellAddress address,
 318        TraversalMedium medium,
 319        out NavigationSurfaceComponentKey key,
 320        out long version)
 321    {
 2333287322        if (SurfaceComponents.TryGet(address, medium, out NavigationSurfaceComponent component))
 323        {
 2192959324            key = component.Key;
 2192959325            version = component.Version;
 2192959326            return true;
 327        }
 140328328        key = default;
 140328329        version = 0;
 140328330        return false;
 331    }
 332
 333    internal bool AreInSameSurfaceComponent(
 334        NavigationCellAddress left,
 335        TraversalMedium leftMedium,
 336        NavigationCellAddress right,
 337        TraversalMedium rightMedium) =>
 976338        SurfaceComponents.TryGet(left, leftMedium, out NavigationSurfaceComponent leftComponent)
 976339        && SurfaceComponents.TryGet(right, rightMedium, out NavigationSurfaceComponent rightComponent)
 976340        && leftComponent.Key.Equals(rightComponent.Key);
 341
 342    internal long RetainedBytes { get; }
 343
 344    internal int PersistentPageCount { get; }
 345
 346    internal static long EmptyMapIndexRetainedBytes =>
 1347        PersistentGridConfigurationMap<string>.Empty.RetainedBytes;
 348
 1349    internal static int EmptyMapIndexPersistentPageCount => 1;
 350
 351    internal static long EmptyClosedStructuralComponentsRetainedBytes =>
 1352        NavigationSurfaceComponentKeySet.Empty.RetainedBytes;
 353
 354    internal static int EmptyClosedStructuralComponentsPersistentPageCount =>
 1355        NavigationSurfaceComponentKeySet.Empty.PersistentPageCount;
 356
 30842357    internal int LeaseCount => Volatile.Read(ref _leaseCount);
 358
 43071359    internal NavigationMapInstance GetInstance(int mapOrdinal) => _instances.Get(mapOrdinal);
 360
 361    internal bool IsWithinDynamicSlotCapacity(int maximumPerMap, int maximumTotal)
 362    {
 21334363        int total = 0;
 139732364        for (int i = 0; i < _instances.Count; i++)
 365        {
 48549366            int count = _instances.Get(i).DynamicSlotCount;
 48549367            if (count > maximumPerMap || count > maximumTotal - total)
 17368                return false;
 48532369            total += count;
 370        }
 21317371        return true;
 372    }
 373
 9424374    internal void Checkout() => Interlocked.Increment(ref _leaseCount);
 375
 9423376    internal void Return() => Interlocked.Decrement(ref _leaseCount);
 377
 378    internal bool TryGetMap(string mapId, out NavigationMapInstance instance) =>
 109352379        _instances.TryGet(mapId, out instance);
 380
 381    internal bool IsSurfaceAddressClosed(
 382        NavigationCellAddress address,
 383        TraversalMedium medium) =>
 963961384        _allStructuralComponentsClosed
 963961385        || (SurfaceComponents.TryGet(
 963961386                address,
 963961387                medium,
 963961388                out NavigationSurfaceComponent component)
 963961389            && (_closedStructuralComponents.Contains(component.Key)
 963961390                || _additionalClosedStructuralComponents.Contains(component.Key)));
 391
 392    internal bool IsSurfaceComponentClosed(NavigationSurfaceComponentKey key) =>
 35770393        _allStructuralComponentsClosed
 35770394        || _closedStructuralComponents.Contains(key)
 35770395        || _additionalClosedStructuralComponents.Contains(key);
 396
 397    internal NavigationWorldGraph WithSurfaceComponents(
 398        NavigationSurfaceComponentIndex surfaceComponents)
 399    {
 1701400        if (ReferenceEquals(surfaceComponents, SurfaceComponents))
 130401            return this;
 1571402        return new NavigationWorldGraph(
 1571403            GraphVersion,
 1571404            _instances,
 1571405            AreaCatalog,
 1571406            _mapIndex,
 1571407            surfaceComponents,
 1571408            _explicitConnections,
 1571409            _automaticSeams,
 1571410            _transitionPages,
 1571411            TransitionRules,
 1571412            _closedStructuralComponents,
 1571413            _additionalClosedStructuralComponents,
 1571414            _allStructuralComponentsClosed,
 1571415            checked(RetainedBytes - SurfaceComponents.RetainedBytes
 1571416                + surfaceComponents.RetainedBytes),
 1571417            PersistentPageCount - SurfaceComponents.PersistentPageCount
 1571418                + surfaceComponents.PersistentPageCount);
 419    }
 420
 421    internal NavigationWorldGraph WithAutomaticSeams(NavigationAutomaticSeamIndex seams)
 422    {
 1201423        if (ReferenceEquals(seams, _automaticSeams))
 1009424            return this;
 192425        return new NavigationWorldGraph(
 192426            GraphVersion,
 192427            _instances,
 192428            AreaCatalog,
 192429            _mapIndex,
 192430            SurfaceComponents,
 192431            _explicitConnections,
 192432            seams,
 192433            _transitionPages,
 192434            TransitionRules,
 192435            _closedStructuralComponents,
 192436            _additionalClosedStructuralComponents,
 192437            _allStructuralComponentsClosed,
 192438            checked(RetainedBytes - _automaticSeams.RetainedBytes + seams.RetainedBytes),
 192439            PersistentPageCount - _automaticSeams.PersistentPageCount
 192440                + seams.PersistentPageCount);
 441    }
 442
 443    internal NavigationWorldGraph WithTransitionPublication(
 444        NavigationTransitionPageRoot pages,
 445        NavigationTransitionRuleTable rules)
 446    {
 2998447        if (ReferenceEquals(pages, _transitionPages)
 2998448            && ReferenceEquals(rules, TransitionRules))
 449        {
 2862450            return this;
 451        }
 136452        long priorBytes = checked(
 136453            _transitionPages.RetainedBytes
 136454            + TransitionRules.RetainedBytes);
 136455        long nextBytes = checked(
 136456            pages.RetainedBytes
 136457            + rules.RetainedBytes);
 136458        int priorPages = checked(
 136459            _transitionPages.PersistentPageCount
 136460            + TransitionRules.PersistentPageCount);
 136461        int nextPages = checked(
 136462            pages.PersistentPageCount
 136463            + rules.PersistentPageCount);
 136464        return new NavigationWorldGraph(
 136465            GraphVersion,
 136466            _instances,
 136467            AreaCatalog,
 136468            _mapIndex,
 136469            SurfaceComponents,
 136470            _explicitConnections,
 136471            _automaticSeams,
 136472            pages,
 136473            rules,
 136474            _closedStructuralComponents,
 136475            _additionalClosedStructuralComponents,
 136476            _allStructuralComponentsClosed,
 136477            checked(RetainedBytes - priorBytes + nextBytes),
 136478            PersistentPageCount - priorPages + nextPages);
 479    }
 480
 481    internal NavigationWorldGraph WithClosedStructuralComponents(
 482        NavigationSurfaceComponentKeySet closed,
 483        bool closeAllStructuralComponents,
 484        long graphVersion)
 485    {
 3448486        if (ReferenceEquals(closed, _closedStructuralComponents)
 3448487            && ReferenceEquals(
 3448488                _additionalClosedStructuralComponents,
 3448489                NavigationSurfaceComponentKeySet.Empty)
 3448490            && closeAllStructuralComponents == _allStructuralComponentsClosed
 3448491            && graphVersion == GraphVersion)
 492        {
 220493            return this;
 494        }
 3228495        return new NavigationWorldGraph(
 3228496            graphVersion,
 3228497            _instances,
 3228498            AreaCatalog,
 3228499            _mapIndex,
 3228500            SurfaceComponents,
 3228501            _explicitConnections,
 3228502            _automaticSeams,
 3228503            _transitionPages,
 3228504            TransitionRules,
 3228505            closed,
 3228506            NavigationSurfaceComponentKeySet.Empty,
 3228507            closeAllStructuralComponents,
 3228508            checked(RetainedBytes - GetClosedRootRetainedBytes()
 3228509                + closed.RetainedBytes),
 3228510            PersistentPageCount - GetClosedRootPersistentPages()
 3228511                + closed.PersistentPageCount);
 512    }
 513
 514    internal NavigationWorldGraph WithOwnedStructuralClosure(
 515        NavigationSurfaceComponentKeySet baseline,
 516        NavigationSurfaceComponentKeySet affected,
 517        bool closeAllStructuralComponents,
 518        long graphVersion)
 519    {
 756520        if (closeAllStructuralComponents)
 521        {
 409522            return WithClosedStructuralComponents(
 409523                NavigationSurfaceComponentKeySet.Empty,
 409524                true,
 409525                graphVersion);
 526        }
 347527        NavigationSurfaceComponentKeySet additional = ReferenceEquals(baseline, affected)
 347528            ? NavigationSurfaceComponentKeySet.Empty
 347529            : affected;
 347530        return new NavigationWorldGraph(
 347531            graphVersion,
 347532            _instances,
 347533            AreaCatalog,
 347534            _mapIndex,
 347535            SurfaceComponents,
 347536            _explicitConnections,
 347537            _automaticSeams,
 347538            _transitionPages,
 347539            TransitionRules,
 347540            baseline,
 347541            additional,
 347542            false,
 347543            checked(RetainedBytes - GetClosedRootRetainedBytes()
 347544                + baseline.RetainedBytes
 347545                + GetAdditionalClosedRootRetainedBytes(baseline, additional)),
 347546            PersistentPageCount - GetClosedRootPersistentPages()
 347547                + baseline.PersistentPageCount
 347548                + GetAdditionalClosedRootPersistentPages(baseline, additional));
 549    }
 550
 551    internal NavigationWorldGraph WithStructuralClosureFrom(
 552        NavigationWorldGraph owner,
 553        long graphVersion) =>
 206554        new(
 206555            graphVersion,
 206556            _instances,
 206557            AreaCatalog,
 206558            _mapIndex,
 206559            SurfaceComponents,
 206560            _explicitConnections,
 206561            _automaticSeams,
 206562            _transitionPages,
 206563            TransitionRules,
 206564            owner._closedStructuralComponents,
 206565            owner._additionalClosedStructuralComponents,
 206566            owner._allStructuralComponentsClosed,
 206567            checked(RetainedBytes - GetClosedRootRetainedBytes()
 206568                + owner._closedStructuralComponents.RetainedBytes
 206569                + GetAdditionalClosedRootRetainedBytes(
 206570                    owner._closedStructuralComponents,
 206571                    owner._additionalClosedStructuralComponents)),
 206572            PersistentPageCount - GetClosedRootPersistentPages()
 206573                + owner._closedStructuralComponents.PersistentPageCount
 206574                + GetAdditionalClosedRootPersistentPages(
 206575                    owner._closedStructuralComponents,
 206576                    owner._additionalClosedStructuralComponents));
 577
 578    internal bool HasClosedStructuralScope =>
 17669579        _allStructuralComponentsClosed
 17669580        || _closedStructuralComponents.Count != 0
 17669581        || _additionalClosedStructuralComponents.Count != 0;
 582
 583    internal NavigationSurfaceComponentKeySet ClosedStructuralComponents =>
 516584        _closedStructuralComponents;
 585
 586    internal bool RetainsClosedComponentRoot(NavigationSurfaceComponentKeySet root) =>
 24587        ReferenceEquals(root, _closedStructuralComponents)
 24588        || ReferenceEquals(root, _additionalClosedStructuralComponents);
 589
 3831590    private long GetClosedRootRetainedBytes() => checked(
 3831591        _closedStructuralComponents.RetainedBytes
 3831592        + GetAdditionalClosedRootRetainedBytes(
 3831593            _closedStructuralComponents,
 3831594            _additionalClosedStructuralComponents));
 595
 3831596    private int GetClosedRootPersistentPages() => checked(
 3831597        _closedStructuralComponents.PersistentPageCount
 3831598        + GetAdditionalClosedRootPersistentPages(
 3831599            _closedStructuralComponents,
 3831600            _additionalClosedStructuralComponents));
 601
 602    private static long GetAdditionalClosedRootRetainedBytes(
 603        NavigationSurfaceComponentKeySet baseline,
 604        NavigationSurfaceComponentKeySet additional) =>
 4384605        ReferenceEquals(additional, NavigationSurfaceComponentKeySet.Empty)
 4384606        || ReferenceEquals(additional, baseline)
 4384607            ? 0L
 4384608            : additional.RetainedBytes;
 609
 610    private static int GetAdditionalClosedRootPersistentPages(
 611        NavigationSurfaceComponentKeySet baseline,
 612        NavigationSurfaceComponentKeySet additional) =>
 4384613        ReferenceEquals(additional, NavigationSurfaceComponentKeySet.Empty)
 4384614        || ReferenceEquals(additional, baseline)
 4384615            ? 0
 4384616            : additional.PersistentPageCount;
 617
 886618    internal bool AreAllStructuralComponentsClosed => _allStructuralComponentsClosed;
 619
 620    internal NavigationWorldGraph ReopenStructuralScopes(long graphVersion)
 621    {
 55622        if (!_allStructuralComponentsClosed
 55623            && _closedStructuralComponents.Count == 0
 55624            && _additionalClosedStructuralComponents.Count == 0)
 5625            return this;
 50626        NavigationSurfaceComponentKeySet open = NavigationSurfaceComponentKeySet.Empty;
 50627        return new NavigationWorldGraph(
 50628            graphVersion,
 50629            _instances,
 50630            AreaCatalog,
 50631            _mapIndex,
 50632            SurfaceComponents,
 50633            _explicitConnections,
 50634            _automaticSeams,
 50635            _transitionPages,
 50636            TransitionRules,
 50637            open,
 50638            NavigationSurfaceComponentKeySet.Empty,
 50639            false,
 50640            checked(RetainedBytes - GetClosedRootRetainedBytes() + open.RetainedBytes),
 50641            PersistentPageCount - GetClosedRootPersistentPages()
 50642                + open.PersistentPageCount);
 643    }
 644
 645    internal int CaptureMaintenanceSnapshot(
 646        GridWorld world,
 647        NavigationWorldGraph previousGraph,
 648        ReadOnlySpan<GridEventInfo> events,
 649        ReadOnlySpan<NavigationGridChangeScope> resnapshotScopes,
 650        bool resnapshotAll,
 651        ReadOnlySpan<NavigationGridChangeScope> blockedScopes,
 652        bool blockAll,
 653        NavigationOperationFrameChange[] changes,
 654        int changeCount,
 655        MaintenanceWorkMeter maintenanceMeter,
 656        long maximumActiveSnapshotBytes,
 657        int maximumPersistentGraphPages,
 658        NavigationGridBaselineCapture[] baselineCaptures,
 659        ref PersistentStringMap<NavigationBaselineRebuild> baselineRebuilds,
 660        Span<VoxelIndex> baselineAddressScratch,
 661        Span<GridCoveredAddress> baselineCoveredAddressScratch,
 662        Span<NavigationGridChangeScope> deferredScopes,
 663        out int deferredScopeCount,
 664        out bool deferAll,
 665        int[] affectedOrdinals,
 666        int[] affectedStamps,
 667        ref int affectedStamp,
 668        out int affectedCollectionCount)
 669    {
 20256670        deferredScopeCount = 0;
 20256671        deferAll = false;
 20256672        affectedCollectionCount = 0;
 42786673        for (int changeIndex = 0; changeIndex < changeCount; changeIndex++)
 674        {
 1137675            if (changes[changeIndex].Kind == NavigationOperationFrameChangeKind.MapRemove)
 8676                baselineRebuilds = baselineRebuilds.Remove(changes[changeIndex].MapId!, out _);
 677        }
 20256678        if (_instances.Count == 0)
 11470679            return 0;
 680
 8786681        int affectedCount = CollectAffectedMaps(
 8786682            events,
 8786683            resnapshotScopes,
 8786684            resnapshotAll,
 8786685            blockedScopes,
 8786686            blockAll,
 8786687            changes,
 8786688            changeCount,
 8786689            affectedOrdinals,
 8786690            affectedStamps,
 8786691            ref affectedStamp);
 8786692        affectedCollectionCount = affectedCount;
 8786693        NavigationBaselineRebuild.GetRetainedTotals(
 8786694            baselineRebuilds,
 8786695            out long rebuildRetainedBytes,
 8786696            out int rebuildPersistentPages);
 8786697        int remainingBaselineAddresses = maintenanceMeter.RemainingBaselineAddresses;
 20398698        for (int affectedIndex = 0; affectedIndex < affectedCount; affectedIndex++)
 699        {
 1413700            int mapIndex = affectedOrdinals[affectedIndex];
 1413701            baselineCaptures[mapIndex] = default;
 1413702            NavigationMapInstance current = _instances.Get(mapIndex);
 1413703            GridConfigurationKey configurationKey = current.Map.GridBinding.Key;
 1413704            bool isBlocked = blockAll || ContainsScope(blockedScopes, configurationKey);
 1413705            bool requiresRecoveryBaseline = resnapshotAll
 1413706                || ContainsScope(resnapshotScopes, configurationKey)
 1413707                || EventsRequireBaseline(
 1413708                    events,
 1413709                    configurationKey,
 1413710                    current.Map.DefaultCell.HasValue);
 1413711            bool operationChanged = !current.IsMaterialized
 1413712                && IsOperationChanged(changes, changeCount, current.MapId);
 1413713            bool requiresBaseline = requiresRecoveryBaseline || operationChanged;
 1413714            if (isBlocked || !requiresBaseline)
 715                continue;
 1231716            NavigationMapInstance? prior = null;
 1231717            bool isDelta = !requiresRecoveryBaseline
 1231718                && IsCellOverlayOnlyChanged(changes, changeCount, current.MapId)
 1231719                && previousGraph.TryGetMap(current.MapId, out prior)
 1231720                && prior.IsMaterialized;
 1231721            baselineRebuilds.TryGetValue(
 1231722                current.MapId,
 1231723                out NavigationBaselineRebuild? rebuild);
 1231724            if (rebuild != null && !rebuild.Matches(current))
 725            {
 1726                RemoveBaselineRebuild(
 1727                    ref baselineRebuilds,
 1728                    current.MapId,
 1729                    rebuild,
 1730                    ref rebuildRetainedBytes,
 1731                    ref rebuildPersistentPages);
 1732                rebuild = null;
 733            }
 1231734            if (rebuild != null
 1231735                && rebuild.TryGetCompletedCapture(
 1231736                    out NavigationGridBaselineCapture readyCapture))
 737            {
 39738                baselineCaptures[mapIndex] = readyCapture;
 39739                continue;
 740            }
 1192741            if (rebuild != null)
 63742                isDelta = false;
 743            int addressCount;
 1192744            bool requiresDefaultDiscovery = !isDelta && current.Map.DefaultCell.HasValue;
 1192745            if (isDelta)
 746            {
 36747                if (!current.TryCopyNewCanonicalAddresses(
 36748                        prior!,
 36749                        baselineAddressScratch,
 36750                        out addressCount))
 751                {
 1752                    isDelta = false;
 1753                    addressCount = 0;
 754                }
 755            }
 1156756            else if (rebuild == null && !requiresDefaultDiscovery)
 757            {
 1046758                addressCount = current.AddressCount <= remainingBaselineAddresses
 1046759                    ? current.CopyCanonicalAddresses(baselineAddressScratch)
 1046760                    : 0;
 761            }
 762            else
 763            {
 110764                addressCount = 0;
 765            }
 766
 1192767            bool requiresChunkedBaseline = !isDelta
 1192768                && (requiresDefaultDiscovery
 1192769                    || rebuild != null
 1192770                    || current.AddressCount > remainingBaselineAddresses);
 1192771            if (!requiresChunkedBaseline && addressCount <= remainingBaselineAddresses)
 772            {
 1062773                bool consumed = maintenanceMeter.TryConsumeBaselineAddresses(addressCount);
 774                System.Diagnostics.Debug.Assert(consumed,
 775                    "The capture is bounded by the meter's remaining baseline addresses.");
 1062776                remainingBaselineAddresses -= addressCount;
 777                System.Diagnostics.Debug.Assert(addressCount > 0 || !isDelta,
 778                    "a nonmaterialized cell-only delta owns at least one new canonical address");
 1062779                world.TryCaptureNavigationBaseline(
 1062780                    configurationKey,
 1062781                    baselineAddressScratch.Slice(0, addressCount),
 1062782                    out GridNavigationBaseline? baseline);
 1062783                baselineCaptures[mapIndex] = new NavigationGridBaselineCapture(
 1062784                    addressCount,
 1062785                    baseline,
 1062786                    isDelta);
 787            }
 788            else
 789            {
 130790                if (!isDelta)
 791                {
 130792                    if (rebuild == null)
 793                    {
 67794                        var proposed = new NavigationBaselineRebuild(current);
 67795                        if (TryAddBaselineRebuild(
 67796                                ref baselineRebuilds,
 67797                                proposed,
 67798                                RetainedBytes,
 67799                                PersistentPageCount,
 67800                                maximumActiveSnapshotBytes,
 67801                                maximumPersistentGraphPages,
 67802                                ref rebuildRetainedBytes,
 67803                                ref rebuildPersistentPages))
 804                        {
 66805                            rebuild = proposed;
 806                        }
 807                    }
 130808                    if (rebuild != null && !rebuild.RequiresCoveredDiscovery)
 809                    {
 70810                        long beforeBytes = rebuild.RetainedBytes;
 70811                        int beforePages = rebuild.PersistentPageCount;
 70812                        long otherBytes = rebuildRetainedBytes - beforeBytes;
 70813                        int otherPages = rebuildPersistentPages - beforePages;
 70814                        long maximumRebuildBytes = Math.Max(
 70815                            0,
 70816                            maximumActiveSnapshotBytes - RetainedBytes - otherBytes);
 70817                        int maximumRebuildPages = Math.Max(
 70818                            0,
 70819                            maximumPersistentGraphPages - PersistentPageCount - otherPages);
 70820                        int consumed = rebuild.Advance(
 70821                            world,
 70822                            current,
 70823                            remainingBaselineAddresses,
 70824                            maximumRebuildBytes,
 70825                            maximumRebuildPages,
 70826                            baselineAddressScratch,
 70827                            baselineCoveredAddressScratch,
 70828                            out NavigationGridBaselineCapture completedCapture,
 70829                            out bool completed);
 70830                        rebuildRetainedBytes = checked(
 70831                            rebuildRetainedBytes - beforeBytes + rebuild.RetainedBytes);
 70832                        rebuildPersistentPages = checked(
 70833                            rebuildPersistentPages - beforePages + rebuild.PersistentPageCount);
 70834                        maintenanceMeter.TryConsumeBaselineAddresses(consumed);
 70835                        remainingBaselineAddresses -= consumed;
 70836                        if (completed)
 837                        {
 17838                            baselineCaptures[mapIndex] = completedCapture;
 17839                            continue;
 840                        }
 841                    }
 842                }
 113843                NavigationGridGenerationIdentity deferredIdentity = current.GridIdentity;
 113844                if (!deferredIdentity.IsValid
 113845                    && previousGraph.TryGetMap(current.MapId, out NavigationMapInstance deferredPrior))
 846                {
 69847                    deferredIdentity = deferredPrior.GridIdentity;
 848                }
 113849                if (deferredScopeCount < deferredScopes.Length)
 850                {
 112851                    deferredScopes[deferredScopeCount++] = new NavigationGridChangeScope(
 112852                        configurationKey,
 112853                        deferredIdentity.WorldSpawnToken,
 112854                        deferredIdentity.GridIndex,
 112855                        deferredIdentity.GridSpawnToken);
 856                }
 857                else
 858                {
 1859                    deferredScopeCount = 0;
 1860                    deferAll = true;
 861                }
 862            }
 863        }
 8786864        return affectedCount;
 865    }
 866
 867    private static bool TryAddBaselineRebuild(
 868        ref PersistentStringMap<NavigationBaselineRebuild> rebuilds,
 869        NavigationBaselineRebuild rebuild,
 870        long graphRetainedBytes,
 871        int graphPersistentPages,
 872        long maximumRetainedBytes,
 873        int maximumPersistentPages,
 874        ref long rebuildRetainedBytes,
 875        ref int rebuildPersistentPages)
 876    {
 67877        PersistentStringMap<NavigationBaselineRebuild> next = rebuilds.Set(
 67878            rebuild.MapId,
 67879            rebuild);
 67880        long priorRegistryBytes = rebuilds.Count == 0 ? 0 : rebuilds.RetainedBytes;
 67881        int priorRegistryPages = rebuilds.Count == 0
 67882            ? 0
 67883            : 1 + rebuilds.PersistentNodeCount;
 67884        long nextRetainedBytes = checked(
 67885            rebuildRetainedBytes
 67886            - priorRegistryBytes
 67887            + next.RetainedBytes
 67888            + rebuild.RetainedBytes);
 67889        int nextPersistentPages = checked(
 67890            rebuildPersistentPages
 67891            - priorRegistryPages
 67892            + 1
 67893            + next.PersistentNodeCount
 67894            + rebuild.PersistentPageCount);
 67895        if (graphRetainedBytes > maximumRetainedBytes - nextRetainedBytes
 67896            || graphPersistentPages > maximumPersistentPages - nextPersistentPages)
 897        {
 1898            return false;
 899        }
 900
 66901        rebuilds = next;
 66902        rebuildRetainedBytes = nextRetainedBytes;
 66903        rebuildPersistentPages = nextPersistentPages;
 66904        return true;
 905    }
 906
 907    private static void RemoveBaselineRebuild(
 908        ref PersistentStringMap<NavigationBaselineRebuild> rebuilds,
 909        string mapId,
 910        NavigationBaselineRebuild rebuild,
 911        ref long rebuildRetainedBytes,
 912        ref int rebuildPersistentPages)
 913    {
 1914        GetBaselineRebuildRegistryFootprint(
 1915            rebuilds,
 1916            out long priorRegistryBytes,
 1917            out int priorRegistryPages);
 1918        PersistentStringMap<NavigationBaselineRebuild> next = rebuilds.Remove(mapId, out _);
 1919        GetBaselineRebuildRegistryFootprint(
 1920            next,
 1921            out long nextRegistryBytes,
 1922            out int nextRegistryPages);
 1923        rebuildRetainedBytes = checked(
 1924            rebuildRetainedBytes
 1925            - priorRegistryBytes
 1926            - rebuild.RetainedBytes
 1927            + nextRegistryBytes);
 1928        rebuildPersistentPages = checked(
 1929            rebuildPersistentPages
 1930            - priorRegistryPages
 1931            - rebuild.PersistentPageCount
 1932            + nextRegistryPages);
 1933        rebuilds = next;
 1934    }
 935
 936    internal static void GetBaselineRebuildRegistryFootprint(
 937        PersistentStringMap<NavigationBaselineRebuild> rebuilds,
 938        out long retainedBytes,
 939        out int persistentPages)
 940    {
 4941        bool hasRebuilds = rebuilds.Count != 0;
 4942        retainedBytes = hasRebuilds ? rebuilds.RetainedBytes : 0;
 4943        persistentPages = hasRebuilds ? 1 + rebuilds.PersistentNodeCount : 0;
 4944    }
 945
 946    internal NavigationWorldGraph ApplyMaintenanceSnapshot(
 947        long worldSpawnToken,
 948        NavigationWorldGraph previousGraph,
 949        ReadOnlySpan<GridEventInfo> events,
 950        ReadOnlySpan<NavigationGridChangeScope> resnapshotScopes,
 951        bool resnapshotAll,
 952        ReadOnlySpan<NavigationGridChangeScope> blockedScopes,
 953        bool blockAll,
 954        NavigationOperationFrameChange[] changes,
 955        int changeCount,
 956        NavigationGridBaselineCapture[] baselineCaptures,
 957        int[] affectedOrdinals,
 958        int affectedCount,
 959        long graphVersion)
 960    {
 20249961        NavigationInstanceDirectory changed = _instances;
 20249962        long retainedBytes = RetainedBytes;
 20249963        int persistentPages = PersistentPageCount;
 43310964        for (int affectedIndex = 0; affectedIndex < affectedCount; affectedIndex++)
 965        {
 1406966            int mapIndex = affectedOrdinals[affectedIndex];
 1406967            NavigationMapInstance current = changed.Get(mapIndex);
 1406968            GridConfigurationKey configurationKey = current.Map.GridBinding.Key;
 1406969            bool isBlocked = blockAll || ContainsScope(blockedScopes, configurationKey);
 1406970            bool requiresRecoveryBaseline = resnapshotAll
 1406971                || ContainsScope(resnapshotScopes, configurationKey)
 1406972                || EventsRequireBaseline(
 1406973                    events,
 1406974                    configurationKey,
 1406975                    current.Map.DefaultCell.HasValue);
 1406976            bool requiresBaseline = requiresRecoveryBaseline
 1406977                || (!current.IsMaterialized && IsOperationChanged(changes, changeCount, current.MapId));
 978            NavigationMapInstance next;
 1406979            if (isBlocked)
 980            {
 44981                next = current.FailClosed(graphVersion);
 982            }
 1362983            else if (!requiresBaseline)
 984            {
 138985                next = current.ApplyBatch(worldSpawnToken, events, false, graphVersion);
 986            }
 1224987            else if (!requiresRecoveryBaseline
 1224988                && IsCellOverlayOnlyChanged(changes, changeCount, current.MapId)
 1224989                && previousGraph.TryGetMap(current.MapId, out NavigationMapInstance prior))
 990            {
 118991                next = current.MaterializeDelta(
 118992                    prior,
 118993                    baselineCaptures[mapIndex],
 118994                    graphVersion).ApplyBatch(worldSpawnToken, events, false, graphVersion);
 995            }
 996            else
 997            {
 1106998                next = current.Materialize(baselineCaptures[mapIndex], graphVersion);
 999            }
 14061000            if (!ReferenceEquals(current, next))
 1001            {
 10961002                retainedBytes = checked(retainedBytes - current.RetainedBytes + next.RetainedBytes);
 10961003                persistentPages += next.PersistentPageCount - current.PersistentPageCount;
 10961004                changed = changed.With(mapIndex, next);
 1005            }
 1006        }
 202491007        if (ReferenceEquals(changed, _instances))
 193701008            return this;
 8791009        var updated = new NavigationWorldGraph(
 8791010                graphVersion,
 8791011                changed,
 8791012                AreaCatalog,
 8791013                _mapIndex,
 8791014                SurfaceComponents,
 8791015                _explicitConnections,
 8791016                _automaticSeams,
 8791017                _transitionPages,
 8791018                TransitionRules,
 8791019                _closedStructuralComponents,
 8791020                _additionalClosedStructuralComponents,
 8791021                _allStructuralComponentsClosed,
 8791022                retainedBytes,
 8791023                persistentPages);
 8791024        return updated;
 1025    }
 1026
 1027    internal NavigationWorldGraph WithAreaCatalog(
 1028        NavigationAreaCatalog catalog,
 1029        long graphVersion)
 1030    {
 36431031        if (ReferenceEquals(catalog, AreaCatalog))
 34241032            return this;
 2191033        long retainedBytes = checked(RetainedBytes - AreaCatalog.RetainedBytes + catalog.RetainedBytes);
 2191034        int persistentPages = PersistentPageCount - AreaCatalog.PersistentPageCount + catalog.PersistentPageCount;
 2191035        return new NavigationWorldGraph(
 2191036            graphVersion,
 2191037            _instances,
 2191038            catalog,
 2191039            _mapIndex,
 2191040            SurfaceComponents,
 2191041            _explicitConnections,
 2191042            _automaticSeams,
 2191043            _transitionPages,
 2191044            TransitionRules,
 2191045            _closedStructuralComponents,
 2191046            _additionalClosedStructuralComponents,
 2191047            _allStructuralComponentsClosed,
 2191048            retainedBytes,
 2191049            persistentPages);
 1050    }
 1051
 1052    internal NavigationWorldGraph WithGraphVersion(long graphVersion)
 1053    {
 3411054        if (graphVersion == GraphVersion)
 11055            return this;
 3401056        return new NavigationWorldGraph(
 3401057            graphVersion,
 3401058            _instances,
 3401059            AreaCatalog,
 3401060            _mapIndex,
 3401061            SurfaceComponents,
 3401062            _explicitConnections,
 3401063            _automaticSeams,
 3401064            _transitionPages,
 3401065            TransitionRules,
 3401066            _closedStructuralComponents,
 3401067            _additionalClosedStructuralComponents,
 3401068            _allStructuralComponentsClosed,
 3401069            RetainedBytes,
 3401070            PersistentPageCount);
 1071    }
 1072
 1073    internal bool TryGetDependencyStamp(
 1074        NavigationAreaPolicyKey areaPolicy,
 1075        ReadOnlySpan<NavigationSurfaceComponentKey> componentKeys,
 1076        ReadOnlySpan<GraphPageDependencyAddress> pageAddresses,
 181077        out GraphDependencyStamp stamp) => TryGetDependencyStamp(
 181078        areaPolicy,
 181079        componentKeys,
 181080        pageAddresses,
 181081        includeTransitionRules: false,
 181082        out stamp);
 1083
 1084    internal bool TryGetDependencyStamp(
 1085        NavigationAreaPolicyKey areaPolicy,
 1086        ReadOnlySpan<NavigationSurfaceComponentKey> componentKeys,
 1087        ReadOnlySpan<GraphPageDependencyAddress> pageAddresses,
 1088        bool includeTransitionRules,
 1089        out GraphDependencyStamp stamp)
 1090    {
 201091        if (!AreaCatalog.TryGet(areaPolicy, out _))
 1092        {
 11093            stamp = null!;
 11094            return false;
 1095        }
 1096
 191097        var components = new GraphComponentDependency[componentKeys.Length];
 191098        NavigationSurfaceComponentKey priorComponent = default;
 541099        for (int i = 0; i < componentKeys.Length; i++)
 1100        {
 111101            NavigationSurfaceComponentKey key = componentKeys[i];
 111102            if ((i > 0 && priorComponent.CompareTo(key) >= 0)
 111103                || !TryGetComponentDependency(key, out components[i]))
 1104            {
 31105                stamp = null!;
 31106                return false;
 1107            }
 81108            priorComponent = key;
 1109        }
 1110
 161111        var pages = new GraphPageDependency[pageAddresses.Length];
 161112        string? priorMapId = null;
 161113        int priorPageIndex = -1;
 561114        for (int i = 0; i < pageAddresses.Length; i++)
 1115        {
 171116            GraphPageDependencyAddress address = pageAddresses[i];
 171117            int mapComparison = priorMapId == null
 171118                ? 1
 171119                : string.CompareOrdinal(address.MapId, priorMapId);
 171120            if (string.IsNullOrEmpty(address.MapId)
 171121                || address.PageIndex < 0
 171122                || mapComparison < 0
 171123                || (mapComparison == 0 && address.PageIndex <= priorPageIndex)
 171124                || !TryGetPageDependency(
 171125                    address,
 171126                    includeTransitionRules,
 171127                    out pages[i]))
 1128            {
 51129                stamp = null!;
 51130                return false;
 1131            }
 121132            priorMapId = address.MapId;
 121133            priorPageIndex = address.PageIndex;
 1134        }
 1135
 111136        stamp = new GraphDependencyStamp(
 111137            areaPolicy,
 111138            components,
 111139            pages,
 111140            includeTransitionRules,
 111141            TransitionRules.Version);
 111142        return true;
 1143    }
 1144
 1145    internal bool TryGetComponentDependency(
 1146        NavigationSurfaceComponentKey key,
 1147        out GraphComponentDependency dependency)
 1148    {
 74161149        if (!IsSurfaceComponentClosed(key)
 74161150            && SurfaceComponents.TryGet(key, out NavigationSurfaceComponent component))
 1151        {
 1152            System.Diagnostics.Debug.Assert(component.Key.Equals(key),
 1153                "Surface component records are indexed by their exact immutable key.");
 74111154            dependency = new GraphComponentDependency(
 74111155                key,
 74111156                component.Version);
 74111157            return true;
 1158        }
 51159        dependency = default;
 51160        return false;
 1161    }
 1162
 1163    internal bool TryGetPageDependency(
 1164        GraphPageDependencyAddress address,
 64341165        out GraphPageDependency dependency) => TryGetPageDependency(
 64341166        address,
 64341167        includeTransitionPage: false,
 64341168        out dependency);
 1169
 1170    internal bool TryGetPageDependency(
 1171        GraphPageDependencyAddress address,
 1172        bool includeTransitionPage,
 1173        out GraphPageDependency dependency)
 1174    {
 329141175        if (!string.IsNullOrEmpty(address.MapId)
 329141176            && address.PageIndex >= 0
 329141177            && TryGetMap(address.MapId, out NavigationMapInstance instance))
 1178        {
 329091179            long transitionVersion = includeTransitionPage && _transitionPages.TryGet(
 329091180                new NavigationTransitionPageAddress(address.MapId, address.PageIndex),
 329091181                out NavigationTransitionPage transitionPage)
 329091182                    ? transitionPage.Version
 329091183                    : 0;
 329091184            dependency = instance.GetPageDependency(address.PageIndex, transitionVersion);
 329091185            return true;
 1186        }
 51187        dependency = default;
 51188        return false;
 1189    }
 1190
 1191    internal bool IsDependencyCurrent(GraphDependencyStamp stamp)
 1192    {
 216041193        if (!AreaCatalog.TryGet(stamp.AreaPolicy, out _))
 21194            return false;
 216021195        if (stamp.HasTransitionRuleDependency
 216021196            && stamp.TransitionRuleVersion != TransitionRules.Version)
 1197        {
 71198            return false;
 1199        }
 998181200        for (int component = 0; component < stamp.Components.Length; component++)
 1201        {
 283501202            GraphComponentDependency dependency = stamp.Components[component];
 283501203            if (IsSurfaceComponentClosed(dependency.Key)
 283501204                || !SurfaceComponents.TryGet(
 283501205                    dependency.Key,
 283501206                    out NavigationSurfaceComponent current))
 221207                return false;
 1208            System.Diagnostics.Debug.Assert(current.Key.Equals(dependency.Key),
 1209                "Surface component records are indexed by their exact immutable key.");
 283281210            if (current.Version != dependency.Version)
 141211                return false;
 1212        }
 940541213        for (int page = 0; page < stamp.Pages.Length; page++)
 1214        {
 254921215            GraphPageDependency dependency = stamp.Pages[page];
 254921216            if (!TryGetPageDependency(
 254921217                    new GraphPageDependencyAddress(dependency.MapId, dependency.PageIndex),
 254921218                    stamp.HasTransitionRuleDependency,
 254921219                    out GraphPageDependency current)
 254921220                || !current.Equals(dependency))
 241221                return false;
 1222        }
 215351223        return true;
 1224    }
 1225
 1226    private static PersistentGridConfigurationMap<string> BuildMapIndex(
 1227        NavigationMapInstance[] instances)
 1228    {
 6441229        PersistentGridConfigurationMap<string> index = PersistentGridConfigurationMap<string>.Empty;
 25941230        for (int i = 0; i < instances.Length; i++)
 6531231            index = index.Set(instances[i].Map.GridBinding.Key, instances[i].MapId);
 6441232        return index;
 1233    }
 1234
 1235    private int FindMapOrdinal(string mapId)
 1236    {
 9553841237        int low = 0;
 9553841238        int high = _instances.Count - 1;
 15827911239        while (low <= high)
 1240        {
 15823371241            int middle = low + ((high - low) >> 1);
 15823371242            int comparison = string.CompareOrdinal(_instances.GetMapId(middle), mapId);
 15823371243            if (comparison == 0)
 9549301244                return middle;
 6274071245            if (comparison < 0)
 5646691246                low = middle + 1;
 1247            else
 627381248                high = middle - 1;
 1249        }
 4541250        return -1;
 1251    }
 1252
 1253    private int CollectAffectedMaps(
 1254        ReadOnlySpan<GridEventInfo> events,
 1255        ReadOnlySpan<NavigationGridChangeScope> resnapshotScopes,
 1256        bool resnapshotAll,
 1257        ReadOnlySpan<NavigationGridChangeScope> blockedScopes,
 1258        bool blockAll,
 1259        NavigationOperationFrameChange[] changes,
 1260        int changeCount,
 1261        int[] ordinals,
 1262        int[] stamps,
 1263        ref int stamp)
 1264    {
 87861265        if (++stamp == 0)
 1266        {
 11267            Array.Clear(stamps, 0, stamps.Length);
 11268            stamp = 1;
 1269        }
 1270
 87861271        int count = 0;
 87861272        bool all = resnapshotAll || blockAll;
 183161273        for (int i = 0; i < events.Length && !all; i++)
 1274        {
 3731275            if (events[i].ChangeKind == GridEventKind.WorldReset)
 1276            {
 11277                all = true;
 11278                break;
 1279            }
 3721280            MarkConfiguration(events[i].Configuration.ToGridKey(), ordinals, ref count, stamps, stamp);
 1281        }
 1282
 177841283        for (int i = 0; i < resnapshotScopes.Length && !all; i++)
 1061284            MarkConfiguration(resnapshotScopes[i].ConfigurationKey, ordinals, ref count, stamps, stamp);
 175841285        for (int i = 0; i < blockedScopes.Length && !all; i++)
 61286            MarkConfiguration(blockedScopes[i].ConfigurationKey, ordinals, ref count, stamps, stamp);
 87861287        MarkOperationChanges(changes, changeCount, ordinals, ref count, stamps, stamp);
 1288
 87861289        if (all)
 1290        {
 611291            count = _instances.Count;
 2661292            for (int i = 0; i < count; i++)
 721293                ordinals[i] = i;
 1294        }
 1295        else
 87251296            Array.Sort(ordinals, 0, count);
 87861297        return count;
 1298    }
 1299
 1300    private void MarkOperationChanges(
 1301        NavigationOperationFrameChange[] changes,
 1302        int changeCount,
 1303        int[] ordinals,
 1304        ref int count,
 1305        int[] stamps,
 1306        int stamp)
 1307    {
 198381308        for (int i = 0; i < changeCount; i++)
 1309        {
 11331310            NavigationOperationFrameChange change = changes[i];
 11331311            if (change.Kind == NavigationOperationFrameChangeKind.MapCommit)
 1312            {
 9481313                MarkMapId(change.MapId!, ordinals, ref count, stamps, stamp);
 9481314                continue;
 1315            }
 1851316            if (change.Kind != NavigationOperationFrameChangeKind.Overlay)
 1317                continue;
 1801318            ReadOnlySpan<NavigationMapOverlayDelta> deltas = change.PreparedOverlay!.Transaction.MapSpan;
 7501319            for (int delta = 0; delta < deltas.Length; delta++)
 1951320                MarkMapId(deltas[delta].MapId, ordinals, ref count, stamps, stamp);
 1321        }
 87861322    }
 1323
 1324    private void MarkMapId(
 1325        string mapId,
 1326        int[] ordinals,
 1327        ref int count,
 1328        int[] stamps,
 1329        int stamp)
 1330    {
 11431331        int ordinal = FindMapOrdinal(mapId);
 11431332        TryMarkOrdinal(ordinal, ordinals, ref count, stamps, stamp);
 11431333    }
 1334
 1335    private void MarkConfiguration(
 1336        GridConfigurationKey key,
 1337        int[] ordinals,
 1338        ref int count,
 1339        int[] stamps,
 1340        int stamp)
 1341    {
 4841342        if (_mapIndex.TryGetValue(key, out string mapId))
 1343        {
 2321344            int ordinal = FindMapOrdinal(mapId);
 2321345            TryMarkOrdinal(ordinal, ordinals, ref count, stamps, stamp);
 1346        }
 4841347    }
 1348
 1349    internal static bool TryMarkOrdinal(
 1350        int ordinal,
 1351        int[] ordinals,
 1352        ref int count,
 1353        int[] stamps,
 1354        int stamp)
 1355    {
 13791356        if (ordinal < 0 || stamps[ordinal] == stamp)
 341357            return false;
 13451358        stamps[ordinal] = stamp;
 13451359        ordinals[count++] = ordinal;
 13451360        return true;
 1361    }
 1362
 1363    private static bool ContainsScope(
 1364        ReadOnlySpan<NavigationGridChangeScope> scopes,
 1365        GridConfigurationKey key)
 1366    {
 110421367        for (int i = 0; i < scopes.Length; i++)
 1368        {
 2451369            if (scopes[i].ConfigurationKey.Equals(key))
 2231370                return true;
 1371        }
 52761372        return false;
 1373    }
 1374
 1375    private static bool EventsRequireBaseline(
 1376        ReadOnlySpan<GridEventInfo> events,
 1377        GridConfigurationKey key,
 1378        bool discoverDefaultPresence)
 1379    {
 55141380        for (int i = 0; i < events.Length; i++)
 1381        {
 2601382            if ((events[i].ChangeKind == GridEventKind.GridAdded
 2601383                    || events[i].ChangeKind == GridEventKind.GridChanged
 2601384                    || discoverDefaultPresence
 2601385                        && (events[i].ChangeKind == GridEventKind.SparseVoxelAdded
 2601386                            || events[i].ChangeKind == GridEventKind.SparseVoxelRemoved))
 2601387                && events[i].Configuration.ToGridKey().Equals(key))
 1388            {
 481389                return true;
 1390            }
 1391        }
 24971392        return false;
 1393    }
 1394
 1395    private static bool IsOperationChanged(
 1396        NavigationOperationFrameChange[] changes,
 1397        int changeCount,
 1398        string mapId)
 1399    {
 61401400        for (int i = 0; i < changeCount; i++)
 1401        {
 28711402            NavigationOperationFrameChange change = changes[i];
 28711403            if (change.Kind == NavigationOperationFrameChangeKind.MapCommit)
 1404            {
 26301405                if (string.Equals(change.MapId, mapId, StringComparison.Ordinal))
 18961406                    return true;
 1407                continue;
 1408            }
 2411409            if (change.Kind != NavigationOperationFrameChangeKind.Overlay)
 1410                continue;
 2391411            ReadOnlySpan<NavigationMapOverlayDelta> deltas = change.PreparedOverlay!.Transaction.MapSpan;
 9581412            for (int delta = 0; delta < deltas.Length; delta++)
 1413            {
 4791414                if (string.Equals(deltas[delta].MapId, mapId, StringComparison.Ordinal))
 2391415                    return true;
 1416            }
 1417        }
 1991418        return false;
 1419    }
 1420
 1421    private static bool IsCellOverlayOnlyChanged(
 1422        NavigationOperationFrameChange[] changes,
 1423        int changeCount,
 1424        string mapId)
 1425    {
 21331426        bool found = false;
 62201427        for (int i = 0; i < changeCount; i++)
 1428        {
 28711429            NavigationOperationFrameChange change = changes[i];
 28711430            if (change.Kind == NavigationOperationFrameChangeKind.MapCommit
 28711431                && string.Equals(change.MapId, mapId, StringComparison.Ordinal))
 1432            {
 18941433                return false;
 1434            }
 9771435            if (change.Kind != NavigationOperationFrameChangeKind.Overlay)
 1436                continue;
 2431437            ReadOnlySpan<NavigationMapOverlayDelta> deltas = change.PreparedOverlay!.Transaction.MapSpan;
 19321438            for (int delta = 0; delta < deltas.Length; delta++)
 1439            {
 7231440                if (string.Equals(deltas[delta].MapId, mapId, StringComparison.Ordinal))
 2431441                    found = true;
 1442            }
 1443        }
 2391444        return found;
 1445    }
 1446}

/home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Graph/NavigationWorldGraph.NativeEdges.cs

#LineLine coverage
 1//=======================================================================
 2// NavigationWorldGraph.NativeEdges.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 FixedMathSharp;
 9using GridForge.Grids.Topology;
 10using GridForge.Spatial;
 11
 12namespace Trailblazer.Pathing;
 13
 14internal sealed partial class NavigationWorldGraph
 15{
 16    internal bool TryGetNodeRef(
 17        int mapOrdinal,
 18        VoxelIndex index,
 19        out NavigationNodeRef node)
 20    {
 184019321        if ((uint)mapOrdinal >= (uint)_instances.Count)
 22        {
 45423            node = default;
 45424            return false;
 25        }
 26
 183973927        NavigationMapInstance instance = _instances.Get(mapOrdinal);
 183973928        if (!instance.Map.GridBinding.IsValidIndex(index)
 183973929            || !instance.TryGetSlot(index, out int slot))
 30        {
 16046331            node = default;
 16046332            return false;
 33        }
 34
 167927635        node = new NavigationNodeRef(mapOrdinal, slot);
 167927636        return node.IsValid;
 37    }
 38
 39    internal bool TryGetNodeRef(
 40        NavigationCellAddress address,
 41        out NavigationNodeRef node)
 42    {
 95400943        int mapOrdinal = FindMapOrdinal(address.MapId);
 95400944        return TryGetNodeRef(mapOrdinal, address.Index, out node);
 45    }
 46
 47    internal bool TryGetNodeAddress(
 48        NavigationNodeRef node,
 49        out NavigationCellAddress address)
 50    {
 203581151        if (!TryGetNodeLocation(node, out NavigationMapInstance? instance, out VoxelIndex index))
 52        {
 253            address = default;
 254            return false;
 55        }
 56
 203580957        address = new NavigationCellAddress(instance!.MapId, index);
 203580958        return true;
 59    }
 60
 61    internal bool TryGetNodeState(NavigationNodeRef node, out NavigationNodeState state)
 72663262        => TryGetNodeState(node, TraversalMedium.Solid, out state);
 63
 64    internal bool TryGetNodeState(
 65        NavigationNodeRef node,
 66        TraversalMedium medium,
 67        out NavigationNodeState state)
 68    {
 69        System.Diagnostics.Debug.Assert(NavigationCell.IsKnownMedium(medium),
 70            "graph node-state callers retain one validated exact traversal medium");
 96336671        if (!TryGetNodeLocation(node, out NavigationMapInstance? instance, out VoxelIndex index)
 96336672            || IsSurfaceAddressClosed(
 96336673                new NavigationCellAddress(instance!.MapId, index),
 96336674                medium)
 96336675            || !TryGetRawNodeState(node, instance, index, out state))
 76        {
 5177            state = default;
 5178            return false;
 79        }
 80
 96331581        return true;
 82    }
 83
 84    internal bool TryGetRawNodeState(
 85        NavigationNodeRef node,
 86        out NavigationNodeState state)
 87    {
 49388        bool found = TryGetNodeLocation(
 49389            node,
 49390            out NavigationMapInstance? instance,
 49391            out VoxelIndex index);
 92        System.Diagnostics.Debug.Assert(found,
 93            "raw node-state lookup receives a node owned by this immutable graph");
 49394        return TryGetRawNodeState(node, instance!, index, out state);
 95    }
 96
 97    private static bool TryGetRawNodeState(
 98        NavigationNodeRef node,
 99        NavigationMapInstance instance,
 100        VoxelIndex index,
 101        out NavigationNodeState state)
 102    {
 963810103        if (!instance.TryGetEffectiveCell(node.CellSlot, out NavigationCell cell)
 963810104            || !instance.Map.GridBinding.TryGetCellPrism(index, out GridCellPrism prism))
 105        {
 2106            state = default;
 2107            return false;
 108        }
 109
 963808110        instance.TryGetPhysicalState(node.CellSlot, out bool isPresent, out byte obstacleCount);
 963808111        state = new NavigationNodeState(
 963808112            cell,
 963808113            isPresent,
 963808114            obstacleCount,
 963808115            prism.Center,
 963808116            new Vector3d(prism.Center.X, prism.VerticalMin, prism.Center.Z));
 963808117        return true;
 118    }
 119
 120    internal int GetCompleteDirectionCount(NavigationNodeRef node)
 121    {
 3469122        bool found = TryGetNodeLocation(node, out NavigationMapInstance? instance, out _);
 123        System.Diagnostics.Debug.Assert(found,
 124            "direction lookup receives a node owned by this immutable graph");
 3469125        return instance!.Map.GridBinding.Configuration.TopologyKind
 3469126            == GridTopologyKind.HexPrism
 3469127                ? HexDirectionUtility.Offsets.Length
 3469128                : RectangularDirectionUtility.Offsets.Length;
 129    }
 130
 131    internal bool TryGetCompleteNeighbor(
 132        NavigationNodeRef source,
 133        int directionOrdinal,
 134        out NavigationNodeRef neighbor,
 135        out bool isPrimary)
 136    {
 69956137        bool found = TryGetNodeLocation(
 69956138            source,
 69956139            out NavigationMapInstance? instance,
 69956140            out VoxelIndex index);
 141        System.Diagnostics.Debug.Assert(found,
 142            "neighbor lookup receives a source node owned by this immutable graph");
 143
 69956144        bool hex = instance!.Map.GridBinding.Configuration.TopologyKind
 69956145            == GridTopologyKind.HexPrism;
 69956146        int count = hex
 69956147            ? HexDirectionUtility.Offsets.Length
 69956148            : RectangularDirectionUtility.Offsets.Length;
 69956149        if ((uint)directionOrdinal >= (uint)count)
 150        {
 1151            neighbor = default;
 1152            isPrimary = false;
 1153            return false;
 154        }
 155
 156        VoxelIndex offset;
 69955157        if (hex)
 158        {
 20464159            HexDirection direction = HexDirectionUtility.All[directionOrdinal];
 20464160            offset = HexDirectionUtility.GetOffset(direction);
 20464161            isPrimary = HexDirectionUtility.IsPlanar(direction)
 20464162                || HexDirectionUtility.IsVertical(direction);
 163        }
 164        else
 165        {
 49491166            RectangularDirection direction = RectangularDirectionUtility.All[
 49491167                directionOrdinal];
 49491168            (int x, int y, int z) rectangular = RectangularDirectionUtility.Offsets[
 49491169                directionOrdinal];
 49491170            offset = new VoxelIndex(rectangular.x, rectangular.y, rectangular.z);
 49491171            isPrimary = RectangularDirectionUtility.IsPerpendicularNeighbor(direction);
 172        }
 173
 69955174        var address = new NavigationCellAddress(
 69955175            instance.MapId,
 69955176            new VoxelIndex(index.x + offset.x, index.y + offset.y, index.z + offset.z));
 69955177        return TryGetNodeRef(address, out neighbor);
 178    }
 179
 180    internal bool TryGetMediumStateRef(
 181        NavigationCellAddress address,
 182        TraversalMedium medium,
 183        out NavigationMediumStateRef state)
 184    {
 320185        if (!TryGetStructuralMediumStateRef(address, medium, out state)
 320186            || IsSurfaceAddressClosed(address, medium))
 187        {
 40188            state = default;
 40189            return false;
 190        }
 280191        NavigationNodeRef node = state.Node;
 280192        NavigationMapInstance instance = _instances.Get(node.MapOrdinal);
 280193        if (!instance.TryGetPhysicalState(node.CellSlot, out bool isPresent, out _)
 280194            || !isPresent)
 195        {
 1196            state = default;
 1197            return false;
 198        }
 279199        return true;
 200    }
 201
 202    internal bool TryGetStructuralMediumStateRef(
 203        NavigationCellAddress address,
 204        TraversalMedium medium,
 205        out NavigationMediumStateRef state)
 206    {
 423284207        if (!NavigationCell.IsKnownMedium(medium)
 423284208            || !TryGetNodeRef(address, out NavigationNodeRef node)
 423284209            || !_instances.Get(node.MapOrdinal).TryGetEffectiveCell(
 423284210                node.CellSlot,
 423284211                out NavigationCell cell)
 423284212            || !cell.SupportsMedium(medium))
 213        {
 107271214            state = default;
 107271215            return false;
 216        }
 217
 316013218        state = new NavigationMediumStateRef(node, medium);
 316013219        return true;
 220    }
 221
 222    internal int GetPrimaryDirectionCount(NavigationNodeRef node)
 223    {
 3347224        bool found = TryGetNodeLocation(node, out NavigationMapInstance? instance, out _);
 225        System.Diagnostics.Debug.Assert(found,
 226            "direction lookup receives a node owned by this immutable graph");
 3347227        return instance!.Map.GridBinding.Configuration.TopologyKind
 3347228            == GridTopologyKind.HexPrism
 3347229                ? HexDirectionUtility.Primary.Length
 3347230                : RectangularDirectionUtility.Primary.Length;
 231    }
 232
 233    internal bool TryGetStructuralPrimaryMediumNeighbor(
 234        NavigationMediumStateRef source,
 235        int directionOrdinal,
 236        out NavigationMediumStateRef neighbor)
 237    {
 12679238        if (!TryGetPrimaryNeighbor(
 12679239                source.Node,
 12679240                directionOrdinal,
 12679241                out NavigationNodeRef neighborNode)
 12679242            || !TryGetNodeAddress(neighborNode, out NavigationCellAddress address))
 243        {
 7548244            neighbor = default;
 7548245            return false;
 246        }
 5131247        return TryGetStructuralMediumStateRef(address, source.Medium, out neighbor);
 248    }
 249
 250    internal bool TryGetPrimaryNeighbor(
 251        NavigationNodeRef source,
 252        int directionOrdinal,
 253        out NavigationNodeRef neighbor)
 254    {
 13553255        bool found = TryGetNodeLocation(
 13553256            source,
 13553257            out NavigationMapInstance? instance,
 13553258            out VoxelIndex index);
 259        System.Diagnostics.Debug.Assert(found,
 260            "neighbor lookup receives a source node owned by this immutable graph");
 13553261        bool hex = instance!.Map.GridBinding.Configuration.TopologyKind
 13553262            == GridTopologyKind.HexPrism;
 13553263        int count = hex
 13553264            ? HexDirectionUtility.Primary.Length
 13553265            : RectangularDirectionUtility.Primary.Length;
 13553266        if ((uint)directionOrdinal >= (uint)count)
 267        {
 1268            neighbor = default;
 1269            return false;
 270        }
 271        VoxelIndex offset;
 13552272        if (hex)
 273        {
 2944274            offset = HexDirectionUtility.GetOffset(
 2944275                HexDirectionUtility.Primary[directionOrdinal]);
 276        }
 277        else
 278        {
 10608279            (int x, int y, int z) rectangular = RectangularDirectionUtility.Offsets[
 10608280                (int)RectangularDirectionUtility.Primary[directionOrdinal]];
 10608281            offset = new VoxelIndex(rectangular.x, rectangular.y, rectangular.z);
 282        }
 13552283        var address = new NavigationCellAddress(
 13552284            instance.MapId,
 13552285            new VoxelIndex(index.x + offset.x, index.y + offset.y, index.z + offset.z));
 13552286        return TryGetNodeRef(address, out neighbor);
 287    }
 288
 289    internal NavigationNativeSurfaceEdgeEnumerator EnumerateNativeSurfaceEdges(
 290        NavigationNodeRef source)
 291    {
 181700292        if (!TryGetNodeLocation(
 181700293                source,
 181700294                out NavigationMapInstance? instance,
 181700295                out VoxelIndex sourceIndex)
 181700296            || !TryGetNodeState(source, out NavigationNodeState sourceState)
 181700297            || !sourceState.IsPresent)
 298        {
 2299            return default;
 300        }
 301
 181698302        return new NavigationNativeSurfaceEdgeEnumerator(
 181698303            this,
 181698304            source.MapOrdinal,
 181698305            instance!,
 181698306            sourceIndex);
 307    }
 308
 309    internal NavigationNativeSurfaceEdgeEnumerator EnumerateStructuralNativeSurfaceEdges(
 310        NavigationNodeRef source)
 311    {
 359447312        bool foundSource = TryGetNodeLocation(
 359447313            source,
 359447314            out NavigationMapInstance? instance,
 359447315            out VoxelIndex sourceIndex);
 316        System.Diagnostics.Debug.Assert(foundSource,
 317            "structural enumeration retains its exact graph-owned source node");
 359447318        if (!instance!.TryGetEffectiveCell(source.CellSlot, out _))
 319        {
 1320            return default;
 321        }
 359446322        return new NavigationNativeSurfaceEdgeEnumerator(
 359446323            this,
 359446324            source.MapOrdinal,
 359446325            instance!,
 359446326            sourceIndex,
 359446327            structural: true);
 328    }
 329
 330    internal NavigationSurfaceEdgeEnumerator EnumerateSurfaceEdges(
 138239331        NavigationNodeRef source) => new(
 138239332            this,
 138239333            source,
 138239334            incoming: false,
 138239335            includeNative: true,
 138239336            includeAutomaticSeams: true);
 337
 338    internal NavigationIncomingSurfaceEdgeEnumerator EnumerateIncomingSurfaceEdges(
 23477339        NavigationNodeRef destination) => new(this, destination);
 340
 341    internal NavigationSurfaceEdgeEnumerator EnumerateStructuralSurfaceEdges(
 271755342        NavigationNodeRef source) => new(
 271755343            this,
 271755344            source,
 271755345            incoming: false,
 271755346            includeNative: true,
 271755347            includeAutomaticSeams: true,
 271755348            structural: true);
 349
 350    internal NavigationIncomingSurfaceEdgeEnumerator EnumerateIncomingStructuralSurfaceEdges(
 87690351        NavigationNodeRef destination) => new(this, destination, structural: true);
 352
 353    internal NavigationSurfaceEdgeEnumerator EnumerateIncomingExplicitSurfaceEdges(
 2354        NavigationNodeRef destination) => new(
 2355            this,
 2356            destination,
 2357            incoming: true,
 2358            includeNative: false,
 2359            includeAutomaticSeams: false);
 360
 361    private bool TryGetNodeLocation(
 362        NavigationNodeRef node,
 363        out NavigationMapInstance? instance,
 364        out VoxelIndex index)
 365    {
 3631142366        if (!node.IsValid || (uint)node.MapOrdinal >= (uint)_instances.Count)
 367        {
 2368            instance = null;
 2369            index = default;
 2370            return false;
 371        }
 372
 3631140373        instance = _instances.Get(node.MapOrdinal);
 3631140374        if (instance.TryGetSlotIndex(node.CellSlot, out index))
 3631137375            return true;
 376
 3377        instance = null;
 3378        index = default;
 3379        return false;
 380    }
 381}

/home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Graph/NavigationWorldGraph.StructuralPreparationWork.cs

#LineLine coverage
 1//=======================================================================
 2// NavigationWorldGraph.StructuralPreparationWork.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;
 9
 10namespace Trailblazer.Pathing;
 11
 12internal sealed partial class NavigationWorldGraph
 13{
 14    /// <summary>Prepares changed instance and lookup roots without replaying payloads at publication.</summary>
 15    internal sealed class StructuralPreparationWork
 16    {
 17        internal const long BaseRetainedBytes = 192L;
 18        private readonly NavigationWorldGraph _source;
 19        private readonly NavigationOperationCandidate _candidate;
 20        private readonly NavigationOperationFrameChange[] _changes;
 21        private readonly int _changeCount;
 22        private readonly PersistentStringMap<bool> _changedMapIds;
 23        private readonly long _version;
 24        private NavigationInstanceDirectory _directory;
 25        private PersistentGridConfigurationMap<string> _mapIndex;
 26        private NavigationMapInstance.ComposeWork? _compose;
 27        private NavigationMapInstance? _prior;
 28        private NavigationMapInstance? _next;
 29        private string? _mapId;
 30        private int _changeIndex;
 31        private bool _directoryConsumed;
 32        private long _retainedBytes;
 33        private int _persistentPages;
 34        private long _copiedPersistentBytes;
 35        private int _copiedPersistentPages;
 36        private long _ownedInstanceExclusiveBytes;
 37        private int _ownedInstanceExclusivePages;
 38        private bool _composeOwnershipTransferred;
 39        private NavigationWorldGraph? _prepared;
 40        private NavigationTransitionRefreshWork? _transitionRefresh;
 41        private bool _rootsPrepared;
 42        private bool _rebuildTransitionRules;
 43
 112844        internal StructuralPreparationWork(
 112845            NavigationWorldGraph source,
 112846            NavigationOperationCandidate candidate,
 112847            NavigationOperationFrameChange[] changes,
 112848            int changeCount,
 112849            PersistentStringMap<bool> changedMapIds,
 112850            long version)
 51        {
 112852            _source = source;
 112853            _candidate = candidate;
 112854            _changes = changes;
 112855            _changeCount = changeCount;
 112856            _changedMapIds = changedMapIds;
 112857            _version = version;
 112858            _directory = source._instances;
 112859            _mapIndex = source._mapIndex;
 112860            _retainedBytes = source.RetainedBytes;
 112861            _persistentPages = source.PersistentPageCount;
 112862        }
 63
 1024264        internal bool IsComplete => Result != null;
 65
 66        internal NavigationWorldGraph Result { get; private set; } = null!;
 67
 26718468        internal long RetainedBytes => checked(
 26718469            BaseRetainedBytes
 26718470            + _ownedInstanceExclusiveBytes
 26718471            + _copiedPersistentBytes
 26718472            + GetComposeAdditionalRetainedBytes()
 26718473            + (Result == null
 26718474                || _prepared == null
 26718475                || ReferenceEquals(Result, _prepared)
 26718476                    ? 0L
 26718477                    : NavigationWorldGraph.BaseRetainedBytes)
 26718478            + (_transitionRefresh?.RetainedBytes ?? 0L));
 79
 26753380        internal int PersistentPageCount => checked(
 26753381            1
 26753382            + _ownedInstanceExclusivePages
 26753383            + _copiedPersistentPages
 26753384            + GetComposeAdditionalPersistentPages()
 26753385            + (_transitionRefresh?.PersistentPageCount ?? 0));
 86
 87        private long GetComposeAdditionalRetainedBytes()
 88        {
 26718489            if (_compose == null)
 26653690                return 0;
 64891            return checked(
 64892                96L
 64893                + (_composeOwnershipTransferred
 64894                    ? 0L
 64895                    : _compose.AdditionalExclusiveRetainedBytes));
 96        }
 97
 98        private int GetComposeAdditionalPersistentPages()
 99        {
 267533100            if (_compose == null)
 266884101                return 0;
 649102            return checked(
 649103                1
 649104                + (_composeOwnershipTransferred
 649105                    ? 0
 649106                    : _compose.AdditionalExclusivePersistentPages));
 107        }
 108
 109        internal bool Advance(MaintenanceWorkMeter meter)
 110        {
 3937111            while (_changeIndex < _changedMapIds.Count)
 112            {
 1644113                string mapId = _changedMapIds.GetKeyAt(_changeIndex);
 1644114                if (_candidate.TryGetState(
 1644115                        mapId,
 1644116                        out NavigationOperationCandidate.MapState? state)
 1644117                    && state != null)
 118                {
 1633119                    if (!PrepareState(mapId, state, meter))
 276120                        return false;
 121                }
 122                else
 123                {
 11124                    if (!PrepareRemoval(mapId, meter))
 2125                        return false;
 126                }
 1366127                _changeIndex++;
 128            }
 2293129            if (!_rootsPrepared)
 130            {
 1127131                _retainedBytes = checked(
 1127132                    _retainedBytes
 1127133                    - _source._explicitConnections.RetainedBytes
 1127134                    + _candidate.ExplicitConnections.RetainedBytes);
 1127135                _persistentPages += _candidate.ExplicitConnections.PersistentPageCount
 1127136                    - _source._explicitConnections.PersistentPageCount;
 1127137                _prepared = new NavigationWorldGraph(
 1127138                    _version,
 1127139                    _directory,
 1127140                    _source.AreaCatalog,
 1127141                    _mapIndex,
 1127142                    _source.SurfaceComponents,
 1127143                    _candidate.ExplicitConnections,
 1127144                    _source._automaticSeams,
 1127145                    _source.TransitionPages,
 1127146                    _source.TransitionRules,
 1127147                    _source._closedStructuralComponents,
 1127148                    _source._additionalClosedStructuralComponents,
 1127149                    _source._allStructuralComponentsClosed,
 1127150                    _retainedBytes,
 1127151                    _persistentPages);
 1127152                _transitionRefresh = new NavigationTransitionRefreshWork(
 1127153                    _source,
 1127154                    _prepared,
 1127155                    _candidate,
 1127156                    _changedMapIds,
 1127157                    _rebuildTransitionRules,
 1127158                    _version);
 1127159                _rootsPrepared = true;
 160            }
 2293161            if (!_transitionRefresh!.Advance(meter))
 1166162                return false;
 1127163            Result = _prepared!.WithTransitionPublication(
 1127164                _transitionRefresh.Pages,
 1127165                _transitionRefresh.Rules);
 1127166            return true;
 167        }
 168
 169        private bool PrepareState(
 170            string mapId,
 171            NavigationOperationCandidate.MapState state,
 172            MaintenanceWorkMeter meter)
 173        {
 1633174            if (_compose == null)
 175            {
 176                System.Diagnostics.Debug.Assert(_next == null,
 177                    "A prepared instance is retained together with its compose work.");
 1357178                _mapId = mapId;
 1357179                _directory.TryGet(_mapId, out _prior!);
 1357180                if (_prior != null
 1357181                    && ReferenceEquals(_prior.Map, state.Map)
 1357182                    && _prior.BakeVersion == state.BakeVersion
 1357183                    && ReferenceEquals(_prior.Overlay, state.Overlay)
 1357184                    && _prior.DynamicSlotGeneration == state.DynamicSlotGeneration
 1357185                    && ReferenceEquals(_prior.DynamicAddresses, state.DynamicAddresses)
 1357186                    && ReferenceEquals(_prior.BakedCellLookup, state.BakedCellLookup))
 187                {
 22188                    ResetItem();
 22189                    return true;
 190                }
 1335191                bool overlayOnly = _prior != null
 1335192                    && ReferenceEquals(_prior.Map, state.Map)
 1335193                    && _prior.BakeVersion == state.BakeVersion
 1335194                    && _prior.DynamicSlotGeneration == state.DynamicSlotGeneration;
 1335195                _compose = overlayOnly
 1335196                    ? new NavigationMapInstance.ComposeWork(
 1335197                        state,
 1335198                        _prior!,
 1335199                        _changes,
 1335200                        _changeCount,
 1335201                        mapId,
 1335202                        _version)
 1335203                    : new NavigationMapInstance.ComposeWork(state, _prior, _version);
 204            }
 1611205            return AdvanceComposeAndAttach(meter);
 206        }
 207
 208        private bool AdvanceComposeAndAttach(MaintenanceWorkMeter meter)
 209        {
 1611210            if (_next == null)
 211            {
 1391212                if (!_compose!.Advance(meter))
 56213                    return false;
 1335214                _next = _compose.Result;
 215            }
 1555216            if (!_directoryConsumed)
 217            {
 1553218                if (!meter.TryConsumeComponentNodes(1))
 218219                    return false;
 1335220                _ownedInstanceExclusiveBytes = checked(
 1335221                    _ownedInstanceExclusiveBytes + _compose!.AdditionalExclusiveRetainedBytes);
 1335222                _ownedInstanceExclusivePages = checked(
 1335223                    _ownedInstanceExclusivePages + _compose.AdditionalExclusivePersistentPages);
 1335224                _composeOwnershipTransferred = true;
 1335225                NavigationInstanceDirectory nextDirectory = _directory.Set(
 1335226                    _mapId!,
 1335227                    _next,
 1335228                    out int copiedNodes);
 1335229                RecordPersistentCopies(copiedNodes, 64L);
 1335230                _retainedBytes = checked(
 1335231                    _retainedBytes
 1335232                    - _directory.RetainedBytes
 1335233                    + nextDirectory.RetainedBytes
 1335234                    + _next.RetainedBytes
 1335235                    - (_prior?.RetainedBytes ?? 0));
 1335236                _persistentPages += nextDirectory.PersistentPageCount
 1335237                    - _directory.PersistentPageCount
 1335238                    + _next.PersistentPageCount
 1335239                    - (_prior?.PersistentPageCount ?? 0);
 1335240                _directory = nextDirectory;
 1335241                _directoryConsumed = true;
 242            }
 1337243            if (!meter.TryConsumeDependencyEntries(1))
 2244                return false;
 1335245            PersistentGridConfigurationMap<string> before = _mapIndex;
 1335246            if (_prior != null
 1335247                && !_prior.Map.GridBinding.Key.Equals(_next.Map.GridBinding.Key))
 248            {
 1249                _mapIndex = _mapIndex.Remove(
 1250                    _prior.Map.GridBinding.Key,
 1251                    out _,
 1252                    out int removedCopies);
 1253                RecordPersistentCopies(removedCopies, 144L);
 254            }
 1335255            _mapIndex = _mapIndex.Set(
 1335256                _next.Map.GridBinding.Key,
 1335257                _next.MapId,
 1335258                out int setCopies);
 1335259            RecordPersistentCopies(setCopies, 144L);
 1335260            _retainedBytes = checked(
 1335261                _retainedBytes - before.RetainedBytes + _mapIndex.RetainedBytes);
 1335262            _persistentPages += _mapIndex.Count - before.Count;
 1335263            if (_prior == null || !ReferenceEquals(_prior.Map, _next!.Map))
 1131264                _rebuildTransitionRules = true;
 1335265            ResetItem();
 1335266            return true;
 267        }
 268
 269        private bool PrepareRemoval(string mapId, MaintenanceWorkMeter meter)
 270        {
 11271            if (_mapId == null)
 272            {
 9273                _mapId = mapId;
 9274                _directory.TryGet(mapId, out _prior!);
 275                System.Diagnostics.Debug.Assert(_prior != null,
 276                    "The operation fold rejects a removal unless its candidate contains the map.");
 277            }
 11278            if (!_directoryConsumed)
 279            {
 10280                if (!meter.TryConsumeComponentNodes(1))
 1281                    return false;
 9282                NavigationInstanceDirectory nextDirectory =
 9283                    _directory.Remove(mapId, out bool removed, out int copiedNodes);
 284                System.Diagnostics.Debug.Assert(removed,
 285                    "The operation fold emits removals only for maps in its candidate.");
 9286                RecordPersistentCopies(copiedNodes, 64L);
 9287                _retainedBytes = checked(
 9288                    _retainedBytes
 9289                    - _directory.RetainedBytes
 9290                    + nextDirectory.RetainedBytes
 9291                    - _prior!.RetainedBytes);
 9292                _persistentPages += nextDirectory.PersistentPageCount
 9293                    - _directory.PersistentPageCount
 9294                    - _prior.PersistentPageCount;
 9295                _directory = nextDirectory;
 9296                _directoryConsumed = true;
 297            }
 10298            if (!meter.TryConsumeDependencyEntries(1))
 1299                return false;
 9300            PersistentGridConfigurationMap<string> before = _mapIndex;
 9301            _mapIndex = _mapIndex.Remove(
 9302                _prior!.Map.GridBinding.Key,
 9303                out _,
 9304                out int copiedIndexNodes);
 9305            RecordPersistentCopies(copiedIndexNodes, 144L);
 9306            _retainedBytes = checked(
 9307                _retainedBytes - before.RetainedBytes + _mapIndex.RetainedBytes);
 9308            _persistentPages += _mapIndex.Count - before.Count;
 9309            _rebuildTransitionRules = true;
 9310            ResetItem();
 9311            return true;
 312        }
 313
 314        private void ResetItem()
 315        {
 1366316            _compose = null;
 1366317            _prior = null;
 1366318            _next = null;
 1366319            _mapId = null;
 1366320            _directoryConsumed = false;
 1366321            _composeOwnershipTransferred = false;
 1366322        }
 323
 324        private void RecordPersistentCopies(int copiedNodes, long bytesPerNode)
 325        {
 2689326            _copiedPersistentPages = checked(_copiedPersistentPages + copiedNodes);
 2689327            _copiedPersistentBytes = checked(
 2689328                _copiedPersistentBytes + (copiedNodes * bytesPerNode));
 2689329        }
 330    }
 331}

Methods/Properties

.ctor(System.Int64,Trailblazer.Pathing.NavigationMapInstance[],Trailblazer.Pathing.NavigationAreaCatalog,Trailblazer.Pathing.NavigationExplicitConnectionIndex,Trailblazer.Pathing.NavigationSurfaceComponentIndex)
.ctor(System.Int64,Trailblazer.Pathing.NavigationInstanceDirectory,Trailblazer.Pathing.NavigationAreaCatalog,Trailblazer.Pathing.PersistentGridConfigurationMap`1<System.String>,Trailblazer.Pathing.NavigationSurfaceComponentIndex,Trailblazer.Pathing.NavigationExplicitConnectionIndex,Trailblazer.Pathing.NavigationAutomaticSeamIndex,Trailblazer.Pathing.NavigationTransitionPageRoot,Trailblazer.Pathing.NavigationTransitionRuleTable,Trailblazer.Pathing.NavigationSurfaceComponentKeySet,Trailblazer.Pathing.NavigationSurfaceComponentKeySet,System.Boolean,System.Int64,System.Int32)
CreateEmpty(System.Int64)
get_ExplicitConnections()
get_AutomaticSeams()
get_TransitionPages()
TryGetMapId(GridForge.Configuration.GridConfigurationKey,System.String&)
TryGetSeamPrism(Trailblazer.Pathing.NavigationCellAddress,GridForge.Grids.Topology.GridCellPrism&)
HasEffectiveCell(Trailblazer.Pathing.NavigationCellAddress)
TryGetSemanticState(Trailblazer.Pathing.NavigationCellAddress,Trailblazer.Pathing.NavigationCellSemanticSource&,System.Boolean&,Trailblazer.Pathing.NavigationCell&)
EnumerateOutgoingTransitions(Trailblazer.Pathing.NavigationMediumStateRef)
EnumerateOutgoingTransitionCandidates(Trailblazer.Pathing.NavigationMediumStateRef)
EnumerateIncomingTransitions(Trailblazer.Pathing.NavigationMediumStateRef)
EnumerateIncomingTransitionCandidates(Trailblazer.Pathing.NavigationMediumStateRef)
GetPublishedTransition(Trailblazer.Pathing.NavigationIncomingTransitionRef)
IsTransitionActive(Trailblazer.Pathing.NavigationPublishedTransition,Trailblazer.Pathing.NavigationMediumStateRef,System.Boolean)
IsTransitionEndpoint(Trailblazer.Pathing.NavigationPublishedTransition,Trailblazer.Pathing.NavigationMediumStateRef,System.Boolean)
get_MapCount()
TryGetCoveredAddressGeneration(System.Int32,System.String&,GridForge.Grids.Topology.GridCoveredAddressGeneration&)
TryGetCoveredAddressGeneration(System.String,GridForge.Grids.Topology.GridCoveredAddressGeneration&)
TryGetSurfaceComponent(Trailblazer.Pathing.NavigationCellAddress,Trailblazer.TraversalMedium,Trailblazer.Pathing.NavigationSurfaceComponentKey&,System.Int64&)
AreInSameSurfaceComponent(Trailblazer.Pathing.NavigationCellAddress,Trailblazer.TraversalMedium,Trailblazer.Pathing.NavigationCellAddress,Trailblazer.TraversalMedium)
get_EmptyMapIndexRetainedBytes()
get_EmptyMapIndexPersistentPageCount()
get_EmptyClosedStructuralComponentsRetainedBytes()
get_EmptyClosedStructuralComponentsPersistentPageCount()
get_LeaseCount()
GetInstance(System.Int32)
IsWithinDynamicSlotCapacity(System.Int32,System.Int32)
Checkout()
Return()
TryGetMap(System.String,Trailblazer.Pathing.NavigationMapInstance&)
IsSurfaceAddressClosed(Trailblazer.Pathing.NavigationCellAddress,Trailblazer.TraversalMedium)
IsSurfaceComponentClosed(Trailblazer.Pathing.NavigationSurfaceComponentKey)
WithSurfaceComponents(Trailblazer.Pathing.NavigationSurfaceComponentIndex)
WithAutomaticSeams(Trailblazer.Pathing.NavigationAutomaticSeamIndex)
WithTransitionPublication(Trailblazer.Pathing.NavigationTransitionPageRoot,Trailblazer.Pathing.NavigationTransitionRuleTable)
WithClosedStructuralComponents(Trailblazer.Pathing.NavigationSurfaceComponentKeySet,System.Boolean,System.Int64)
WithOwnedStructuralClosure(Trailblazer.Pathing.NavigationSurfaceComponentKeySet,Trailblazer.Pathing.NavigationSurfaceComponentKeySet,System.Boolean,System.Int64)
WithStructuralClosureFrom(Trailblazer.Pathing.NavigationWorldGraph,System.Int64)
get_HasClosedStructuralScope()
get_ClosedStructuralComponents()
RetainsClosedComponentRoot(Trailblazer.Pathing.NavigationSurfaceComponentKeySet)
GetClosedRootRetainedBytes()
GetClosedRootPersistentPages()
GetAdditionalClosedRootRetainedBytes(Trailblazer.Pathing.NavigationSurfaceComponentKeySet,Trailblazer.Pathing.NavigationSurfaceComponentKeySet)
GetAdditionalClosedRootPersistentPages(Trailblazer.Pathing.NavigationSurfaceComponentKeySet,Trailblazer.Pathing.NavigationSurfaceComponentKeySet)
get_AreAllStructuralComponentsClosed()
ReopenStructuralScopes(System.Int64)
CaptureMaintenanceSnapshot(GridForge.Grids.GridWorld,Trailblazer.Pathing.NavigationWorldGraph,System.ReadOnlySpan`1<GridForge.Grids.GridEventInfo>,System.ReadOnlySpan`1<Trailblazer.Pathing.NavigationGridChangeScope>,System.Boolean,System.ReadOnlySpan`1<Trailblazer.Pathing.NavigationGridChangeScope>,System.Boolean,Trailblazer.Pathing.NavigationOperationFrameChange[],System.Int32,Trailblazer.Pathing.MaintenanceWorkMeter,System.Int64,System.Int32,Trailblazer.Pathing.NavigationGridBaselineCapture[],Trailblazer.Pathing.PersistentStringMap`1<Trailblazer.Pathing.NavigationBaselineRebuild>&,System.Span`1<GridForge.Spatial.VoxelIndex>,System.Span`1<GridForge.Grids.Topology.GridCoveredAddress>,System.Span`1<Trailblazer.Pathing.NavigationGridChangeScope>,System.Int32&,System.Boolean&,System.Int32[],System.Int32[],System.Int32&,System.Int32&)
TryAddBaselineRebuild(Trailblazer.Pathing.PersistentStringMap`1<Trailblazer.Pathing.NavigationBaselineRebuild>&,Trailblazer.Pathing.NavigationBaselineRebuild,System.Int64,System.Int32,System.Int64,System.Int32,System.Int64&,System.Int32&)
RemoveBaselineRebuild(Trailblazer.Pathing.PersistentStringMap`1<Trailblazer.Pathing.NavigationBaselineRebuild>&,System.String,Trailblazer.Pathing.NavigationBaselineRebuild,System.Int64&,System.Int32&)
GetBaselineRebuildRegistryFootprint(Trailblazer.Pathing.PersistentStringMap`1<Trailblazer.Pathing.NavigationBaselineRebuild>,System.Int64&,System.Int32&)
ApplyMaintenanceSnapshot(System.Int64,Trailblazer.Pathing.NavigationWorldGraph,System.ReadOnlySpan`1<GridForge.Grids.GridEventInfo>,System.ReadOnlySpan`1<Trailblazer.Pathing.NavigationGridChangeScope>,System.Boolean,System.ReadOnlySpan`1<Trailblazer.Pathing.NavigationGridChangeScope>,System.Boolean,Trailblazer.Pathing.NavigationOperationFrameChange[],System.Int32,Trailblazer.Pathing.NavigationGridBaselineCapture[],System.Int32[],System.Int32,System.Int64)
WithAreaCatalog(Trailblazer.Pathing.NavigationAreaCatalog,System.Int64)
WithGraphVersion(System.Int64)
TryGetDependencyStamp(Trailblazer.Pathing.NavigationAreaPolicyKey,System.ReadOnlySpan`1<Trailblazer.Pathing.NavigationSurfaceComponentKey>,System.ReadOnlySpan`1<Trailblazer.Pathing.GraphPageDependencyAddress>,Trailblazer.Pathing.GraphDependencyStamp&)
TryGetDependencyStamp(Trailblazer.Pathing.NavigationAreaPolicyKey,System.ReadOnlySpan`1<Trailblazer.Pathing.NavigationSurfaceComponentKey>,System.ReadOnlySpan`1<Trailblazer.Pathing.GraphPageDependencyAddress>,System.Boolean,Trailblazer.Pathing.GraphDependencyStamp&)
TryGetComponentDependency(Trailblazer.Pathing.NavigationSurfaceComponentKey,Trailblazer.Pathing.GraphComponentDependency&)
TryGetPageDependency(Trailblazer.Pathing.GraphPageDependencyAddress,Trailblazer.Pathing.GraphPageDependency&)
TryGetPageDependency(Trailblazer.Pathing.GraphPageDependencyAddress,System.Boolean,Trailblazer.Pathing.GraphPageDependency&)
IsDependencyCurrent(Trailblazer.Pathing.GraphDependencyStamp)
BuildMapIndex(Trailblazer.Pathing.NavigationMapInstance[])
FindMapOrdinal(System.String)
CollectAffectedMaps(System.ReadOnlySpan`1<GridForge.Grids.GridEventInfo>,System.ReadOnlySpan`1<Trailblazer.Pathing.NavigationGridChangeScope>,System.Boolean,System.ReadOnlySpan`1<Trailblazer.Pathing.NavigationGridChangeScope>,System.Boolean,Trailblazer.Pathing.NavigationOperationFrameChange[],System.Int32,System.Int32[],System.Int32[],System.Int32&)
MarkOperationChanges(Trailblazer.Pathing.NavigationOperationFrameChange[],System.Int32,System.Int32[],System.Int32&,System.Int32[],System.Int32)
MarkMapId(System.String,System.Int32[],System.Int32&,System.Int32[],System.Int32)
MarkConfiguration(GridForge.Configuration.GridConfigurationKey,System.Int32[],System.Int32&,System.Int32[],System.Int32)
TryMarkOrdinal(System.Int32,System.Int32[],System.Int32&,System.Int32[],System.Int32)
ContainsScope(System.ReadOnlySpan`1<Trailblazer.Pathing.NavigationGridChangeScope>,GridForge.Configuration.GridConfigurationKey)
EventsRequireBaseline(System.ReadOnlySpan`1<GridForge.Grids.GridEventInfo>,GridForge.Configuration.GridConfigurationKey,System.Boolean)
IsOperationChanged(Trailblazer.Pathing.NavigationOperationFrameChange[],System.Int32,System.String)
IsCellOverlayOnlyChanged(Trailblazer.Pathing.NavigationOperationFrameChange[],System.Int32,System.String)
TryGetNodeRef(System.Int32,GridForge.Spatial.VoxelIndex,Trailblazer.Pathing.NavigationNodeRef&)
TryGetNodeRef(Trailblazer.Pathing.NavigationCellAddress,Trailblazer.Pathing.NavigationNodeRef&)
TryGetNodeAddress(Trailblazer.Pathing.NavigationNodeRef,Trailblazer.Pathing.NavigationCellAddress&)
TryGetNodeState(Trailblazer.Pathing.NavigationNodeRef,Trailblazer.Pathing.NavigationNodeState&)
TryGetNodeState(Trailblazer.Pathing.NavigationNodeRef,Trailblazer.TraversalMedium,Trailblazer.Pathing.NavigationNodeState&)
TryGetRawNodeState(Trailblazer.Pathing.NavigationNodeRef,Trailblazer.Pathing.NavigationNodeState&)
TryGetRawNodeState(Trailblazer.Pathing.NavigationNodeRef,Trailblazer.Pathing.NavigationMapInstance,GridForge.Spatial.VoxelIndex,Trailblazer.Pathing.NavigationNodeState&)
GetCompleteDirectionCount(Trailblazer.Pathing.NavigationNodeRef)
TryGetCompleteNeighbor(Trailblazer.Pathing.NavigationNodeRef,System.Int32,Trailblazer.Pathing.NavigationNodeRef&,System.Boolean&)
TryGetMediumStateRef(Trailblazer.Pathing.NavigationCellAddress,Trailblazer.TraversalMedium,Trailblazer.Pathing.NavigationMediumStateRef&)
TryGetStructuralMediumStateRef(Trailblazer.Pathing.NavigationCellAddress,Trailblazer.TraversalMedium,Trailblazer.Pathing.NavigationMediumStateRef&)
GetPrimaryDirectionCount(Trailblazer.Pathing.NavigationNodeRef)
TryGetStructuralPrimaryMediumNeighbor(Trailblazer.Pathing.NavigationMediumStateRef,System.Int32,Trailblazer.Pathing.NavigationMediumStateRef&)
TryGetPrimaryNeighbor(Trailblazer.Pathing.NavigationNodeRef,System.Int32,Trailblazer.Pathing.NavigationNodeRef&)
EnumerateNativeSurfaceEdges(Trailblazer.Pathing.NavigationNodeRef)
EnumerateStructuralNativeSurfaceEdges(Trailblazer.Pathing.NavigationNodeRef)
EnumerateSurfaceEdges(Trailblazer.Pathing.NavigationNodeRef)
EnumerateIncomingSurfaceEdges(Trailblazer.Pathing.NavigationNodeRef)
EnumerateStructuralSurfaceEdges(Trailblazer.Pathing.NavigationNodeRef)
EnumerateIncomingStructuralSurfaceEdges(Trailblazer.Pathing.NavigationNodeRef)
EnumerateIncomingExplicitSurfaceEdges(Trailblazer.Pathing.NavigationNodeRef)
TryGetNodeLocation(Trailblazer.Pathing.NavigationNodeRef,Trailblazer.Pathing.NavigationMapInstance&,GridForge.Spatial.VoxelIndex&)
.ctor(Trailblazer.Pathing.NavigationWorldGraph,Trailblazer.Pathing.NavigationOperationCandidate,Trailblazer.Pathing.NavigationOperationFrameChange[],System.Int32,Trailblazer.Pathing.PersistentStringMap`1<System.Boolean>,System.Int64)
get_IsComplete()
get_RetainedBytes()
get_PersistentPageCount()
GetComposeAdditionalRetainedBytes()
GetComposeAdditionalPersistentPages()
Advance(Trailblazer.Pathing.MaintenanceWorkMeter)
PrepareState(System.String,Trailblazer.Pathing.NavigationOperationCandidate/MapState,Trailblazer.Pathing.MaintenanceWorkMeter)
AdvanceComposeAndAttach(Trailblazer.Pathing.MaintenanceWorkMeter)
PrepareRemoval(System.String,Trailblazer.Pathing.MaintenanceWorkMeter)
ResetItem()
RecordPersistentCopies(System.Int32,System.Int64)