Newer
Older
ChallengeSystem / ChallengeUtils / src / main / java / de / fanta / challengeutils / LocationUtils.java
@fanta fanta on 28 Jun 2024 4 KB Start Chaos Challenge
package de.fanta.challengeutils;

import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.util.BoundingBox;

import java.util.List;
import java.util.Random;

public class LocationUtils {

    private static final int MAX_ATTEMPTS = 10; // Maximale Versuche, um eine sichere Location zu finden

    public static Location getRandomLocationAroundPlayer(Player player, double radius) {
        return getRandomLocationAroundLocation(player.getLocation(), radius, false);
    }

    public static Location getRandomLocationAroundPlayer(Player player, double radius, boolean findSafeLocation) {
        return getRandomLocationAroundLocation(player.getLocation(), radius, findSafeLocation);
    }

    public static Location getRandomLocationAroundLocation(Location location, double radius) {
        return getRandomLocationAroundLocation(location, radius, false);
    }

    public static Location getRandomLocationAroundLocation(Location location, double radius, boolean findSafeLocation) {
        Random random = new Random();
        World world = location.getWorld();
        int maxHeight = world.getMaxHeight();
        int minHeight = world.getMinHeight() + 5; //+5 Weil Bedrock

        if (world.getEnvironment() == World.Environment.NETHER) {
            maxHeight = 122;  //Max Logical height in Nether
        }

        if (findSafeLocation) {
            for (int attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
                double angle = random.nextDouble() * 2 * Math.PI;
                double distance = random.nextDouble() * radius;
                double xOffset = Math.cos(angle) * distance;
                double zOffset = Math.sin(angle) * distance;

                double newX = location.getX() + xOffset;
                double newZ = location.getZ() + zOffset;
                double newY = random.nextDouble() * (maxHeight - minHeight) + minHeight;

                Location newLocation = new Location(world, newX, newY, newZ);

                if (isSafeLocation(newLocation)) {
                    return newLocation;
                }
            }
        }

        double finalAngle = random.nextDouble() * 2 * Math.PI;
        double finalDistance = random.nextDouble() * radius;
        double finalXOffset = Math.cos(finalAngle) * finalDistance;
        double finalZOffset = Math.sin(finalAngle) * finalDistance;

        double finalX = location.getX() + finalXOffset;
        double finalZ = location.getZ() + finalZOffset;
        double finalY = random.nextDouble() * (maxHeight - minHeight) + minHeight;

        return new Location(location.getWorld(), finalX, finalY, finalZ);
    }

    private static boolean isSafeLocation(Location location) {
        World world = location.getWorld();
        int x = location.getBlockX();
        int y = location.getBlockY();
        int z = location.getBlockZ();

        if (world.getBlockAt(x, y - 1, z).getType().isSolid()) {
            return world.getBlockAt(x, y, z).getType() == Material.AIR && world.getBlockAt(x, y + 1, z).getType() == Material.AIR;
        }
        return false;
    }

    public static BoundingBox calculateEnclosingBoundingBox(List<BoundingBox> boxes) {
        if (boxes == null || boxes.isEmpty()) {
            throw new IllegalArgumentException("Error while the bounding box list is null or Empty");
        }

        double minX = boxes.getFirst().getMinX();
        double minY = boxes.getFirst().getMinY();
        double minZ = boxes.getFirst().getMinZ();
        double maxX = boxes.getFirst().getMaxX();
        double maxY = boxes.getFirst().getMaxY();
        double maxZ = boxes.getFirst().getMaxZ();

        for (BoundingBox box : boxes) {
            if (box.getMinX() < minX) {
                minX = box.getMinX();
            }
            if (box.getMinY() < minY) {
                minY = box.getMinY();
            }
            if (box.getMinZ() < minZ) {
                minZ = box.getMinZ();
            }
            if (box.getMaxX() > maxX) {
                maxX = box.getMaxX();
            }
            if (box.getMaxY() > maxY) {
                maxY = box.getMaxY();
            }
            if (box.getMaxZ() > maxZ) {
                maxZ = box.getMaxZ();
            }
        }

        return new BoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
    }
}