/// <summary>
    /// This implementation turns the given placeable in a square around it's starting position until a valid position is found.
    /// </summary>
    /// <param name="placementController"></param>
    /// <param name="terrainGenerator"></param>
    /// <param name="placeable"></param>
    /// <returns></returns>
    public static ThreadsafePlaceable MoveToPlaceablePosition(IPlacementController placementController,
                                                              ITerrainGenerator terrainGenerator, ThreadsafePlaceable placeable)
    {
        while (!terrainGenerator.IsReady(placeable.Position))
        {
            Thread.Sleep(50);
        }

        int stepSize     = 2;
        int targetXMove  = 0;
        int targetYMove  = 0;
        int currentXMove = 0;
        int currentYMove = 0;
        int direction    = -1;

        // Moves the cityPlaceable in a growing square around the starting position until a suitable location is found
        while (!placementController.IsPlaceable(placeable.Position, placeable.NeededSpaces))
        {
            // Move one step at a time
            if (currentXMove > 0)
            {
                placeable.Translate(direction * stepSize, 0, 0);
                currentXMove--;
                continue;
            }

            if (currentYMove > 0)
            {
                placeable.Translate(0, 0, direction * stepSize);
                currentYMove--;
                continue;
            }

            // Control step Amount
            if (targetXMove == targetYMove)
            {
                direction = -direction;
                targetXMove++;
                currentXMove = targetXMove;
            }
            else
            {
                targetYMove  = targetXMove;
                currentYMove = targetYMove;
            }
        }

        return(placeable);
    }
    public static ThreadsafePlaceable FindForrestPosition(IPlacementController placementController,
                                                          ITerrainGenerator terrainGenerator, ThreadsafePlaceable placeable, float[,] values)
    {
        while (!terrainGenerator.IsReady(placeable.Position))
        {
            Thread.Sleep(50);
        }

        List <NeededSpace> coastNeededSpace = new List <NeededSpace>
        {
            new NeededSpace(Vector3Int.zero, TerrainGenerator.TerrainType.Coast)
        };
        List <NeededSpace> flatLandNeededSpace = new List <NeededSpace>
        {
            new NeededSpace(Vector3Int.zero, TerrainGenerator.TerrainType.Flatland)
        };
        List <NeededSpace> hillNeededSpace = new List <NeededSpace>
        {
            new NeededSpace(Vector3Int.zero, TerrainGenerator.TerrainType.Hill)
        };
        List <NeededSpace> mountainNeededSpace = new List <NeededSpace>
        {
            new NeededSpace(Vector3Int.zero, TerrainGenerator.TerrainType.Mountain)
        };
        float limit = 0.1f;

        for (int x = 0; x < values.GetLength(0) - 3; x++)
        {
            for (int y = 0; y < values.GetLength(1) - 3; y++)
            {
                Vector3Int relativePosition =
                    new Vector3Int(x - values.GetLength(0) / 2 + 1, 0, y - values.GetLength(1) / 2 + 1);
                Vector3 absolutePosition = relativePosition + placeable.Position;
                bool    isThreshold      = (values[x, y] > limit - 0.05f && values[x, y] < limit + 0.05f);
                if (!isThreshold)
                {
                    continue;
                }

                TerrainGenerator.TerrainType terrainType = terrainGenerator.GetTerrainType(absolutePosition.x, absolutePosition.z);
                bool isPlaceable = false;
                switch (terrainType)
                {
                case TerrainGenerator.TerrainType.Flatland:
                    isPlaceable = placementController.IsPlaceable(absolutePosition, flatLandNeededSpace);
                    break;

                case TerrainGenerator.TerrainType.Coast:
                    isPlaceable = placementController.IsPlaceable(absolutePosition, coastNeededSpace);
                    break;

                case TerrainGenerator.TerrainType.Hill:
                    isPlaceable = placementController.IsPlaceable(absolutePosition, hillNeededSpace);
                    break;

                case TerrainGenerator.TerrainType.Mountain:
                    isPlaceable = placementController.IsPlaceable(absolutePosition, mountainNeededSpace);
                    break;
                }
                if (!isPlaceable)
                {
                    continue;
                }
                placeable.NeededSpaces.Add(new ProceduralNeededSpace(relativePosition, terrainType, values[x, y]));
            }
        }

        return(placeable);
    }