136 lines
5.4 KiB
Java
136 lines
5.4 KiB
Java
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<World> worldAllowed, int maxRadius, int minClaimArea) {
|
|
List<Claim> 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<NearbyClaim> 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<String> 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) {}
|
|
}
|