public static Stack <Point> findPath(Point startPoint, Point endPoint, isAtEnd endPointFunction, GameLocation location, int limit = -1) { if (Interlocked.Increment(ref _counter) != 1) { throw new Exception(); } try { bool endPointIsFarmer = endPoint.X == Game1.player.getTileX() && endPoint.Y == Game1.player.getTileY(); _openList.Clear(); _closedList.Clear(); var openList = _openList; HashSet <int> closedList = _closedList; int iterations = 0; openList.Enqueue(new PathNode(startPoint.X, startPoint.Y, 0, null), Math.Abs(endPoint.X - startPoint.X) + Math.Abs(endPoint.Y - startPoint.Y)); int layerWidth = location.map.Layers[0].LayerWidth; int layerHeight = location.map.Layers[0].LayerHeight; Character character = Game1.player; List <int> searchDirections = SearchDirections(startPoint, endPoint); while (!openList.IsEmpty()) { PathNode currentNode = openList.Dequeue(); if (endPointFunction(currentNode, endPoint, location, character)) { return(reconstructPath(currentNode)); } closedList.Add(currentNode.id); int ng = (byte)(currentNode.g + 1); foreach (int i in searchDirections) { int nx = currentNode.x + Directions[i, 0]; int ny = currentNode.y + Directions[i, 1]; int nid = PathNode.ComputeHash(nx, ny); if (!closedList.Contains(nid)) { bool isWalkable = isTileWalkable(location, nx, ny); bool isEndPoint = nx == endPoint.X && ny == endPoint.Y; bool isOffMap = nx < 0 || ny < 0 || nx >= layerWidth || ny >= layerHeight; if ((!isEndPoint && isOffMap) || !isWalkable) { closedList.Add(nid); } else { PathNode neighbor = new(nx, ny, currentNode); neighbor.g = (byte)(currentNode.g + 1); float f = ng + (Math.Abs(endPoint.X - nx) + Math.Abs(endPoint.Y - ny)); closedList.Add(nid); openList.Enqueue(neighbor, f); } } } iterations++; if (limit >= 0) { if (iterations >= limit) { return(null); } } } return(null); } finally { if (Interlocked.Decrement(ref _counter) != 0) { throw new Exception(); } } }