/// <summary> /// Checks to see if this cached path is still valid. If not, the cached parameters are /// updated assuming that pathing is recalculated. /// </summary> /// <param name="navGrid">The navigation grid to use.</param> /// <param name="newCell">The starting cell.</param> /// <param name="navType">The navigation type currently in use.</param> /// <param name="abilities">The path finder's current abilities.</param> /// <param name="newFlags">The path finder's current flags.</param> /// <returns>true if cached information can be used, or false otherwise.</returns> public bool CheckAndUpdate(NavGrid navGrid, int newCell, NavType navType, PathFinderAbilities abilities, PathFlags newFlags) { if (navGrid == null) { throw new ArgumentNullException("navGrid"); } if (abilities == null) { throw new ArgumentNullException("abilities"); } bool ok = false; if (NavFences.AllFences.TryGetValue(navGrid.id, out NavFences fences)) { long serial = fences.CurrentSerial; if (serial == globalSerial && flags == newFlags) { ok = (cell == newCell) || CanNavigateReciprocal(cell, newCell, navGrid, navType, abilities, newFlags); } else { // Guaranteed out of date flags = newFlags; globalSerial = serial; } cell = newCell; } return(ok); }
/// <summary> /// Checks to see if this cached path is still valid. If not, the cached parameters are /// updated assuming that pathing is recalculated. /// </summary> /// <param name="navigator">The navigator to use.</param> /// <param name="newCell">The starting cell.</param> /// <returns>true if cached information can be used, or false otherwise.</returns> public bool CheckAndUpdate(Navigator navigator, int newCell) { if (navigator == null) { throw new ArgumentNullException("navigator"); } bool ok = false; var newFlags = navigator.flags; var navGrid = navigator.NavGrid; if (NavFences.AllFences.TryGetValue(navGrid.id, out NavFences fences)) { long serial = fences.CurrentSerial; if (serial == globalSerial && flags == newFlags) { ok = (cell == newCell) || !PathFinder.ValidatePath(navGrid, ABILITIES. Get(navigator), ref navigator.path); } else { // Guaranteed out of date flags = newFlags; globalSerial = serial; } cell = newCell; } return(ok); }
public static bool TryGetSuitMarkerFlags(int cell, out SuitMarker.Flags flags, out PathFinder.PotentialPath.Flags pathFlags) { if (HasSuitMarker[cell]) { SuitMarker suitMarker = suitMarkers[cell]; flags = suitMarker.flags; SuitMarker suitMarker2 = suitMarkers[cell]; pathFlags = suitMarker2.pathFlags; return(true); } flags = (SuitMarker.Flags) 0; pathFlags = PathFinder.PotentialPath.Flags.None; return(false); }
internal static bool Prefix(PathProber __instance, int cell, NavType nav_type, PathFinder.PotentialPath.Flags flags, NavGrid nav_grid, PathFinderAbilities abilities) { // If nothing has changed since last time, it is a hit! var cached = PathCacher.Lookup(__instance); bool hit; if (hit = cached.CheckAndUpdate(nav_grid, cell, nav_type, abilities, flags)) { Interlocked.Increment(ref hits); } Interlocked.Increment(ref total); return(!hit); }
public void ClearFlags(PathFinder.PotentialPath.Flags new_flags) { flags &= (PathFinder.PotentialPath.Flags)(byte)(~(uint)new_flags); }
public void SetFlags(PathFinder.PotentialPath.Flags new_flags) { flags |= new_flags; }
public void UpdateProbe(NavGrid nav_grid, int cell, NavType nav_type, PathFinderAbilities abilities, PathFinder.PotentialPath.Flags flags) { if (scratchPad == null) { scratchPad = new PathFinder.PotentialScratchPad(nav_grid.maxLinksPerCell); } bool flag = updateCount == -1; bool flag2 = Potentials.Count == 0 || flag; PathGrid.BeginUpdate(cell, !flag2); bool is_cell_in_range; if (flag2) { updateCount = 0; PathFinder.Cell cell_data = PathGrid.GetCell(cell, nav_type, out is_cell_in_range); PathFinder.PotentialPath potential_path = new PathFinder.PotentialPath(cell, nav_type, flags); PathFinder.AddPotential(potential_path, Grid.InvalidCell, NavType.NumNavTypes, 0, 0, -1, Potentials, PathGrid, ref cell_data); } int num = (potentialCellsPerUpdate > 0 && !flag) ? potentialCellsPerUpdate : 2147483647; updateCount++; while (Potentials.Count > 0 && num > 0) { KeyValuePair <int, PathFinder.PotentialPath> keyValuePair = Potentials.Next(); num--; PathFinder.Cell cell2 = PathGrid.GetCell(keyValuePair.Value, out is_cell_in_range); if (cell2.cost == keyValuePair.Key) { PathFinder.AddPotentials(scratchPad, keyValuePair.Value, cell2.cost, cell2.underwaterCost, ref abilities, null, nav_grid.maxLinksPerCell, nav_grid.Links, Potentials, PathGrid, cell2.parent, cell2.parentNavType); } } bool flag3 = Potentials.Count == 0; PathGrid.EndUpdate(flag3); if (flag3 && updateCount > 25) { KProfiler.AddEvent("PathProberUpdateCountExceeded"); } }
public override bool TraversePath(ref PathFinder.PotentialPath path, int from_cell, NavType from_nav_type, int cost, int transition_id, int underwater_cost) { if (!IsAccessPermitted(proxyID, path.cell, from_cell)) { return(false); } CellOffset[] array = transitionVoidOffsets[transition_id]; foreach (CellOffset offset in array) { int cell = Grid.OffsetCell(from_cell, offset); if (!IsAccessPermitted(proxyID, cell, from_cell)) { return(false); } } if (path.navType == NavType.Tube && from_nav_type == NavType.Floor && !Grid.HasUsableTubeEntrance(from_cell, prefabInstanceID)) { return(false); } if (path.navType == NavType.Hover && (out_of_fuel || !path.HasFlag(PathFinder.PotentialPath.Flags.HasJetPack))) { return(false); } Grid.SuitMarker.Flags flags = (Grid.SuitMarker.Flags) 0; PathFinder.PotentialPath.Flags pathFlags = PathFinder.PotentialPath.Flags.None; bool flag = path.HasFlag(PathFinder.PotentialPath.Flags.PerformSuitChecks) && Grid.TryGetSuitMarkerFlags(from_cell, out flags, out pathFlags) && (flags & Grid.SuitMarker.Flags.Operational) != (Grid.SuitMarker.Flags) 0; bool flag2 = SuitMarker.DoesTraversalDirectionRequireSuit(from_cell, path.cell, flags); bool flag3 = path.HasAnyFlag(PathFinder.PotentialPath.Flags.HasAtmoSuit | PathFinder.PotentialPath.Flags.HasJetPack); if (flag) { bool flag4 = path.HasFlag(pathFlags); if (flag2) { if (!flag3 && !Grid.HasSuit(from_cell, prefabInstanceID)) { return(false); } } else if (flag3 && (flags & Grid.SuitMarker.Flags.OnlyTraverseIfUnequipAvailable) != 0 && (!flag4 || !Grid.HasEmptyLocker(from_cell, prefabInstanceID))) { return(false); } } if (idleNavMaskEnabled && (Grid.PreventIdleTraversal[path.cell] || Grid.PreventIdleTraversal[from_cell])) { return(false); } if (flag) { if (flag2) { if (!flag3) { path.SetFlags(pathFlags); } } else { path.ClearFlags(PathFinder.PotentialPath.Flags.HasAtmoSuit | PathFinder.PotentialPath.Flags.HasJetPack); } } return(true); }
/// <summary> /// Checks to see if the navigator can reciprocally go back and forth between a cell /// and another cell, checking only if they are immediately reachable. /// </summary> /// <param name="fromCell">The cell where the navigator is currently located.</param> /// <param name="toCell">The potential destination cell.</param> /// <param name="navGrid">The navigation grid to use for lookups.</param> /// <param name="startNavType">The navigation type to use.</param> /// <param name="abilities">The current navigator abilities.</param> /// <param name="newFlags">The flags available for this path.</param> /// <returns>true if navigation can be performed, both ways, or false otherwise.</returns> private static bool CanNavigateReciprocal(int fromCell, int toCell, NavGrid navGrid, NavType startNavType, PathFinderAbilities abilities, PathFlags flags) { var grid = PathFinder.PathGrid; bool ok = false; // Find a link from this cell to the target cell var link = FindLinkToCell(fromCell, toCell, navGrid, startNavType); if (link.link != InvalidHandle) { var endNavType = link.endNavType; var pp = new PathFinder.PotentialPath(toCell, endNavType, flags); int uwCost = grid.GetCell(toCell, endNavType, out _).underwaterCost; // Can navigate there, and has a link back? if (abilities.TraversePath(ref pp, fromCell, startNavType, link.cost, link. transitionId, uwCost) && (link = FindLinkToCell(toCell, fromCell, navGrid, endNavType)).link != InvalidHandle) { pp.cell = fromCell; pp.navType = startNavType; uwCost = grid.GetCell(fromCell, startNavType, out _).underwaterCost; ok = abilities.TraversePath(ref pp, toCell, endNavType, link.cost, link.transitionId, uwCost); } } return(ok); }
private PathCacher() { cell = -1; flags = PathFlags.None; globalSerial = 0L; }
public static void UpdateSuitMarker(int cell, int fullLockerCount, int emptyLockerCount, SuitMarker.Flags flags, PathFinder.PotentialPath.Flags pathFlags) { DebugUtil.Assert(HasSuitMarker[cell]); SuitMarker value = suitMarkers[cell]; value.suitCount = fullLockerCount; value.lockerCount = fullLockerCount + emptyLockerCount; value.flags = flags; value.pathFlags = pathFlags; suitMarkers[cell] = value; }