AI reachable improvements (#1595)

Deleted regions in some instances were being retained indefinitely.

Co-authored-by: Metal Gear Sloth <metalgearsloth@gmail.com>
This commit is contained in:
metalgearsloth
2020-08-06 00:19:00 +10:00
committed by GitHub
parent c5d3bff266
commit 140f8f7647
2 changed files with 38 additions and 10 deletions

View File

@@ -123,7 +123,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
{ {
ClearCache(region); ClearCache(region);
} }
_queuedCacheDeletions.Clear(); _queuedCacheDeletions.Clear();
} }
@@ -228,7 +228,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 || region.Deleted) if (region == null)
{ {
return new HashSet<PathfindingRegion>(); return new HashSet<PathfindingRegion>();
} }
@@ -357,7 +357,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) || neighbor.Deleted) if (closedSet.Contains(neighbor))
{ {
continue; continue;
} }
@@ -504,7 +504,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
{ {
bottomRegion.Add(node); bottomRegion.Add(node);
existingRegions.Add(node, bottomRegion); existingRegions.Add(node, bottomRegion);
MergeInto(leftRegion, bottomRegion); MergeInto(leftRegion, bottomRegion, existingRegions);
// Cleanup leftRegion // Cleanup leftRegion
// MergeInto will remove it from the overall region chunk cache while we need to remove it from // MergeInto will remove it from the overall region chunk cache while we need to remove it from
@@ -541,7 +541,6 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
_regions[parentChunk.GridId][parentChunk].Add(newRegion); _regions[parentChunk.GridId][parentChunk].Add(newRegion);
existingRegions.Add(node, newRegion); existingRegions.Add(node, newRegion);
UpdateRegionEdge(newRegion, node); UpdateRegionEdge(newRegion, node);
return newRegion; return newRegion;
} }
@@ -550,7 +549,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
/// </summary> /// </summary>
/// <param name="source"></param> /// <param name="source"></param>
/// <param name="target"></param> /// <param name="target"></param>
private void MergeInto(PathfindingRegion source, PathfindingRegion target) private void MergeInto(PathfindingRegion source, PathfindingRegion target, Dictionary<PathfindingNode, PathfindingRegion> existingRegions = null)
{ {
DebugTools.AssertNotNull(source); DebugTools.AssertNotNull(source);
DebugTools.AssertNotNull(target); DebugTools.AssertNotNull(target);
@@ -560,6 +559,14 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
target.Add(node); target.Add(node);
} }
if (existingRegions != null)
{
foreach (var node in source.Nodes)
{
existingRegions[node] = target;
}
}
source.Shutdown(); source.Shutdown();
// This doesn't check the cachedaccessible to see if it's reachable but maybe it should? // 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 // Although currently merge gets spammed so maybe when some other stuff is improved
@@ -578,6 +585,8 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
/// <param name="region"></param> /// <param name="region"></param>
private void ClearCache(PathfindingRegion region) private void ClearCache(PathfindingRegion region)
{ {
DebugTools.Assert(region.Deleted);
// Need to forcibly clear cache for ourself and anything that includes us // Need to forcibly clear cache for ourself and anything that includes us
foreach (var (_, cachedRegions) in _cachedAccessible) foreach (var (_, cachedRegions) in _cachedAccessible)
{ {
@@ -604,6 +613,14 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
cachedRegions.Remove(otherRegion); cachedRegions.Remove(otherRegion);
} }
} }
#if DEBUG
if (_regions.TryGetValue(region.ParentChunk.GridId, out var chunks) &&
chunks.TryGetValue(region.ParentChunk, out var regions))
{
DebugTools.Assert(!regions.Contains(region));
}
#endif
} }
/// <summary> /// <summary>
@@ -647,14 +664,19 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
{ {
continue; continue;
} }
chunkRegions.Add(region); chunkRegions.Add(region);
} }
} }
#if DEBUG #if DEBUG
foreach (var region in chunkRegions)
{
DebugTools.Assert(!region.Deleted);
}
DebugTools.Assert(chunkRegions.Count < Math.Pow(PathfindingChunk.ChunkSize, 2));
SendRegionsDebugMessage(chunk.GridId); SendRegionsDebugMessage(chunk.GridId);
#endif #endif
DebugTools.Assert(chunkRegions.Count(region => region.Deleted) == 0);
} }
#if DEBUG #if DEBUG

View File

@@ -34,7 +34,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
public bool IsDoor { get; } public bool IsDoor { get; }
public HashSet<PathfindingNode> Nodes => _nodes; public HashSet<PathfindingNode> Nodes => _nodes;
private HashSet<PathfindingNode> _nodes; private readonly HashSet<PathfindingNode> _nodes;
public bool Deleted { get; private set; } public bool Deleted { get; private set; }
@@ -55,6 +55,9 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
var neighbor = neighbors[i]; var neighbor = neighbors[i];
neighbor.Neighbors.Remove(this); neighbor.Neighbors.Remove(this);
} }
_nodes.Clear();
Neighbors.Clear();
Deleted = true; Deleted = true;
} }
@@ -127,7 +130,10 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
{ {
if (other == null) return false; if (other == null) return false;
if (ReferenceEquals(this, other)) return true; if (ReferenceEquals(this, other)) return true;
return GetHashCode() == other.GetHashCode(); if (_nodes.Count != other.Nodes.Count) return false;
if (Deleted != other.Deleted) return false;
if (OriginNode != other.OriginNode) return false;
return true;
} }
public override int GetHashCode() public override int GetHashCode()