diff --git a/src/main/java/com/sk89q/worldguard/protection/regions/GlobalProtectedRegion.java b/src/main/java/com/sk89q/worldguard/protection/regions/GlobalProtectedRegion.java index 32fe8944..06b10546 100644 --- a/src/main/java/com/sk89q/worldguard/protection/regions/GlobalProtectedRegion.java +++ b/src/main/java/com/sk89q/worldguard/protection/regions/GlobalProtectedRegion.java @@ -23,8 +23,10 @@ import com.sk89q.worldedit.BlockVector2D; import com.sk89q.worldedit.Vector; +import java.awt.geom.Area; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; /** @@ -47,6 +49,11 @@ public GlobalProtectedRegion(String id) { max = new BlockVector(0, 0, 0); } + @Override + public boolean isPhysicalArea() { + return false; + } + @Override public List getPoints() { // This doesn't make sense @@ -74,7 +81,12 @@ public RegionType getType() { @Override public List getIntersectingRegions(Collection regions) { // Global regions are handled separately so it must not contain any positions - return new ArrayList(); + return Collections.emptyList(); + } + + @Override + Area toArea() { + return null; } } diff --git a/src/main/java/com/sk89q/worldguard/protection/regions/ProtectedCuboidRegion.java b/src/main/java/com/sk89q/worldguard/protection/regions/ProtectedCuboidRegion.java index 0d5c56c9..79848226 100644 --- a/src/main/java/com/sk89q/worldguard/protection/regions/ProtectedCuboidRegion.java +++ b/src/main/java/com/sk89q/worldguard/protection/regions/ProtectedCuboidRegion.java @@ -24,8 +24,9 @@ import com.sk89q.worldedit.Vector; import com.sk89q.worldguard.util.MathUtils; +import java.awt.*; +import java.awt.geom.Area; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import static com.google.common.base.Preconditions.checkNotNull; @@ -83,6 +84,11 @@ public void setMaximumPoint(BlockVector position) { setMinMaxPoints(min, position); } + @Override + public boolean isPhysicalArea() { + return true; + } + @Override public List getPoints() { List pts = new ArrayList(); @@ -115,30 +121,21 @@ public RegionType getType() { } @Override - public List getIntersectingRegions(Collection regions) { - checkNotNull(regions); + Area toArea() { + int x = getMinimumPoint().getBlockX(); + int z = getMinimumPoint().getBlockZ(); + int width = getMaximumPoint().getBlockX() - x; + int height = getMaximumPoint().getBlockZ() - z; + return new Area(new Rectangle(x, z, width, height)); + } - List intersectingRegions = new ArrayList(); - - for (ProtectedRegion region : regions) { - if (!intersectsBoundingBox(region)) continue; - - // If both regions are Cuboids and their bounding boxes intersect, they intersect - if (region instanceof ProtectedCuboidRegion) { - intersectingRegions.add(region); - } else if (region instanceof ProtectedPolygonalRegion) { - // If either region contains the points of the other, - // or if any edges intersect, the regions intersect - if (containsAny(region.getPoints()) || region.containsAny(getPoints()) || intersectsEdges(region)) { - intersectingRegions.add(region); - } - } else if (region instanceof GlobalProtectedRegion) { - // Never intersects - } else { - throw new IllegalArgumentException("Not supported yet."); - } + @Override + protected boolean intersects(ProtectedRegion region, Area thisArea) { + if (region instanceof ProtectedCuboidRegion) { + return intersectsBoundingBox(region); + } else { + return super.intersects(region, thisArea); } - return intersectingRegions; } @Override diff --git a/src/main/java/com/sk89q/worldguard/protection/regions/ProtectedPolygonalRegion.java b/src/main/java/com/sk89q/worldguard/protection/regions/ProtectedPolygonalRegion.java index 0f9c8cbc..932ee3cf 100644 --- a/src/main/java/com/sk89q/worldguard/protection/regions/ProtectedPolygonalRegion.java +++ b/src/main/java/com/sk89q/worldguard/protection/regions/ProtectedPolygonalRegion.java @@ -22,8 +22,10 @@ import com.sk89q.worldedit.BlockVector2D; import com.sk89q.worldedit.Vector; +import java.awt.*; +import java.awt.geom.Area; import java.util.ArrayList; -import java.util.Collection; +import java.util.Collections; import java.util.List; import static com.google.common.base.Preconditions.checkNotNull; @@ -37,7 +39,7 @@ public class ProtectedPolygonalRegion extends ProtectedRegion { public ProtectedPolygonalRegion(String id, List points, int minY, int maxY) { super(id); setMinMaxPoints(points, minY, maxY); - this.points = points; + this.points = Collections.unmodifiableList(points); this.minY = min.getBlockY(); this.maxY = max.getBlockY(); } @@ -61,6 +63,11 @@ private void setMinMaxPoints(List points2D, int minY, int maxY) { setMinMaxPoints(points); } + @Override + public boolean isPhysicalArea() { + return true; + } + @Override public List getPoints() { return points; @@ -133,27 +140,21 @@ public RegionType getType() { } @Override - public List getIntersectingRegions(Collection regions) { - checkNotNull(regions); + Area toArea() { + List points = getPoints(); + int numPoints = points.size(); + int[] xCoords = new int[numPoints]; + int[] yCoords = new int[numPoints]; - List intersectingRegions = new ArrayList(); - - for (ProtectedRegion region : regions) { - if (!intersectsBoundingBox(region)) continue; - - if (region instanceof ProtectedPolygonalRegion || region instanceof ProtectedCuboidRegion) { - // If either region contains the points of the other, - // or if any edges intersect, the regions intersect - if (containsAny(region.getPoints()) || region.containsAny(getPoints()) || intersectsEdges(region)) { - intersectingRegions.add(region); - } - } else if (region instanceof GlobalProtectedRegion) { - // Never intersects - } else { - throw new IllegalArgumentException("Not supported yet."); - } + int i = 0; + for (BlockVector2D point : points) { + xCoords[i] = point.getBlockX(); + yCoords[i] = point.getBlockZ(); + i++; } - return intersectingRegions; + + Polygon polygon = new Polygon(xCoords, yCoords, numPoints); + return new Area(polygon); } @Override diff --git a/src/main/java/com/sk89q/worldguard/protection/regions/ProtectedRegion.java b/src/main/java/com/sk89q/worldguard/protection/regions/ProtectedRegion.java index 216f33a2..428860e7 100644 --- a/src/main/java/com/sk89q/worldguard/protection/regions/ProtectedRegion.java +++ b/src/main/java/com/sk89q/worldguard/protection/regions/ProtectedRegion.java @@ -19,6 +19,7 @@ package com.sk89q.worldguard.protection.regions; +import com.google.common.collect.Lists; import com.sk89q.worldedit.BlockVector; import com.sk89q.worldedit.BlockVector2D; import com.sk89q.worldedit.Vector; @@ -29,6 +30,7 @@ import com.sk89q.worldguard.util.Normal; import javax.annotation.Nullable; +import java.awt.geom.Area; import java.awt.geom.Line2D; import java.util.Collection; import java.util.List; @@ -118,6 +120,13 @@ public String getId() { return id; } + /** + * Return whether this type of region encompasses physical area. + * + * @return Whether physical area is encompassed + */ + public abstract boolean isPhysicalArea(); + /** * Get a vector containing the smallest X, Y, and Z components for the * corner of the axis-aligned bounding box that contains this region. @@ -570,7 +579,39 @@ public final String getTypeName() { * @param regions a list of regions to source from * @return the elements of {@code regions} that intersect with this region */ - public abstract List getIntersectingRegions(Collection regions); + public List getIntersectingRegions(Collection regions) { + checkNotNull(regions, "regions"); + + List intersecting = Lists.newArrayList(); + Area thisArea = toArea(); + + for (ProtectedRegion region : regions) { + if (!region.isPhysicalArea()) continue; + + if (intersects(region, thisArea)) { + intersecting.add(region); + } + } + + return intersecting; + } + + /** + * Test whether the given region intersects with this area. + * + * @param region the region to test + * @param thisArea an area object for this region + * @return true if the two regions intersect + */ + protected boolean intersects(ProtectedRegion region, Area thisArea) { + if (intersectsBoundingBox(region)) { + Area testArea = region.toArea(); + testArea.intersect(thisArea); + return !testArea.isEmpty(); + } else { + return false; + } + } /** * Checks if the bounding box of a region intersects with with the bounding @@ -631,6 +672,14 @@ protected boolean intersectsEdges(ProtectedRegion region) { return false; } + /** + * Return the AWT area, otherwise null if + * {@link #isPhysicalArea()} if false. + * + * @return The shape version + */ + abstract Area toArea(); + @Override public boolean isDirty() { return dirty || owners.isDirty() || members.isDirty();