diff --git a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/Accessible/BFSPathfinder.cs b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/Accessible/BFSPathfinder.cs
new file mode 100644
index 0000000000..ddb5628a02
--- /dev/null
+++ b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/Accessible/BFSPathfinder.cs
@@ -0,0 +1,70 @@
+using System.Collections.Generic;
+using Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Pathfinders;
+using Content.Server.GameObjects.EntitySystems.Pathfinding;
+using Robust.Shared.GameObjects.Systems;
+using Robust.Shared.Map;
+
+namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible
+{
+ ///
+ /// The simplest pathfinder
+ ///
+ public sealed class BFSPathfinder
+ {
+ ///
+ /// Gets all of the tiles in range that can we access
+ ///
+ /// If you want Dikstra then add distances.
+ /// Doesn't use the JobQueue as it will generally be encapsulated by other jobs
+ ///
+ ///
+ /// Whether we traverse from the starting tile or the end tile
+ ///
+ public static IEnumerable GetNodesInRange(PathfindingArgs pathfindingArgs, bool fromStart = true)
+ {
+ var pathfindingSystem = EntitySystem.Get();
+ // Don't need a priority queue given not looking for shortest path
+ var openTiles = new Queue();
+ var closedTiles = new HashSet();
+ PathfindingNode startNode;
+
+ if (fromStart)
+ {
+ startNode = pathfindingSystem.GetNode(pathfindingArgs.Start);
+ }
+ else
+ {
+ startNode = pathfindingSystem.GetNode(pathfindingArgs.End);
+ }
+
+ PathfindingNode currentNode;
+ openTiles.Enqueue(startNode);
+
+ while (openTiles.Count > 0)
+ {
+ currentNode = openTiles.Dequeue();
+
+ foreach (var neighbor in currentNode.GetNeighbors())
+ {
+ // No distances stored so can just check closed tiles here
+ if (closedTiles.Contains(neighbor.TileRef)) continue;
+ closedTiles.Add(currentNode.TileRef);
+
+ // So currently tileCost gets the octile distance between the 2 so we'll also use that for our range check
+ var tileCost = PathfindingHelpers.GetTileCost(pathfindingArgs, startNode, neighbor);
+ var direction = PathfindingHelpers.RelativeDirection(neighbor, currentNode);
+
+ if (tileCost == null ||
+ tileCost > pathfindingArgs.Proximity ||
+ !PathfindingHelpers.DirectionTraversable(pathfindingArgs.CollisionMask, pathfindingArgs.Access, currentNode, direction))
+ {
+ continue;
+ }
+
+ openTiles.Enqueue(neighbor);
+ yield return neighbor;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingHelpers.cs b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingHelpers.cs
index e4c04d5a94..4c5e25390a 100644
--- a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingHelpers.cs
+++ b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingHelpers.cs
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
+using Content.Server.GameObjects.Components.Access;
+using Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible;
using Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Pathfinders;
using Content.Server.GameObjects.EntitySystems.Pathfinding;
using Robust.Shared.Interfaces.GameObjects;
@@ -18,15 +20,10 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding
{
if (pathfindingArgs.Proximity > 0.0f)
{
- // TODO: Should make this account for proximities,
- // probably some kind of breadth-first search to find a valid one
- foreach (var node in endNode.GetNeighbors())
+ foreach (var node in BFSPathfinder.GetNodesInRange(pathfindingArgs, false))
{
- if (Traversable(pathfindingArgs.CollisionMask, pathfindingArgs.Access, node))
- {
- endNode = node;
- return true;
- }
+ endNode = node;
+ return true;
}
}