< Summary

Information
Class: Trailblazer.Pathing.VolumeChartPartition
Assembly: Trailblazer
File(s): /home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Partition/VolumeChartPartition.cs
Line coverage
94%
Covered lines: 52
Uncovered lines: 3
Coverable lines: 55
Total lines: 200
Line coverage: 94.5%
Branch coverage
80%
Covered branches: 21
Total branches: 26
Branch coverage: 80.7%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_HasAnyOwners()100%22100%
get_PathCostModifier()100%11100%
set_PathCostModifier(...)100%11100%
SetParentIndex(...)100%11100%
SetOwner(...)100%11100%
OnAddToVoxel(...)100%11100%
OnRemoveFromVoxel(...)50%2271.42%
HandleChange(...)100%22100%
SupportsMedium(...)100%44100%
BelongsTo(...)100%22100%
IsImpassable(...)50%22100%
Reset()100%22100%
get_Voxel()50%6687.5%
ApplyAuthoredState(...)100%44100%

File(s)

/home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Partition/VolumeChartPartition.cs

#LineLine coverage
 1using FixedMathSharp;
 2using GridForge.Grids;
 3using GridForge.Spatial;
 4using SwiftCollections;
 5using System;
 6using System.Runtime.CompilerServices;
 7
 8namespace Trailblazer.Pathing;
 9
 10/// <summary>
 11/// Represents authored raw-volume traversal data attached to a voxel.
 12/// </summary>
 13public sealed class VolumeChartPartition : IVoxelPartition
 14{
 15    private int _manualPathCostModifier;
 16
 17    private int _chartPathCostModifier;
 18
 19    private TraversalMedia _volumeKinds;
 20
 21    /// <summary>
 22    /// The world-scoped coordinate of the voxel this partition is attached to.
 23    /// </summary>
 24    public WorldVoxelIndex WorldIndex { get; private set; }
 25
 26    internal PathingWorldState? OwnerState { get; private set; }
 27
 28    /// <summary>
 29    /// The world-space position of the authored voxel.
 30    /// </summary>
 31    public Vector3d VoxelPosition { get; private set; }
 32
 33    /// <summary>
 34    /// Indicates whether the voxel itself is currently unblocked.
 35    /// </summary>
 36    public bool IsWalkable { get; private set; }
 37
 38    /// <summary>
 39    /// Charts that currently contribute authored volume data to this voxel.
 40    /// </summary>
 41    public SwiftHashSet<string>? ChartOwners { get; private set; }
 42
 43    /// <summary>
 44    /// Returns true if any chart currently contributes authored volume data to this voxel.
 45    /// </summary>
 546    public bool HasAnyOwners => ChartOwners?.Count > 0;
 47
 48    /// <summary>
 49    /// The chart whose authored cell currently wins overlap resolution for this voxel.
 50    /// </summary>
 51    public string? EffectiveChartOwner { get; private set; }
 52
 53    /// <summary>
 54    /// Additional authored or caller-controlled path cost for this volume voxel.
 55    /// </summary>
 56    public int PathCostModifier
 57    {
 58        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 73759        get => _manualPathCostModifier + _chartPathCostModifier;
 60        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 60961        set => _manualPathCostModifier = value;
 62    }
 63
 64    /// <summary>
 65    /// Sets the parent index for this voxel in the world structure.
 66    /// </summary>
 67    /// <param name="parentIndex">The index representing the parent voxel to assign. Must be a valid WorldVoxelIndex.</p
 60768    public void SetParentIndex(WorldVoxelIndex parentIndex) => WorldIndex = parentIndex;
 69
 60770    internal void SetOwner(PathingWorldState ownerState) => OwnerState = ownerState;
 71
 72    /// <summary>
 73    /// Initializes the obstacle's state based on the specified voxel and subscribes to voxel change events.
 74    /// </summary>
 75    /// <remarks>
 76    /// This method updates the obstacle's world index, position, and walkability status to match the provided voxel.
 77    /// It also attaches event handlers to respond to changes in the voxel's obstacle state.
 78    /// </remarks>
 79    /// <param name="voxel">The voxel to which the obstacle is being added. Cannot be null.</param>
 80    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 81    public void OnAddToVoxel(Voxel voxel)
 82    {
 60783        voxel.OnObstacleAdded += HandleChange;
 60784        voxel.OnObstacleRemoved += HandleChange;
 85
 60786        WorldIndex = voxel.WorldIndex;
 60787        VoxelPosition = voxel.WorldPosition;
 60788        IsWalkable = !voxel.IsBlocked;
 60789    }
 90
 91    /// <summary>
 92    /// Handles cleanup when this object is removed from the specified voxel, including detaching event handlers and rel
 93    /// </summary>
 94    /// <remarks>
 95    /// After calling this method, the object should not be used with the specified voxel unless re-added.
 96    /// This method also releases the object back to the partition pool for reuse.
 97    /// </remarks>
 98    /// <param name="voxel">The voxel from which this object is being removed. Cannot be null.</param>
 99    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 100    public void OnRemoveFromVoxel(Voxel voxel)
 101    {
 607102        voxel.OnObstacleAdded -= HandleChange;
 607103        voxel.OnObstacleRemoved -= HandleChange;
 104
 607105        PathingWorldState? ownerState = OwnerState;
 607106        if (ownerState != null)
 607107            ownerState.VolumeChartPartitionPool.Release(this);
 108        else
 0109            PathManager.VolumeChartPartitionPool.Release(this);
 0110    }
 111
 112    /// <summary>
 113    /// Updates the walkability state based on the provided obstacle event information.
 114    /// </summary>
 115    /// <remarks>
 116    /// Call this method when obstacle state changes to ensure the walkability property reflects the current environment
 117    /// </remarks>
 118    /// <param name="eventInfo">
 119    /// The event data containing voxel index and obstacle count information used to determine walkability. Cannot be nu
 120    /// </param>
 121    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 122    public void HandleChange(ObstacleEventInfo eventInfo)
 123    {
 5124        IsWalkable = eventInfo.VoxelIndex != default && eventInfo.ObstacleCount == 0;
 5125    }
 126
 127    /// <summary>
 128    /// Returns true if this partition currently supports the requested raw volume traversal medium.
 129    /// </summary>
 130    public bool SupportsMedium(TraversalMedium medium)
 131    {
 7520132        return medium switch
 7520133        {
 3758134            TraversalMedium.Gas => (_volumeKinds & TraversalMedia.Gas) != 0,
 3760135            TraversalMedium.Liquid => (_volumeKinds & TraversalMedia.Liquid) != 0,
 2136            _ => false
 7520137        };
 138    }
 139
 140    /// <summary>
 141    /// Returns true if this partition is claimed by the given chart name.
 142    /// </summary>
 143    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 2144    public bool BelongsTo(string chartName) => ChartOwners?.Contains(chartName) == true;
 145
 146    /// <summary>
 147    /// Returns true if the requested unit size cannot fit through this voxel.
 148    /// </summary>
 149    internal bool IsImpassable(Fixed64 unitSize)
 150    {
 3536151        PathingWorldState ownerState = OwnerState
 3536152            ?? throw new InvalidOperationException("Volume chart partition requires an owning pathing context.");
 3536153        return !VolumeVoxelFinder.HasClearance(ownerState.Context, Voxel, unitSize);
 154    }
 155
 156    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 157    internal void Reset()
 158    {
 608159        WorldIndex = default;
 608160        OwnerState = null;
 608161        VoxelPosition = default;
 608162        IsWalkable = false;
 608163        PathCostModifier = 0;
 608164        _chartPathCostModifier = 0;
 608165        _volumeKinds = TraversalMedia.None;
 608166        ChartOwners?.Clear();
 608167        EffectiveChartOwner = null;
 608168    }
 169
 170    private Voxel Voxel
 171    {
 172        get
 173        {
 3536174            PathingWorldState? ownerState = OwnerState;
 3536175            Voxel? voxel = null;
 3536176            bool found = ownerState != null
 3536177                && ownerState.World.TryGetGridAndVoxel(WorldIndex, out _, out voxel);
 178
 3536179            if (found
 3536180                && voxel != null)
 3536181                return voxel;
 182
 0183            throw new InvalidOperationException($"Volume partition at {WorldIndex} is not attached to a valid voxel.");
 184        }
 185    }
 186
 187    internal void ApplyAuthoredState(
 188        ResolvedChartVoxelState? state,
 189        string? effectiveChartOwner,
 190        NavigationChartCell effectiveCell)
 191    {
 614192        ChartOwners ??= new SwiftHashSet<string>();
 614193        ChartOwners.Clear();
 614194        state?.AddChartOwnersTo(ChartOwners);
 195
 614196        EffectiveChartOwner = effectiveChartOwner;
 614197        _chartPathCostModifier = effectiveCell.PathCostModifier;
 614198        _volumeKinds = effectiveCell.TraversalKinds & TraversalMedia.AnyVolume;
 614199    }
 200}