Better AI reachable cleanup (#1507)
Haven't profiled so can't say if it definitely fixes the leak. Co-authored-by: Metal Gear Sloth <metalgearsloth@gmail.com>
This commit is contained in:
@@ -75,6 +75,8 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
|
|||||||
private Dictionary<ReachableArgs, Dictionary<PathfindingRegion, (TimeSpan CacheTime, HashSet<PathfindingRegion> Regions)>> _cachedAccessible =
|
private Dictionary<ReachableArgs, Dictionary<PathfindingRegion, (TimeSpan CacheTime, HashSet<PathfindingRegion> Regions)>> _cachedAccessible =
|
||||||
new Dictionary<ReachableArgs, Dictionary<PathfindingRegion, (TimeSpan, HashSet<PathfindingRegion>)>>();
|
new Dictionary<ReachableArgs, Dictionary<PathfindingRegion, (TimeSpan, HashSet<PathfindingRegion>)>>();
|
||||||
|
|
||||||
|
private readonly List<PathfindingRegion> _queuedCacheDeletions = new List<PathfindingRegion>();
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
private int _runningCacheIdx = 0;
|
private int _runningCacheIdx = 0;
|
||||||
#endif
|
#endif
|
||||||
@@ -115,6 +117,13 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
_queuedUpdates.Clear();
|
_queuedUpdates.Clear();
|
||||||
|
|
||||||
|
foreach (var region in _queuedCacheDeletions)
|
||||||
|
{
|
||||||
|
ClearCache(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
_queuedCacheDeletions.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Shutdown()
|
public override void Shutdown()
|
||||||
@@ -123,6 +132,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
|
|||||||
_queuedUpdates.Clear();
|
_queuedUpdates.Clear();
|
||||||
_regions.Clear();
|
_regions.Clear();
|
||||||
_cachedAccessible.Clear();
|
_cachedAccessible.Clear();
|
||||||
|
_queuedCacheDeletions.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResettingCleanup()
|
public void ResettingCleanup()
|
||||||
@@ -130,6 +140,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
|
|||||||
_queuedUpdates.Clear();
|
_queuedUpdates.Clear();
|
||||||
_regions.Clear();
|
_regions.Clear();
|
||||||
_cachedAccessible.Clear();
|
_cachedAccessible.Clear();
|
||||||
|
_queuedCacheDeletions.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecalculateNodeRegions(PathfindingChunkUpdateMessage message)
|
private void RecalculateNodeRegions(PathfindingChunkUpdateMessage message)
|
||||||
@@ -216,7 +227,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
|
|||||||
public HashSet<PathfindingRegion> GetReachableRegions(ReachableArgs reachableArgs, PathfindingRegion region)
|
public HashSet<PathfindingRegion> GetReachableRegions(ReachableArgs reachableArgs, PathfindingRegion region)
|
||||||
{
|
{
|
||||||
// if we're on a node that's not tracked at all atm then region will be null
|
// if we're on a node that's not tracked at all atm then region will be null
|
||||||
if (region == null)
|
if (region == null || region.Deleted)
|
||||||
{
|
{
|
||||||
return new HashSet<PathfindingRegion>();
|
return new HashSet<PathfindingRegion>();
|
||||||
}
|
}
|
||||||
@@ -345,7 +356,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
|
|||||||
|
|
||||||
foreach (var neighbor in region.Neighbors)
|
foreach (var neighbor in region.Neighbors)
|
||||||
{
|
{
|
||||||
if (closedSet.Contains(neighbor))
|
if (closedSet.Contains(neighbor) || neighbor.Deleted)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -530,6 +541,9 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
|
|||||||
}
|
}
|
||||||
|
|
||||||
source.Shutdown();
|
source.Shutdown();
|
||||||
|
// This doesn't check the cachedaccessible to see if it's reachable but maybe it should?
|
||||||
|
// Although currently merge gets spammed so maybe when some other stuff is improved
|
||||||
|
// MergeInto is also only called by GenerateRegions currently so nothing should hold onto the original region
|
||||||
_regions[source.ParentChunk.GridId][source.ParentChunk].Remove(source);
|
_regions[source.ParentChunk.GridId][source.ParentChunk].Remove(source);
|
||||||
|
|
||||||
foreach (var node in target.Nodes)
|
foreach (var node in target.Nodes)
|
||||||
@@ -538,6 +552,40 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove the cached accessibility lookup for this region
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="region"></param>
|
||||||
|
private void ClearCache(PathfindingRegion region)
|
||||||
|
{
|
||||||
|
// Need to forcibly clear cache for ourself and anything that includes us
|
||||||
|
foreach (var (_, cachedRegions) in _cachedAccessible)
|
||||||
|
{
|
||||||
|
if (cachedRegions.ContainsKey(region))
|
||||||
|
{
|
||||||
|
cachedRegions.Remove(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seemed like the safest way to remove this
|
||||||
|
// We could just have GetVisionAccessible remove us if it can tell we're deleted but that
|
||||||
|
// seems like it could be unreliable
|
||||||
|
var regionsToClear = new List<PathfindingRegion>();
|
||||||
|
|
||||||
|
foreach (var (otherRegion, cache) in cachedRegions)
|
||||||
|
{
|
||||||
|
if (cache.Regions.Contains(region))
|
||||||
|
{
|
||||||
|
regionsToClear.Add(otherRegion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var otherRegion in regionsToClear)
|
||||||
|
{
|
||||||
|
cachedRegions.Remove(otherRegion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generate all of the regions within a chunk
|
/// Generate all of the regions within a chunk
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -554,8 +602,10 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
|
|||||||
{
|
{
|
||||||
foreach (var region in regions)
|
foreach (var region in regions)
|
||||||
{
|
{
|
||||||
|
_queuedCacheDeletions.Add(region);
|
||||||
region.Shutdown();
|
region.Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
_regions[chunk.GridId].Remove(chunk);
|
_regions[chunk.GridId].Remove(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
|
|||||||
public HashSet<PathfindingNode> Nodes => _nodes;
|
public HashSet<PathfindingNode> Nodes => _nodes;
|
||||||
private HashSet<PathfindingNode> _nodes;
|
private HashSet<PathfindingNode> _nodes;
|
||||||
|
|
||||||
|
public bool Deleted { get; private set; }
|
||||||
|
|
||||||
public PathfindingRegion(PathfindingNode originNode, HashSet<PathfindingNode> nodes, bool isDoor = false)
|
public PathfindingRegion(PathfindingNode originNode, HashSet<PathfindingNode> nodes, bool isDoor = false)
|
||||||
{
|
{
|
||||||
OriginNode = originNode;
|
OriginNode = originNode;
|
||||||
@@ -53,6 +55,8 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
|
|||||||
var neighbor = neighbors[i];
|
var neighbor = neighbors[i];
|
||||||
neighbor.Neighbors.Remove(this);
|
neighbor.Neighbors.Remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Deleted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user