package com.github.jamesnorris.ablockalypse.utility; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; public class Region { private Location loc1, loc2, loc3, loc4, loc5, loc6, loc7, loc8, center; private double lowX, highX, lowZ, highZ, lowY, highY, midX, midY, midZ; private World world; /** * Creates a new 3D region from 2 corner points. * @param start The first corner selected * @param end The second corner selected */ public Region(Location start, Location end) { world = start.getWorld(); double startX = start.getX(); double startY = start.getY(); double startZ = start.getZ(); double endX = end.getX(); double endY = end.getY(); double endZ = end.getZ(); highX = startX > endX ? startX : endX; lowX = startX <= endX ? startX : endX; highY = startY > endY ? startY : endY; lowY = startY <= endY ? startY : endY; highZ = startZ > endZ ? startZ : endZ; lowZ = startZ <= endZ ? startZ : endZ; midX = lowX + (highX - lowX) / 2; midY = lowY + (highY - lowY) / 2; midZ = lowZ + (highZ - lowZ) / 2; center = new Location(world, midX, midY, midZ); loc1 = new Location(world, lowX, highY, highZ); loc2 = new Location(world, highX, highY, highZ); loc3 = new Location(world, highX, highY, lowZ); loc4 = new Location(world, lowX, highY, lowZ); loc5 = new Location(world, lowX, lowY, highZ); loc6 = new Location(world, highX, lowY, highZ); loc7 = new Location(world, highX, lowY, lowZ); loc8 = new Location(world, lowX, lowY, lowZ); } /** * Checks if the location is contained inside the region. * @param loc The location to check for * @return Whether or not the location is contained in the region */ public boolean contains(Location loc) { boolean Xs = overlap_1D(lowX, highX, loc.getBlockX(), loc.getBlockX()); boolean Ys = overlap_1D(lowY, highY, loc.getBlockY(), loc.getBlockY()); boolean Zs = overlap_1D(lowZ, highZ, loc.getBlockZ(), loc.getBlockZ()); return Xs && Ys && Zs; } /** * Checks if the player is contained inside the region. * @param p The player to check for * @return Whether or not the player is contained in the region */ public boolean contains(Player p) { return contains(p.getLocation()); } /** * Gets the location at the very center of this region. * This may be slightly inaccurate as an estimate, since the location * is found using doubles, and block locations can only be integers. * Therefore, the getBlock() method for this center location may get * a block next to the middle, if the middle is between two or more blocks. * @return The location at (or close) to the center of the region */ public Location getCenter() { return center; } /** * Gets the corner that matches the given number. * Corners are matched up to numbers in this order: <br> * 1. Low X, High Y, High Z <br> * 2. High X, High Y, High Z <br> * 3. High X, High Y, Low Z <br> * 4. Low X, High Y, Low Z <br> * 5. Low X, Low Y, High Z <br> * 6. High X, Low Y, High Z <br> * 7. High X, Low Y, Low Z <br> * 8. Low X, Low Y, Low Z * @param corner The corner number from 1-8 * @return The corner corresponding to the number */ public Location getCorner(int corner) { Location[] locs = new Location[] {loc1, loc2, loc3, loc4, loc5, loc6, loc7, loc8}; return locs[corner]; } /** * Gets the highest X of all 8 locations in this region. * @return The highest X value for this region */ public double getHighestX() { return highX; } /** * Gets the highest Y of all 8 locations in this region. * @return The highest Y value for this region */ public double getHighestY() { return highY; } /** * Gets the highest Z of all 8 locations in this region. * @return The highest Z value for this region */ public double getHighestZ() { return highZ; } /** * Gets the lowest X of all 8 locations in this region. * @return The lowest X value for this region */ public double getLowestX() { return lowX; } /** * Gets the lowest Y of all 8 locations in this region. * @return The lowest Y value for this region */ public double getLowestY() { return lowY; } /** * Gets the lowest Z of all 8 locations in this region. * @return The lowest Z value for this region */ public double getLowestZ() { return lowZ; } /** * Checks if the given region touches or overlaps this region. * @param other The region to check for * @return Whether or not they touch or overlap */ public boolean overlaps(Region other) { boolean Xs = overlap_1D(lowX, highX, other.getLowestX(), other.getHighestX()); boolean Ys = overlap_1D(lowY, highY, other.getLowestY(), other.getHighestY()); boolean Zs = overlap_1D(lowZ, highZ, other.getLowestZ(), other.getHighestZ()); return Xs && Ys && Zs; } /* Checks a 1D rectangle for overlap. */ private boolean overlap_1D(double low1, double high1, double low2, double high2) { return low1 <= low2 ? low2 <= high1 : low1 <= high2; } }