diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/AbstractRegion.java b/src/main/java/in/twizmwaz/cardinal/module/region/AbstractRegion.java index 00975fc..e441226 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/AbstractRegion.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/AbstractRegion.java @@ -32,6 +32,7 @@ import org.bukkit.block.Block; import java.util.Collection; +import java.util.Random; @Getter @Setter(AccessLevel.PROTECTED) @@ -42,4 +43,6 @@ public abstract class AbstractRegion implements Region { private Collection blocks; + private Random random = new Random(); + } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/RegionBounds.java b/src/main/java/in/twizmwaz/cardinal/module/region/RegionBounds.java index e10ec26..0961459 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/RegionBounds.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/RegionBounds.java @@ -28,9 +28,10 @@ import com.google.common.collect.ImmutableSet; import in.twizmwaz.cardinal.match.Match; import in.twizmwaz.cardinal.module.region.type.BlockRegion; -import in.twizmwaz.cardinal.util.Vectors; +import in.twizmwaz.cardinal.util.Geometry; import lombok.Data; import org.bukkit.block.Block; +import org.bukkit.util.Cuboid; import org.bukkit.util.Vector; import java.util.Collection; @@ -44,19 +45,18 @@ public class RegionBounds { private final Match match; - private final Vector min; - private final Vector max; + private final Cuboid cuboid; public static RegionBounds empty(Match match) { - return new RegionBounds(match, Vectors.max(), Vectors.min()); + return new RegionBounds(match, Cuboid.empty()); } public static RegionBounds unbounded(Match match) { - return new RegionBounds(match, Vectors.min(), Vectors.max()); + return new RegionBounds(match, Cuboid.unbounded()); } public RegionBounds translate(Vector offset) { - return new RegionBounds(match, min.plus(offset), max.plus(offset)); + return new RegionBounds(match, cuboid.translate(offset)); } /** @@ -67,9 +67,9 @@ public RegionBounds translate(Vector offset) { * @return The mirrored region bounds. */ public RegionBounds mirror(Vector origin, Vector normal) { - return new RegionBounds(match, - Vectors.getMirroredVector(min, origin, normal), - Vectors.getMirroredVector(max, origin, normal)); + return new RegionBounds(match, Cuboid.between( + Geometry.getMirrored(cuboid.minimum(), origin, normal), + Geometry.getMirrored(cuboid.maximum(), origin, normal))); } /** @@ -78,16 +78,11 @@ public RegionBounds mirror(Vector origin, Vector normal) { * @return If the bounds are bounded. */ public boolean isBounded() { - return !(Double.isInfinite(min.getX()) - || Double.isInfinite(max.getX()) - || Double.isInfinite(min.getY()) - || Double.isInfinite(max.getY()) - || Double.isInfinite(min.getZ()) - || Double.isInfinite(max.getZ())); + return cuboid.isFinite(); } public Vector getCenter() { - return min.midpoint(max); + return cuboid.center(); } public BlockRegion getCenterBlock() { @@ -100,17 +95,17 @@ public BlockRegion getCenterBlock() { * @return The blocks. */ public Collection getBlocks() { - if (!isBounded()) { + if (!cuboid.isBlockFinite()) { throw new UnsupportedOperationException("Cannot get blocks in unbounded region"); } - Vector min = Vectors.alignToBlock(this.min); - Vector max = Vectors.alignToBlock(this.max); + Vector min = Geometry.alignToBlock(this.cuboid.minimum()); + Vector max = Geometry.alignToBlock(this.cuboid.maximum()); ImmutableSet.Builder builder = ImmutableSet.builder(); for (int z = min.getBlockZ(); z < max.getBlockZ(); z++) { for (int y = min.getBlockY(); y < max.getBlockY(); y++) { for (int x = min.getBlockX(); x < max.getBlockX(); x++) { - builder.add(new Vector(x, y, z).toLocation(match.getWorld()).getBlock()); //TODO: Get match world + builder.add(new Vector(x, y, z).toLocation(match.getWorld()).getBlock()); } } } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/RegionModule.java b/src/main/java/in/twizmwaz/cardinal/module/region/RegionModule.java index a5073ed..6e5f16f 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/RegionModule.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/RegionModule.java @@ -44,6 +44,7 @@ import in.twizmwaz.cardinal.module.region.parser.CuboidRegionParser; import in.twizmwaz.cardinal.module.region.parser.CylinderRegionParser; import in.twizmwaz.cardinal.module.region.parser.HalfRegionParser; +import in.twizmwaz.cardinal.module.region.parser.PointRegionParser; import in.twizmwaz.cardinal.module.region.parser.RectangleRegionParser; import in.twizmwaz.cardinal.module.region.parser.SphereRegionParser; import in.twizmwaz.cardinal.module.region.parser.modifications.ComplementRegionParser; @@ -176,6 +177,8 @@ public Region getRegion(Match match, Element element, String... alternateAttribu return checkRegion(match, id, new TranslatedRegion(new TranslatedRegionParser(match, element))); case "mirror": return checkRegion(match, id, new MirroredRegion(new MirroredRegionParser(match, element))); + case "point": + return checkRegion(match, id, PointRegionParser.generateRegion(match, element)); default: if (id != null) { Region region = getRegionById(match, id); @@ -199,7 +202,12 @@ public Region getRegion(Match match, Element element, String... alternateAttribu private Region checkRegion(Match match, String id, Region region) { if (id != null) { - regions.get(match).put(id, region); + if (!regions.get(match).containsKey(id)) { + regions.get(match).put(id, region); + } else { + errors.add(new ModuleError(this, match.getMap(), + new String[] {"Cannot have two regions assigned to the same id."}, false)); + } } return region; } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/parser/BlockRegionParser.java b/src/main/java/in/twizmwaz/cardinal/module/region/parser/BlockRegionParser.java index 6d3d753..6d7bee3 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/parser/BlockRegionParser.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/parser/BlockRegionParser.java @@ -29,7 +29,7 @@ import in.twizmwaz.cardinal.module.region.RegionParser; import in.twizmwaz.cardinal.module.region.exception.property.InvalidRegionPropertyException; import in.twizmwaz.cardinal.module.region.exception.property.MissingRegionPropertyException; -import in.twizmwaz.cardinal.util.Vectors; +import in.twizmwaz.cardinal.util.Numbers; import lombok.Getter; import org.bukkit.util.Vector; import org.jdom2.Element; @@ -52,7 +52,7 @@ public BlockRegionParser(Element element) throws RegionException { if (text == null) { throw new MissingRegionPropertyException("location", element); } - vector = Vectors.getVector(text); + vector = Numbers.getVector(text); if (vector == null) { throw new InvalidRegionPropertyException("location", element); } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/parser/CircleRegionParser.java b/src/main/java/in/twizmwaz/cardinal/module/region/parser/CircleRegionParser.java index 054a64b..0429d48 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/parser/CircleRegionParser.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/parser/CircleRegionParser.java @@ -30,13 +30,10 @@ import in.twizmwaz.cardinal.module.region.exception.attribute.InvalidRegionAttributeException; import in.twizmwaz.cardinal.module.region.exception.attribute.MissingRegionAttributeException; import in.twizmwaz.cardinal.util.Numbers; -import in.twizmwaz.cardinal.util.Vectors; import lombok.Getter; import org.bukkit.util.Vector; import org.jdom2.Element; -import java.util.List; - @Getter public class CircleRegionParser implements RegionParser { @@ -54,11 +51,11 @@ public CircleRegionParser(Element element) throws RegionException { if (centerValue == null) { throw new MissingRegionAttributeException("center", element); } - List coords = Vectors.getCoordinates(centerValue); - if (coords == null || coords.size() != 2) { + double[] coords = Numbers.parseCoordinates(centerValue); + if (coords == null || coords.length != 2) { throw new InvalidRegionAttributeException("center", element); } - center = new Vector(coords.get(0), 0, coords.get(1)); + center = new Vector(coords[0], 0, coords[1]); String radiusValue = element.getAttributeValue("radius"); if (radiusValue == null) { diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/parser/CuboidRegionParser.java b/src/main/java/in/twizmwaz/cardinal/module/region/parser/CuboidRegionParser.java index 7029f12..c628655 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/parser/CuboidRegionParser.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/parser/CuboidRegionParser.java @@ -30,16 +30,16 @@ import in.twizmwaz.cardinal.module.region.exception.RegionAttributeException; import in.twizmwaz.cardinal.module.region.exception.attribute.InvalidRegionAttributeException; import in.twizmwaz.cardinal.module.region.exception.attribute.MissingRegionAttributeException; -import in.twizmwaz.cardinal.util.Vectors; +import in.twizmwaz.cardinal.util.Numbers; import lombok.Getter; +import org.bukkit.util.Cuboid; import org.bukkit.util.Vector; import org.jdom2.Element; @Getter public class CuboidRegionParser implements RegionParser { - private final Vector min; - private final Vector max; + private final Cuboid cuboid; /** * Parses an element for a cuboid region. @@ -52,7 +52,7 @@ public CuboidRegionParser(Element element) throws RegionException { if (minValue == null) { throw new MissingRegionAttributeException("min", element); } - Vector min = Vectors.getVector(minValue); + Vector min = Numbers.getVector(minValue); if (min == null) { throw new InvalidRegionAttributeException("min", element); } @@ -61,13 +61,12 @@ public CuboidRegionParser(Element element) throws RegionException { if (maxValue == null) { throw new MissingRegionAttributeException("max", element); } - Vector max = Vectors.getVector(maxValue); + Vector max = Numbers.getVector(maxValue); if (max == null) { throw new InvalidRegionAttributeException("max", element); } - this.min = Vector.getMinimum(min, max); - this.max = Vector.getMaximum(min, max); + this.cuboid = Cuboid.between(min, max); } } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/parser/CylinderRegionParser.java b/src/main/java/in/twizmwaz/cardinal/module/region/parser/CylinderRegionParser.java index c10256c..eac17ef 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/parser/CylinderRegionParser.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/parser/CylinderRegionParser.java @@ -30,7 +30,6 @@ import in.twizmwaz.cardinal.module.region.exception.attribute.InvalidRegionAttributeException; import in.twizmwaz.cardinal.module.region.exception.attribute.MissingRegionAttributeException; import in.twizmwaz.cardinal.util.Numbers; -import in.twizmwaz.cardinal.util.Vectors; import lombok.Getter; import org.bukkit.util.Vector; import org.jdom2.Element; @@ -53,7 +52,7 @@ public CylinderRegionParser(Element element) throws RegionException { if (baseValue == null) { throw new MissingRegionAttributeException("base", element); } - base = Vectors.getVector(baseValue); + base = Numbers.getVector(baseValue); if (base == null) { throw new InvalidRegionAttributeException("base", element); } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/parser/HalfRegionParser.java b/src/main/java/in/twizmwaz/cardinal/module/region/parser/HalfRegionParser.java index aa5a3de..f778bb1 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/parser/HalfRegionParser.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/parser/HalfRegionParser.java @@ -29,7 +29,7 @@ import in.twizmwaz.cardinal.module.region.RegionParser; import in.twizmwaz.cardinal.module.region.exception.attribute.InvalidRegionAttributeException; import in.twizmwaz.cardinal.module.region.exception.attribute.MissingRegionAttributeException; -import in.twizmwaz.cardinal.util.Vectors; +import in.twizmwaz.cardinal.util.Numbers; import lombok.Getter; import org.bukkit.util.Vector; import org.jdom2.Element; @@ -51,7 +51,7 @@ public HalfRegionParser(Element element) throws RegionException { if (normalValue == null) { throw new MissingRegionAttributeException("normal", element); } - normal = Vectors.getVector(normalValue); + normal = Numbers.getVector(normalValue); if (normal == null) { throw new InvalidRegionAttributeException("normal", element); } @@ -60,7 +60,7 @@ public HalfRegionParser(Element element) throws RegionException { if (originValue == null) { throw new MissingRegionAttributeException("origin", element); } - origin = Vectors.getVector(originValue); + origin = Numbers.getVector(originValue); if (origin == null) { throw new InvalidRegionAttributeException("origin", element); } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/parser/PointRegionParser.java b/src/main/java/in/twizmwaz/cardinal/module/region/parser/PointRegionParser.java new file mode 100644 index 0000000..0694f46 --- /dev/null +++ b/src/main/java/in/twizmwaz/cardinal/module/region/parser/PointRegionParser.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2016, Kevin Phoenix + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package in.twizmwaz.cardinal.module.region.parser; + +import com.google.common.base.Strings; +import in.twizmwaz.cardinal.Cardinal; +import in.twizmwaz.cardinal.match.Match; +import in.twizmwaz.cardinal.module.region.Region; +import in.twizmwaz.cardinal.module.region.RegionException; +import in.twizmwaz.cardinal.module.region.RegionModule; +import in.twizmwaz.cardinal.module.region.RegionParser; +import in.twizmwaz.cardinal.module.region.exception.property.MissingRegionPropertyException; +import in.twizmwaz.cardinal.module.region.type.PointRegion; +import in.twizmwaz.cardinal.module.region.type.modifications.PointProviderRegion; +import in.twizmwaz.cardinal.util.Numbers; +import in.twizmwaz.cardinal.util.ParseUtil; +import lombok.Getter; +import lombok.NonNull; +import org.bukkit.Location; +import org.bukkit.util.Vector; +import org.jdom2.Element; + +@Getter +public class PointRegionParser implements RegionParser { + + private final float yaw; + private final float pitch; + private Vector position = null; + private Vector angle = null; + private Region region = null; + + private PointRegionParser(@NonNull Match match, @NonNull Element element) throws RegionException { + yaw = Numbers.parseFloat(ParseUtil.getFirstAttribute("yaw")); + pitch = Numbers.parseFloat(element.getAttributeValue("pitch")); + + if (!Strings.isNullOrEmpty(element.getText().trim())) { + position = Numbers.getVector(element.getText()); + } + + if (!Strings.isNullOrEmpty(element.getAttributeValue("angle").trim())) { + angle = Numbers.getVector(element.getAttributeValue("angle")); + } + + RegionModule module = Cardinal.getModule(RegionModule.class); + + if (!Strings.isNullOrEmpty(element.getAttributeValue("region"))) { + + Region region = module.getRegionById(match, element.getAttributeValue("region")); + this.region = region; + + } else if (element.getChildren("region").size() > 0) { + + region = module.getRegion(match, element.getChild("region")); + + } + } + + /** + * Parses a region from the Element. + * + *

This method is different from other parsers intentionally. Point regions are different in that for some reason, + * we have two different types with similar yet different purposes. This method is in place to differentiate between + * the region types and to return the correct one without something ugly in the module class.

+ * + * @param match The match. + * @param element The element to parse. + * @return The region, if applicable. + * @throws RegionException A {@link MissingRegionPropertyException} when there is no valid location. + */ + public static Region generateRegion(@NonNull Match match, @NonNull Element element) throws RegionException { + PointRegionParser parser = new PointRegionParser(match, element); + if (parser.getPosition() != null) { + Location location = parser.getPosition().toLocation(match.getWorld(), parser.getYaw(), parser.getPitch()); + if (parser.getAngle() != null) { + location.setDirection(parser.getAngle()); + } + return new PointRegion(match, location); + } else if (parser.getRegion() != null) { + return new PointProviderRegion(parser.getRegion(), parser.getAngle(), parser.getYaw(), parser.getPitch()); + } else { + throw new MissingRegionPropertyException("position", element); + } + + } + +} diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/parser/RectangleRegionParser.java b/src/main/java/in/twizmwaz/cardinal/module/region/parser/RectangleRegionParser.java index 8c3fdc9..746de45 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/parser/RectangleRegionParser.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/parser/RectangleRegionParser.java @@ -29,18 +29,17 @@ import in.twizmwaz.cardinal.module.region.RegionParser; import in.twizmwaz.cardinal.module.region.exception.attribute.InvalidRegionAttributeException; import in.twizmwaz.cardinal.module.region.exception.attribute.MissingRegionAttributeException; -import in.twizmwaz.cardinal.util.Vectors; +import in.twizmwaz.cardinal.util.Numbers; import lombok.Getter; +import org.bukkit.util.Cuboid; +import org.bukkit.util.ImmutableVector; import org.bukkit.util.Vector; import org.jdom2.Element; -import java.util.List; - @Getter public class RectangleRegionParser implements RegionParser { - private final Vector min; - private final Vector max; + private final Cuboid cuboid; /** * Parses an element for a rectangle region. @@ -52,21 +51,22 @@ public RectangleRegionParser(Element element) throws RegionException { if (minValue == null) { throw new MissingRegionAttributeException("min", element); } - List coords = Vectors.getCoordinates(minValue); - if (coords == null || coords.size() != 2) { + double[] coords = Numbers.parseCoordinates(minValue); + if (coords == null || coords.length != 2) { throw new InvalidRegionAttributeException("min", element); } - min = new Vector(coords.get(0), Double.NEGATIVE_INFINITY, coords.get(1)); + Vector min = ImmutableVector.of(coords[0], Double.NEGATIVE_INFINITY, coords[1]); String maxValue = element.getAttributeValue("max"); if (maxValue == null) { throw new MissingRegionAttributeException("max", element); } - coords = Vectors.getCoordinates(maxValue); - if (coords == null || coords.size() != 2) { + coords = Numbers.parseCoordinates(maxValue); + if (coords == null || coords.length != 2) { throw new InvalidRegionAttributeException("max", element); } - max = new Vector(coords.get(0), Double.POSITIVE_INFINITY, coords.get(1)); + Vector max = ImmutableVector.of(coords[0], Double.POSITIVE_INFINITY, coords[1]); + cuboid = Cuboid.between(min, max); } } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/parser/SphereRegionParser.java b/src/main/java/in/twizmwaz/cardinal/module/region/parser/SphereRegionParser.java index 08ae150..2dff361 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/parser/SphereRegionParser.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/parser/SphereRegionParser.java @@ -30,7 +30,6 @@ import in.twizmwaz.cardinal.module.region.exception.attribute.InvalidRegionAttributeException; import in.twizmwaz.cardinal.module.region.exception.attribute.MissingRegionAttributeException; import in.twizmwaz.cardinal.util.Numbers; -import in.twizmwaz.cardinal.util.Vectors; import lombok.Getter; import org.bukkit.util.Vector; import org.jdom2.Element; @@ -52,7 +51,7 @@ public SphereRegionParser(Element element) throws RegionException { if (originValue == null) { throw new MissingRegionAttributeException("origin", element); } - origin = Vectors.getVector(originValue); + origin = Numbers.getVector(originValue); if (origin == null) { throw new InvalidRegionAttributeException("origin", element); } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/parser/modifications/MirroredRegionParser.java b/src/main/java/in/twizmwaz/cardinal/module/region/parser/modifications/MirroredRegionParser.java index 5d8b1f5..8deed29 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/parser/modifications/MirroredRegionParser.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/parser/modifications/MirroredRegionParser.java @@ -34,7 +34,7 @@ import in.twizmwaz.cardinal.module.region.exception.attribute.InvalidRegionAttributeException; import in.twizmwaz.cardinal.module.region.exception.attribute.MissingRegionAttributeException; import in.twizmwaz.cardinal.module.region.exception.property.MissingRegionPropertyException; -import in.twizmwaz.cardinal.util.Vectors; +import in.twizmwaz.cardinal.util.Numbers; import lombok.Getter; import lombok.NonNull; import org.bukkit.util.Vector; @@ -73,7 +73,7 @@ public MirroredRegionParser(@NonNull Match match, Element element) throws Region if (originValue == null) { origin = new Vector(0, 0, 0); } else { - origin = Vectors.getVector(originValue); + origin = Numbers.getVector(originValue); if (origin == null) { throw new InvalidRegionAttributeException("origin", element); } @@ -83,7 +83,7 @@ public MirroredRegionParser(@NonNull Match match, Element element) throws Region if (normalValue == null) { throw new MissingRegionAttributeException("normal", element); } - normal = Vectors.getVector(normalValue); + normal = Numbers.getVector(normalValue); if (normal == null) { throw new InvalidRegionAttributeException("normal", element); } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/parser/modifications/TranslatedRegionParser.java b/src/main/java/in/twizmwaz/cardinal/module/region/parser/modifications/TranslatedRegionParser.java index 58c23fb..98994be 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/parser/modifications/TranslatedRegionParser.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/parser/modifications/TranslatedRegionParser.java @@ -34,7 +34,7 @@ import in.twizmwaz.cardinal.module.region.exception.attribute.InvalidRegionAttributeException; import in.twizmwaz.cardinal.module.region.exception.attribute.MissingRegionAttributeException; import in.twizmwaz.cardinal.module.region.exception.property.MissingRegionPropertyException; -import in.twizmwaz.cardinal.util.Vectors; +import in.twizmwaz.cardinal.util.Numbers; import lombok.Getter; import lombok.NonNull; import org.bukkit.util.Vector; @@ -72,7 +72,7 @@ public TranslatedRegionParser(@NonNull Match match, Element element) throws Regi if (offsetValue == null) { throw new MissingRegionAttributeException("offset", element); } - offset = Vectors.getVector(offsetValue); + offset = Numbers.getVector(offsetValue); if (offset == null) { throw new InvalidRegionAttributeException("offset", element); } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/type/AboveRegion.java b/src/main/java/in/twizmwaz/cardinal/module/region/type/AboveRegion.java index 7d0a7f4..4572c1f 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/type/AboveRegion.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/type/AboveRegion.java @@ -29,8 +29,9 @@ import in.twizmwaz.cardinal.module.region.AbstractRegion; import in.twizmwaz.cardinal.module.region.RegionBounds; import in.twizmwaz.cardinal.module.region.parser.AboveRegionParser; -import in.twizmwaz.cardinal.util.Vectors; +import in.twizmwaz.cardinal.util.Geometry; import org.bukkit.block.Block; +import org.bukkit.util.Cuboid; import org.bukkit.util.Vector; import java.util.Collection; @@ -40,7 +41,7 @@ public class AboveRegion extends AbstractRegion { private final Vector min; public AboveRegion(Match match, Vector min) { - super(new RegionBounds(match, min, Vectors.max())); + super(new RegionBounds(match, Cuboid.between(min, Geometry.MAXIMUM_VECTOR))); this.min = min; } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/type/BelowRegion.java b/src/main/java/in/twizmwaz/cardinal/module/region/type/BelowRegion.java index f5aa13c..e5b6fd6 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/type/BelowRegion.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/type/BelowRegion.java @@ -29,8 +29,9 @@ import in.twizmwaz.cardinal.module.region.AbstractRegion; import in.twizmwaz.cardinal.module.region.RegionBounds; import in.twizmwaz.cardinal.module.region.parser.BelowRegionParser; -import in.twizmwaz.cardinal.util.Vectors; +import in.twizmwaz.cardinal.util.Geometry; import org.bukkit.block.Block; +import org.bukkit.util.Cuboid; import org.bukkit.util.Vector; import java.util.Collection; @@ -40,7 +41,7 @@ public class BelowRegion extends AbstractRegion { private final Vector max; public BelowRegion(Match match, Vector max) { - super(new RegionBounds(match, Vectors.min(), max)); + super(new RegionBounds(match, Cuboid.between(Geometry.MINIMUM_VECTOR, max))); this.max = max; } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/type/BlockRegion.java b/src/main/java/in/twizmwaz/cardinal/module/region/type/BlockRegion.java index 842d67b..2e37292 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/type/BlockRegion.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/type/BlockRegion.java @@ -32,6 +32,8 @@ import in.twizmwaz.cardinal.module.region.parser.BlockRegionParser; import org.bukkit.Location; import org.bukkit.block.Block; +import org.bukkit.util.Cuboid; +import org.bukkit.util.ImmutableVector; import org.bukkit.util.Vector; import java.util.Collection; @@ -41,8 +43,8 @@ public class BlockRegion extends AbstractRegion { private final Vector vector; public BlockRegion(Match match, Vector vector) { - super(new RegionBounds(match, vector, vector.plus(1, 1, 1))); - this.vector = vector; + super(new RegionBounds(match, Cuboid.between(vector, vector.plus(1, 1, 1)))); + this.vector = ImmutableVector.copyOf(vector); } public BlockRegion(Match match, BlockRegionParser parser) { @@ -61,7 +63,7 @@ public Vector getVector() { } public Location getLocation() { - return getVector().toLocation(null); //TODO: Get match world + return getVector().toLocation(getBounds().getMatch().getWorld()); } public Block getBlock() { diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/type/CircleRegion.java b/src/main/java/in/twizmwaz/cardinal/module/region/type/CircleRegion.java index 363380f..c410486 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/type/CircleRegion.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/type/CircleRegion.java @@ -30,6 +30,7 @@ import in.twizmwaz.cardinal.module.region.RegionBounds; import in.twizmwaz.cardinal.module.region.parser.CircleRegionParser; import org.bukkit.block.Block; +import org.bukkit.util.Cuboid; import org.bukkit.util.Vector; import java.util.Collection; @@ -46,9 +47,9 @@ public class CircleRegion extends AbstractRegion { * @param radius The radius. */ public CircleRegion(Match match, Vector center, double radius) { - super(new RegionBounds(match, + super(new RegionBounds(match, Cuboid.between( new Vector(center.getX() - radius, Double.NEGATIVE_INFINITY, center.getZ() - radius), - new Vector(center.getX() + radius, Double.POSITIVE_INFINITY, center.getZ() + radius))); + new Vector(center.getX() + radius, Double.POSITIVE_INFINITY, center.getZ() + radius)))); this.center = center; this.radius = radius; } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/type/CuboidRegion.java b/src/main/java/in/twizmwaz/cardinal/module/region/type/CuboidRegion.java index b64cd49..689ab93 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/type/CuboidRegion.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/type/CuboidRegion.java @@ -29,36 +29,35 @@ import in.twizmwaz.cardinal.module.region.AbstractRegion; import in.twizmwaz.cardinal.module.region.RegionBounds; import in.twizmwaz.cardinal.module.region.parser.CuboidRegionParser; -import in.twizmwaz.cardinal.util.Numbers; import org.bukkit.block.Block; +import org.bukkit.util.Cuboid; import org.bukkit.util.Vector; import java.util.Collection; +import java.util.Random; public class CuboidRegion extends AbstractRegion { - private final Vector min; - private final Vector max; + private final Cuboid cuboid; + private final Random random = new Random(); /** * Creates a cuboid region with a given min and max. * - * @param min The min. - * @param max The max. + * @param cuboid The cuboid which the region represents. */ - public CuboidRegion(Match match, Vector min, Vector max) { - super(new RegionBounds(match, min, max)); - this.min = min; - this.max = max; + public CuboidRegion(Match match, Cuboid cuboid) { + super(new RegionBounds(match, cuboid)); + this.cuboid = cuboid; } public CuboidRegion(Match match, CuboidRegionParser parser) { - this(match, parser.getMin(), parser.getMax()); + this(match, parser.getCuboid()); } @Override public boolean evaluate(Vector vector) { - return vector.isInAABB(min, max); + return cuboid.contains(vector); } @Override @@ -89,10 +88,7 @@ public Vector getRandomPoint() { if (!isRandomizable()) { throw new UnsupportedOperationException("Cannot get random point in non-randomizable region"); } - return new Vector( - Numbers.getRandom(min.getX(), max.getX()), - Numbers.getRandom(min.getY(), max.getY()), - Numbers.getRandom(min.getZ(), max.getZ())); + return cuboid.randomPointInside(random); } } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/type/CylinderRegion.java b/src/main/java/in/twizmwaz/cardinal/module/region/type/CylinderRegion.java index e30bc1e..9d77574 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/type/CylinderRegion.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/type/CylinderRegion.java @@ -32,6 +32,7 @@ import in.twizmwaz.cardinal.module.region.parser.CylinderRegionParser; import in.twizmwaz.cardinal.util.Numbers; import org.bukkit.block.Block; +import org.bukkit.util.Cuboid; import org.bukkit.util.Vector; import java.util.Collection; @@ -51,9 +52,9 @@ public class CylinderRegion extends AbstractRegion { * @param height The height. */ public CylinderRegion(Match match, Vector base, double radius, double height) { - super(new RegionBounds(match, + super(new RegionBounds(match, Cuboid.between( new Vector(base.getX() - radius, base.getY(), base.getZ() - radius), - new Vector(base.getX() + radius, base.getY() + height, base.getZ() + radius))); + new Vector(base.getX() + radius, base.getY() + height, base.getZ() + radius)))); this.base = base; this.radius = radius; this.height = height; diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/type/PointRegion.java b/src/main/java/in/twizmwaz/cardinal/module/region/type/PointRegion.java new file mode 100644 index 0000000..a4085ca --- /dev/null +++ b/src/main/java/in/twizmwaz/cardinal/module/region/type/PointRegion.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016, Kevin Phoenix + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package in.twizmwaz.cardinal.module.region.type; + +import in.twizmwaz.cardinal.match.Match; +import in.twizmwaz.cardinal.module.region.AbstractRegion; +import in.twizmwaz.cardinal.module.region.RegionBounds; +import org.bukkit.Location; +import org.bukkit.util.Cuboid; +import org.bukkit.util.Vector; + +public class PointRegion extends AbstractRegion { + + private final Location location; + + public PointRegion(Match match, Location location) { + super(new RegionBounds(match, Cuboid.enclosing(location))); + this.location = location; + } + + @Override + public boolean isRandomizable() { + return true; + } + + @Override + public boolean isBounded() { + return true; + } + + @Override + public Vector getRandomPoint() { + return location; + } + + @Override + public boolean evaluate(Vector evaluating) { + return evaluating != null && evaluating.equals(location.toVector()); + } +} diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/type/RectangleRegion.java b/src/main/java/in/twizmwaz/cardinal/module/region/type/RectangleRegion.java index c7c57b8..f9a64be 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/type/RectangleRegion.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/type/RectangleRegion.java @@ -26,59 +26,25 @@ package in.twizmwaz.cardinal.module.region.type; import in.twizmwaz.cardinal.match.Match; -import in.twizmwaz.cardinal.module.region.AbstractRegion; -import in.twizmwaz.cardinal.module.region.RegionBounds; import in.twizmwaz.cardinal.module.region.parser.RectangleRegionParser; -import org.bukkit.block.Block; +import org.bukkit.util.Cuboid; import org.bukkit.util.Vector; -import java.util.Collection; - -public class RectangleRegion extends AbstractRegion { - - private final Vector min; - private final Vector max; +public class RectangleRegion extends CuboidRegion { /** * @param min The rectangle's minimum bound. * @param max The rectangle's maximum bound. */ public RectangleRegion(Match match, Vector min, Vector max) { - super(new RegionBounds(match, min, max)); - - this.min = Vector.getMinimum(min, max); - this.min.setY(Double.NEGATIVE_INFINITY); - - this.max = Vector.getMaximum(min, max); - this.max.setY(Double.POSITIVE_INFINITY); - } - - public RectangleRegion(Match match, RectangleRegionParser parser) { - this(match, parser.getMin(), parser.getMax()); + super(match, Cuboid.between(min.add(0, Double.NEGATIVE_INFINITY, 0), max.add(0, Double.POSITIVE_INFINITY, 0))); } - @Override - public boolean evaluate(Vector vector) { - return vector.isInAABB(min, max); + public RectangleRegion(Match match, Cuboid cuboid) { + this(match, cuboid.minimum(), cuboid.maximum()); } - @Override - public boolean isRandomizable() { - return false; - } - - @Override - public boolean isBounded() { - return false; - } - - @Override - public Collection getBlocks() { - throw new UnsupportedOperationException("Cannot get blocks in unbounded region"); - } - - @Override - public Vector getRandomPoint() { - throw new UnsupportedOperationException("Cannot get random point in non-randomizable region"); + public RectangleRegion(Match match, RectangleRegionParser parser) { + this(match, parser.getCuboid().minimum(), parser.getCuboid().maximum()); } } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/type/SphereRegion.java b/src/main/java/in/twizmwaz/cardinal/module/region/type/SphereRegion.java index 7a802c4..27ace4e 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/type/SphereRegion.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/type/SphereRegion.java @@ -31,6 +31,7 @@ import in.twizmwaz.cardinal.module.region.RegionBounds; import in.twizmwaz.cardinal.module.region.parser.SphereRegionParser; import org.bukkit.block.Block; +import org.bukkit.util.Cuboid; import org.bukkit.util.Vector; import java.util.Collection; @@ -48,9 +49,9 @@ public class SphereRegion extends AbstractRegion { * @param radius The radius. */ public SphereRegion(Match match, Vector origin, double radius) { - super(new RegionBounds(match, + super(new RegionBounds(match, Cuboid.between( new Vector(origin.getX() - radius, origin.getY() - radius, origin.getZ() - radius), - new Vector(origin.getX() + radius, origin.getY() + radius, origin.getZ() + radius))); + new Vector(origin.getX() + radius, origin.getY() + radius, origin.getZ() + radius)))); this.origin = origin; this.radius = radius; } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/type/modifications/IntersectRegion.java b/src/main/java/in/twizmwaz/cardinal/module/region/type/modifications/IntersectRegion.java index 2b5952c..2ff2376 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/type/modifications/IntersectRegion.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/type/modifications/IntersectRegion.java @@ -31,20 +31,19 @@ import in.twizmwaz.cardinal.module.region.Region; import in.twizmwaz.cardinal.module.region.RegionBounds; import in.twizmwaz.cardinal.module.region.parser.modifications.IntersectRegionParser; -import in.twizmwaz.cardinal.util.Vectors; +import in.twizmwaz.cardinal.util.Geometry; import org.bukkit.block.Block; import org.bukkit.util.Vector; import java.util.Collection; -import java.util.List; import java.util.stream.Collectors; public class IntersectRegion extends AbstractRegion { - private final List regions; + private final Collection regions; - public IntersectRegion(Match match, List regions) { - super(new RegionBounds(match, Vectors.getMinimumBound(regions), Vectors.getMaximumBound(regions))); + public IntersectRegion(Match match, Collection regions) { + super(new RegionBounds(match, Geometry.getCuboidEnclosing(regions))); this.regions = regions; } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/type/modifications/MirroredRegion.java b/src/main/java/in/twizmwaz/cardinal/module/region/type/modifications/MirroredRegion.java index 704166c..0efec7b 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/type/modifications/MirroredRegion.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/type/modifications/MirroredRegion.java @@ -28,7 +28,7 @@ import in.twizmwaz.cardinal.module.region.AbstractRegion; import in.twizmwaz.cardinal.module.region.Region; import in.twizmwaz.cardinal.module.region.parser.modifications.MirroredRegionParser; -import in.twizmwaz.cardinal.util.Vectors; +import in.twizmwaz.cardinal.util.Geometry; import org.bukkit.block.Block; import org.bukkit.util.Vector; @@ -61,7 +61,7 @@ public MirroredRegion(MirroredRegionParser parser) { @Override public boolean evaluate(Vector vector) { - return region.evaluate(Vectors.getMirroredVector(vector, origin, normal)); + return region.evaluate(Geometry.getMirrored(vector, origin, normal)); } @Override @@ -93,7 +93,7 @@ public Vector getRandomPoint() { if (!isRandomizable()) { throw new UnsupportedOperationException("Cannot get random point in non-randomizable region"); } - return Vectors.getMirroredVector(region.getRandomPoint(), origin, normal); + return Geometry.getMirrored(region.getRandomPoint(), origin, normal); } } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/type/modifications/NegativeRegion.java b/src/main/java/in/twizmwaz/cardinal/module/region/type/modifications/NegativeRegion.java index 8381fd7..056cb8b 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/type/modifications/NegativeRegion.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/type/modifications/NegativeRegion.java @@ -30,8 +30,8 @@ import in.twizmwaz.cardinal.module.region.Region; import in.twizmwaz.cardinal.module.region.RegionBounds; import in.twizmwaz.cardinal.module.region.parser.modifications.NegativeRegionParser; -import in.twizmwaz.cardinal.util.Vectors; import org.bukkit.block.Block; +import org.bukkit.util.Cuboid; import org.bukkit.util.Vector; import java.util.Collection; @@ -41,7 +41,7 @@ public class NegativeRegion extends AbstractRegion { private final Region region; public NegativeRegion(Match match, Region region) { - super(new RegionBounds(match, Vectors.min(), Vectors.max())); + super(new RegionBounds(match, Cuboid.unbounded())); this.region = region; } diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/type/modifications/PointProviderRegion.java b/src/main/java/in/twizmwaz/cardinal/module/region/type/modifications/PointProviderRegion.java new file mode 100644 index 0000000..ac16e75 --- /dev/null +++ b/src/main/java/in/twizmwaz/cardinal/module/region/type/modifications/PointProviderRegion.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016, Kevin Phoenix + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package in.twizmwaz.cardinal.module.region.type.modifications; + +import in.twizmwaz.cardinal.module.region.AbstractRegion; +import in.twizmwaz.cardinal.module.region.Region; +import lombok.NonNull; +import org.bukkit.Location; +import org.bukkit.util.Vector; + +public class PointProviderRegion extends AbstractRegion { + + private final Region region; + private Vector direction; + private final float yaw; + private final float pitch; + + /** + * @param region The region to get points from. + * @param direction A vector to set direction. + * @param yaw Yaw for direction. + * @param pitch Pitch for direction. + */ + public PointProviderRegion(@NonNull Region region, Vector direction, float yaw, float pitch) { + super(region.getBounds()); + this.region = region; + this.yaw = yaw; + this.pitch = pitch; + } + + @Override + public boolean isRandomizable() { + return true; + } + + @Override + public boolean isBounded() { + return true; + } + + @Override + public Vector getRandomPoint() { + Location location = region.getRandomPoint().toLocation(getBounds().getMatch().getWorld(), yaw, pitch); + if (direction != null) { + location.setDirection(direction); + } + return location; + } + + @Override + public boolean evaluate(Vector evaluating) { + throw new UnsupportedOperationException("Cannot determine absolute location of PointProvider"); + } +} diff --git a/src/main/java/in/twizmwaz/cardinal/module/region/type/modifications/UnionRegion.java b/src/main/java/in/twizmwaz/cardinal/module/region/type/modifications/UnionRegion.java index 1f0496e..6fc0995 100644 --- a/src/main/java/in/twizmwaz/cardinal/module/region/type/modifications/UnionRegion.java +++ b/src/main/java/in/twizmwaz/cardinal/module/region/type/modifications/UnionRegion.java @@ -31,8 +31,8 @@ import in.twizmwaz.cardinal.module.region.Region; import in.twizmwaz.cardinal.module.region.RegionBounds; import in.twizmwaz.cardinal.module.region.parser.modifications.UnionRegionParser; +import in.twizmwaz.cardinal.util.Geometry; import in.twizmwaz.cardinal.util.ListUtil; -import in.twizmwaz.cardinal.util.Vectors; import org.bukkit.block.Block; import org.bukkit.util.Vector; @@ -44,7 +44,7 @@ public class UnionRegion extends AbstractRegion { private final List regions; public UnionRegion(Match match, List regions) { - super(new RegionBounds(match, Vectors.getMinimumBound(regions), Vectors.getMaximumBound(regions))); + super(new RegionBounds(match, Geometry.getCuboidEnclosing(regions))); this.regions = regions; } @@ -91,7 +91,7 @@ public Vector getRandomPoint() { if (!isRandomizable()) { throw new UnsupportedOperationException("Cannot get random point in non-randomizable region"); } - return ListUtil.getRandom(regions).getRandomPoint(); + return ListUtil.getRandom(getRandom(), regions).getRandomPoint(); } @Override diff --git a/src/main/java/in/twizmwaz/cardinal/util/Geometry.java b/src/main/java/in/twizmwaz/cardinal/util/Geometry.java new file mode 100644 index 0000000..f1bdedc --- /dev/null +++ b/src/main/java/in/twizmwaz/cardinal/util/Geometry.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2016, Kevin Phoenix + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package in.twizmwaz.cardinal.util; + +import in.twizmwaz.cardinal.module.region.Region; +import lombok.NonNull; +import org.bukkit.util.Cuboid; +import org.bukkit.util.ImmutableVector; +import org.bukkit.util.Vector; + +import java.util.Collection; +import java.util.stream.Collectors; + +public class Geometry { + + public static final Vector MINIMUM_VECTOR = ImmutableVector.of(Double.NEGATIVE_INFINITY); + public static final Vector MAXIMUM_VECTOR = ImmutableVector.of(Double.POSITIVE_INFINITY); + + /** + * Mirrors a vector across a normal from an origin. + * + * @param vector The original vector. + * @param origin The origin. + * @param normal The normal. + * @return The mirrored vector. + */ + public static Vector getMirrored(Vector vector, Vector origin, Vector normal) { + vector = vector.minus(origin); + vector = vector.minus(normal.times(vector.dot(normal)).times(2)).add(origin); + vector = new Vector(round(vector.getX()), round(vector.getY()), round(vector.getZ())); + return vector; + } + + /** + * Mirrors a cuboid across a normal from an origin. + * + * @param cuboid The original cuboid. + * @param origin The origin. + * @param normal The normal. + * @return The mirrored cuboid. + */ + public static Cuboid getMirrored(Cuboid cuboid, Vector origin, Vector normal) { + return Cuboid.between( + getMirrored(cuboid.minimum(), origin, normal), + getMirrored(cuboid.maximum(), origin, normal)); + } + + public static double round(double d) { + return (double) Math.round(d * 10) / 10d; + } + + /** + * Gets the minimum vector from a list of regions. + * + * @param regions The list of regions. + * @return The minimum vector. + */ + public static Vector getMinimumBound(@NonNull Collection regions) { + Collection minimums = regions.stream().map(region -> + region.getBounds().getCuboid().minimum()).collect(Collectors.toList()); + return getMinimum((Vector[]) minimums.toArray()); + } + + /** + * Gets the minimum vector from a list of vectors. + * + * @param vectors The list of vectors. + * @return The minimum vector. + */ + public static Vector getMinimum(@NonNull Vector... vectors) { + return Cuboid.enclosing(vectors).minimum(); + } + + /** + * Gets the maximum vector from a list of regions. + * + * @param regions The list of regions. + * @return The maximum vector. + */ + public static Vector getMaximumBound(@NonNull Collection regions) { + Collection maximums = regions.stream().map(region -> + region.getBounds().getCuboid().maximum()).collect(Collectors.toList()); + return getMaximum((Vector[]) maximums.toArray()); + } + + /** + * Gets the maximum vector from a list of vectors. + * + * @param vectors The list of vectors. + * @return The maximum vector. + */ + public static Vector getMaximum(@NonNull Vector... vectors) { + return Cuboid.enclosing(vectors).maximum(); + } + + public static Vector floor(Vector vector) { + return ImmutableVector.of(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()); + } + + /** + * Rounds all values of a cuboid down. + * + * @param cuboid The original cuboid. + * @return The floored cuboid. + */ + public static Cuboid floor(Cuboid cuboid) { + Vector min = floor(cuboid.minimum()); + Vector max = floor(cuboid.maximum()); + return Cuboid.between(min, max); + } + + public static Vector alignToBlock(Vector vector) { + return ImmutableVector.copyOf(floor(vector)).add(0.5d, 0.5d, 0.5d); + } + + /** + * Aligns all values of a cuboid to blocks. + * + * @param cuboid The original cuboid. + * @return The aligned cuboid. + */ + public static Cuboid alignToBlock(Cuboid cuboid) { + Vector min = alignToBlock(cuboid.minimum()); + Vector max = alignToBlock(cuboid.maximum()); + return Cuboid.between(min, max); + } + + public static Cuboid getCuboidEnclosing(Collection regions) { + return Cuboid.between(getMinimumBound(regions), getMaximumBound(regions)); + } + +} diff --git a/src/main/java/in/twizmwaz/cardinal/util/ListUtil.java b/src/main/java/in/twizmwaz/cardinal/util/ListUtil.java index 7f0af77..cb36d28 100644 --- a/src/main/java/in/twizmwaz/cardinal/util/ListUtil.java +++ b/src/main/java/in/twizmwaz/cardinal/util/ListUtil.java @@ -40,12 +40,16 @@ public class ListUtil { * @param The list type. * @return A random value from the list, if it exists. */ - public static T getRandom(@NonNull List list) { + public static T getRandom(@NonNull Random random, @NonNull List list) { if (list.size() > 0) { - return list.get(new Random().nextInt(list.size())); + return list.get(random.nextInt(list.size())); } else { throw new IllegalArgumentException("Cannot get random entry from an empty list."); } } + public static T getRandom(@NonNull List list) { + return getRandom(new Random(), list); + } + } diff --git a/src/main/java/in/twizmwaz/cardinal/util/Numbers.java b/src/main/java/in/twizmwaz/cardinal/util/Numbers.java index a73cc47..b32bb53 100644 --- a/src/main/java/in/twizmwaz/cardinal/util/Numbers.java +++ b/src/main/java/in/twizmwaz/cardinal/util/Numbers.java @@ -25,6 +25,10 @@ package in.twizmwaz.cardinal.util; +import lombok.NonNull; +import org.bukkit.util.ImmutableVector; +import org.bukkit.util.Vector; + import java.util.Random; public class Numbers { @@ -71,6 +75,31 @@ public static double parseDouble(String in) { return parseDouble(in, 0); } + /** + * @param in The input string. + * @param fallback The float fallback if parsing fails. + * @return The parsed float based on the input string. + */ + public static float parseFloat(String in, float fallback) { + if (in == null) { + return fallback; + } else if (in.equalsIgnoreCase("oo")) { + return Float.POSITIVE_INFINITY; + } else if (in.equalsIgnoreCase("-oo")) { + return Float.NEGATIVE_INFINITY; + } else { + return Float.parseFloat(in); + } + } + + /** + * @param in The input string. + * @return The parsed float based on the input string. + */ + public static float parseFloat(String in) { + return parseFloat(in, 0); + } + /** * @param in The input string. * @param fallback Fallback value if the input is null. @@ -99,7 +128,7 @@ public static int parseInteger(String in) { /** * @param in The input string. * @param fallback Fallback value if the input is null. - * @return The parsed integer based on the input string. + * @return The parsed short based on the input string. */ public static short parseShort(String in, short fallback) { if (in == null) { @@ -115,12 +144,37 @@ public static short parseShort(String in, short fallback) { /** * @param in The input string. - * @return The parsed integer based on the input string. + * @return The parsed short based on the input string. */ public static short parseShort(String in) { return parseShort(in, (short) 0); } + /** + * @param in The input string. + * @param fallback Fallback value if the input is null. + * @return The parsed long based on the input string. + */ + public static long parseLong(String in, long fallback) { + if (in == null) { + return fallback; + } else if (in.equalsIgnoreCase("oo")) { + return Long.MAX_VALUE; + } else if (in.equalsIgnoreCase("-oo")) { + return Long.MIN_VALUE; + } else { + return Long.parseLong(in); + } + } + + /** + * @param in The input string. + * @return The parsed long based on the input string. + */ + public static long parseLong(String in) { + return parseLong(in, (long) 0); + } + public static double getRandom(double min, double max) { return new Random().nextInt((int) (max - min) + 1) + min; } @@ -141,4 +195,47 @@ public static boolean isNumber(String str) { return isDecimal(str) || isInfinity(str); } + /** + * Gets a vector based on coordinates from a given string. + * + * @param str The string. + * @return The vector. + */ + public static Vector getVector(@NonNull String str) { + double[] coordinates = parseCoordinates(str); + if (coordinates == null || coordinates.length != 3) { + return null; + } + return ImmutableVector.of(coordinates[0], coordinates[1], coordinates[2]); + } + + /** + * Gets a list of coordinates based on a string. + * + * @param str The string. + * @return The list of coordinates. + */ + public static double[] parseCoordinates(@NonNull String str) { + double[] coordinates; + + if (str.contains(",")) { + String[] rawCoords = str.split(","); + coordinates = new double[rawCoords.length]; + for (int i = 0; i < rawCoords.length; i++) { + if (!Numbers.isNumber(rawCoords[i].trim())) { + return null; + } + coordinates[i] = Numbers.parseDouble(rawCoords[i].trim()); + } + } else { + if (!Numbers.isDecimal(str.trim())) { + return null; + } + coordinates = new double[1]; + coordinates[0] = Numbers.parseDouble(str.trim()); + } + + return coordinates; + } + } diff --git a/src/main/java/in/twizmwaz/cardinal/util/Vectors.java b/src/main/java/in/twizmwaz/cardinal/util/Vectors.java deleted file mode 100644 index a1ea0ab..0000000 --- a/src/main/java/in/twizmwaz/cardinal/util/Vectors.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2016, Kevin Phoenix - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package in.twizmwaz.cardinal.util; - -import com.google.common.collect.Lists; -import in.twizmwaz.cardinal.module.region.Region; -import lombok.NonNull; -import org.bukkit.util.Vector; - -import java.util.List; -import java.util.stream.Collectors; - -public class Vectors { - - /** - * Gets a vector based on coordinates from a given string. - * - * @param str The string. - * @return The vector. - */ - public static Vector getVector(String str) { - List coordinates = getCoordinates(str); - if (coordinates == null || coordinates.size() != 3) { - return null; - } - return new Vector(coordinates.get(0), coordinates.get(1), coordinates.get(2)); - } - - /** - * Gets a list of coordinates based on a string. - * - * @param str The string. - * @return The list of coordinates. - */ - public static List getCoordinates(String str) { - List coordinates = Lists.newArrayList(); - - if (str.contains(",")) { - String[] rawCoords = str.split(","); - for (String coordinate : rawCoords) { - if (!Numbers.isNumber(coordinate.trim())) { - return null; - } - coordinates.add(Numbers.parseDouble(coordinate.trim())); - } - } else { - if (!Numbers.isDecimal(str.trim())) { - return null; - } - coordinates.add(Numbers.parseDouble(str.trim())); - } - - return coordinates; - } - - public static Vector min() { - return new Vector(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY); - } - - public static Vector max() { - return new Vector(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); - } - - /** - * Mirrors a vector across a normal from an origin. - * - * @param vector The original vector. - * @param origin The origin. - * @param normal The normal. - * @return The mirrored vector. - */ - public static Vector getMirroredVector(Vector vector, Vector origin, Vector normal) { - vector = vector.minus(origin); - vector = vector.minus(normal.times(vector.dot(normal)).times(2)).add(origin); - vector = new Vector(round(vector.getX()), round(vector.getY()), round(vector.getZ())); - return vector; - } - - public static double round(double d) { - return (double) Math.round(d * 10) / 10D; - } - - public static Vector getMinimumBound(@NonNull List regions) { - return getMinimum(regions.stream().map(region -> region.getBounds().getMin()).collect(Collectors.toList())); - } - - /** - * Gets the minimum vector from a list of vectors. - * - * @param vectors The list of vectors. - * @return The minimum vector. - */ - public static Vector getMinimum(@NonNull List vectors) { - if (vectors.size() == 0) { - throw new IllegalArgumentException("Cannot get maximum vector of no vectors"); - } - double x = vectors.get(0).getX(); - double y = vectors.get(0).getY(); - double z = vectors.get(0).getZ(); - for (int i = 1; i < vectors.size(); i++) { - if (vectors.get(i).getX() < x) { - x = vectors.get(i).getX(); - } - if (vectors.get(i).getY() < y) { - y = vectors.get(i).getY(); - } - if (vectors.get(i).getZ() < z) { - z = vectors.get(i).getZ(); - } - } - return new Vector(x, y, z); - } - - public static Vector getMaximumBound(@NonNull List regions) { - return getMaximum(regions.stream().map(region -> region.getBounds().getMax()).collect(Collectors.toList())); - } - - /** - * Gets the maximum vector from a list of vectors. - * - * @param vectors The list of vectors. - * @return The maximum vector. - */ - public static Vector getMaximum(@NonNull List vectors) { - if (vectors.size() == 0) { - throw new IllegalArgumentException("Cannot get maximum vector of no vectors"); - } - double x = vectors.get(0).getX(); - double y = vectors.get(0).getY(); - double z = vectors.get(0).getZ(); - for (int i = 1; i < vectors.size(); i++) { - if (vectors.get(i).getX() > x) { - x = vectors.get(i).getX(); - } - if (vectors.get(i).getY() > y) { - y = vectors.get(i).getY(); - } - if (vectors.get(i).getZ() > z) { - z = vectors.get(i).getZ(); - } - } - return new Vector(x, y, z); - } - - public static Vector alignToBlock(Vector vector) { - return new Vector(vector.getBlockX() + 0.5d, vector.getBlockY() + 0.5d, vector.getBlockZ() + 0.5d); - } - -}