public static bool IsMatureTreeStumpOrBoulderAt(GameLocation gameLocation, Point tile)
        {
            gameLocation.terrainFeatures.TryGetValue(new Vector2(tile.X, tile.Y), out TerrainFeature terrainFeature);

            if (terrainFeature is Tree || terrainFeature is FruitTree ||
                (terrainFeature is Bush bush &&
                 ClickToMoveHelper.IsBushDestroyable(bush, gameLocation, tile)))
            {
                return(true);
            }

            foreach (LargeTerrainFeature largeTerrainFeature in gameLocation.largeTerrainFeatures)
            {
                if (largeTerrainFeature is Bush bush2 &&
                    bush2.getRenderBounds(new Vector2(bush2.tilePosition.X, bush2.tilePosition.Y)).Contains(
                        tile.X * Game1.tileSize,
                        tile.Y * Game1.tileSize) && ClickToMoveHelper.IsBushDestroyable(bush2, gameLocation, tile))
                {
                    return(true);
                }
            }

            return(ClickToMoveHelper.IsStumpAt(gameLocation, tile.X, tile.Y) ||
                   ClickToMoveHelper.IsBoulderAt(gameLocation, tile.X, tile.Y));
        }
        public static bool WarpIfInRange(GameLocation gameLocation, Warp warp)
        {
            Vector2 warpVector = new Vector2(warp.X * Game1.tileSize, warp.Y * Game1.tileSize);

            if (Vector2.Distance(warpVector, Game1.player.position.Value) < ClickToMoveHelper.WarpRange(gameLocation))
            {
                Game1.player.warpFarmer(warp);
                return(true);
            }

            return(false);
        }
        public static bool IsBoulderAt(GameLocation gameLocation, int x, int y)
        {
            if (!(gameLocation is Forest || gameLocation is Woods) && gameLocation.resourceClumps.Any(
                    resourceClump => ClickToMoveHelper.IsResourceClumpBoulderAt(resourceClump, x, y)))
            {
                return(true);
            }

            gameLocation.objects.TryGetValue(new Vector2(x, y), out SObject @object);

            return(@object is not null && (@object.Name == "Stone" || @object.Name == "Boulder"));
        }
        public static bool ClickedEggAtEggFestival(Point clickPoint)
        {
            if (Game1.CurrentEvent is not null && Game1.CurrentEvent.FestivalName == "Egg Festival")
            {
                foreach (Prop prop in Game1.CurrentEvent.festivalProps)
                {
                    if (ClickToMoveHelper.PropContainsPoint(prop, clickPoint))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
        public static bool WarpIfInRange(GameLocation gameLocation, Vector2 clickPoint)
        {
            float warpRange = ClickToMoveHelper.WarpRange(gameLocation);

            foreach (Warp warp in gameLocation.warps)
            {
                Vector2 warpVector = new Vector2(warp.X * Game1.tileSize, warp.Y * Game1.tileSize);

                if (Vector2.Distance(warpVector, clickPoint) < warpRange &&
                    Vector2.Distance(warpVector, Game1.player.position.Value) < warpRange)
                {
                    Game1.player.warpFarmer(warp);

                    return(true);
                }
            }

            return(false);
        }
        public static Point GetNearestTileNextToBuilding(AStarGraph graph, Building building)
        {
            int buildingTileX       = building.tileX.Value;
            int buildingTileY       = building.tileY.Value;
            int buildingTilesWidth  = building.tilesWide.Value;
            int buildingTilesHeight = building.tilesHigh.Value;

            int tileX;
            int tileY;

            if (Game1.player.getTileX() < buildingTileX)
            {
                tileX = buildingTileX;
            }
            else if (Game1.player.getTileX() > buildingTileX + buildingTilesWidth - 1)
            {
                tileX = buildingTileX + buildingTilesWidth - 1;
            }
            else
            {
                tileX = Game1.player.getTileX();
            }

            if (Game1.player.getTileY() < buildingTileY)
            {
                tileY = buildingTileY;
            }
            else if (Game1.player.getTileY() > buildingTileY + buildingTilesHeight)
            {
                tileY = buildingTileY + buildingTilesHeight - 1;
            }
            else
            {
                tileY = Game1.player.getTileY();
            }

            Point tile = ClickToMoveHelper.GetTileNextToBuilding(tileX, tileY, graph);

            if (tile != Point.Zero)
            {
                return(tile);
            }

            // There is no direct path to the nearest tile, let's search for an alternative around it.

            List <Point> tilesAroundBuilding = ClickToMoveHelper.ListOfTilesSurroundingBuilding(building);

            int tileIndex = 0;

            for (int i = 0; i < tilesAroundBuilding.Count; i++)
            {
                if (tilesAroundBuilding[i].X == tileX && tilesAroundBuilding[i].Y == tileY)
                {
                    tileIndex = i;
                    break;
                }
            }

            for (int i = 1, previousIndex = tileIndex - 1, nextIndex = tileIndex + 1;
                 i < tilesAroundBuilding.Count / 2;
                 i++, previousIndex--, nextIndex++)
            {
                if (previousIndex < 0)
                {
                    previousIndex += tilesAroundBuilding.Count;
                }

                tile = ClickToMoveHelper.GetTileNextToBuilding(
                    tilesAroundBuilding[previousIndex].X,
                    tilesAroundBuilding[previousIndex].Y,
                    graph);

                if (tile != Point.Zero)
                {
                    return(tile);
                }

                if (nextIndex > tilesAroundBuilding.Count - 1)
                {
                    nextIndex -= tilesAroundBuilding.Count;
                }

                tile = ClickToMoveHelper.GetTileNextToBuilding(
                    tilesAroundBuilding[nextIndex].X,
                    tilesAroundBuilding[nextIndex].Y,
                    graph);

                if (tile != Point.Zero)
                {
                    return(tile);
                }
            }

            return(new Point(Game1.player.getTileX(), Game1.player.getTileY()));
        }