package net.therosegarden.firefighter; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Locale; import java.util.Random; import java.util.UUID; import java.util.function.Predicate; import me.ryanhamshire.GriefPrevention.Claim; import me.ryanhamshire.GriefPrevention.GriefPrevention; import org.bukkit.Bukkit; import org.bukkit.HeightMap; import org.bukkit.Location; import org.bukkit.OfflinePlayer; import org.bukkit.World; final class GriefPreventionLocationProvider implements EmergencyLocationProvider { @Override public EmergencySite randomClaimSite(Random random, Predicate worldAllowed, int maxRadius, int minClaimArea) { List eligible = new ArrayList<>(); for (Claim claim : GriefPrevention.instance.dataStore.getClaims()) { if (claim == null || claim.parent != null || claim.getOwnerID() == null || claim.getArea() < minClaimArea) { continue; } Location lesser = claim.getLesserBoundaryCorner(); Location greater = claim.getGreaterBoundaryCorner(); World world = lesser == null ? null : lesser.getWorld(); if (world == null || greater == null || greater.getWorld() == null || !worldAllowed.test(world)) { continue; } eligible.add(claim); } if (eligible.isEmpty()) { return null; } Claim claim = eligible.get(random.nextInt(eligible.size())); Location lesser = claim.getLesserBoundaryCorner(); Location greater = claim.getGreaterBoundaryCorner(); World world = lesser.getWorld(); if (world == null) { return null; } int minX = Math.min(lesser.getBlockX(), greater.getBlockX()); int maxX = Math.max(lesser.getBlockX(), greater.getBlockX()); int minZ = Math.min(lesser.getBlockZ(), greater.getBlockZ()); int maxZ = Math.max(lesser.getBlockZ(), greater.getBlockZ()); int centerX = minX + ((maxX - minX) / 2); int centerZ = minZ + ((maxZ - minZ) / 2); int y = world.getHighestBlockAt(centerX, centerZ, HeightMap.MOTION_BLOCKING).getY() + 1; int halfWidth = Math.max(2, (maxX - minX) / 2); int halfDepth = Math.max(2, (maxZ - minZ) / 2); int radius = Math.max(2, Math.min(Math.max(2, maxRadius), Math.min(halfWidth, halfDepth))); String owner = ownerName(claim); return new EmergencySite(owner + "'s home", world.getName(), centerX, y, centerZ, radius); } @Override public String nearbyClaims(Location location, int radius, int maxResults) { if (location == null || location.getWorld() == null) { return "none"; } List nearby = new ArrayList<>(); for (Claim claim : GriefPrevention.instance.dataStore.getClaims()) { if (claim == null || claim.parent != null) { continue; } Location lesser = claim.getLesserBoundaryCorner(); Location greater = claim.getGreaterBoundaryCorner(); if (lesser == null || greater == null || lesser.getWorld() == null || !lesser.getWorld().equals(location.getWorld())) { continue; } double distance = distanceToClaim(location, lesser, greater); if (distance <= radius) { nearby.add(new NearbyClaim(ownerName(claim), distance)); } } nearby.sort(Comparator.comparingDouble(NearbyClaim::distance)); if (nearby.isEmpty()) { return "none within " + radius + " blocks"; } int limit = Math.max(1, maxResults); List descriptions = new ArrayList<>(); for (int i = 0; i < nearby.size() && i < limit; i++) { NearbyClaim entry = nearby.get(i); String distance = entry.distance() < 1.0 ? "inside" : Math.round(entry.distance()) + "m"; descriptions.add(entry.owner() + " (" + distance + ")"); } if (nearby.size() > limit) { descriptions.add("+" + (nearby.size() - limit) + " more"); } return String.join(", ", descriptions); } private String ownerName(Claim claim) { UUID ownerId = claim.getOwnerID(); if (ownerId == null) { return "Admin claim"; } OfflinePlayer offline = Bukkit.getOfflinePlayer(ownerId); String name = offline.getName(); if (name == null || name.isBlank()) { name = claim.getOwnerName(); } if (name == null || name.isBlank()) { name = ownerId.toString().substring(0, 8).toLowerCase(Locale.ROOT); } return name; } private double distanceToClaim(Location location, Location lesser, Location greater) { int minX = Math.min(lesser.getBlockX(), greater.getBlockX()); int maxX = Math.max(lesser.getBlockX(), greater.getBlockX()); int minZ = Math.min(lesser.getBlockZ(), greater.getBlockZ()); int maxZ = Math.max(lesser.getBlockZ(), greater.getBlockZ()); double x = location.getX(); double z = location.getZ(); double dx = x < minX ? minX - x : (x > maxX ? x - maxX : 0.0); double dz = z < minZ ? minZ - z : (z > maxZ ? z - maxZ : 0.0); return Math.sqrt((dx * dx) + (dz * dz)); } private record NearbyClaim(String owner, double distance) {} }