package net.knarcraft.stargate.utility; import org.bukkit.Location; import org.bukkit.block.BlockFace; import org.bukkit.util.Vector; /** * This class helps with direction-related calculations */ public final class DirectionHelper { private DirectionHelper() { } /** * Gets a yaw by comparing two locations * *
The yaw here is the direction an observer a the first location has to look to face the second location. * The yaw is only meant to be calculated for locations where both have either the same x value or the same z value. * Equal locations, or locations with equal x and equal z will throw an exception.
* * @param location1The first location, which works as the origin
* @param location2The second location, which the yaw will point towards
* @returnThe yaw pointing from the first location to the second location
*/ public static float getYawFromLocationDifference(Location location1, Location location2) { Location difference = location1.clone().subtract(location2.clone()); if (difference.getX() > 0) { return 90; } else if (difference.getX() < 0) { return 270; } else if (difference.getZ() > 0) { return 180; } else if (difference.getZ() < 0) { return 0; } throw new IllegalArgumentException("Locations given are equal or at the same x and y axis"); } /** * Gets a block face given a yaw value * *The supplied yaw must be a value such that (yaw mod 90) = 0. If not, an exception is thrown.
* * @param yawThe yaw value to convert
* @returnThe block face the yaw corresponds to
*/ public static BlockFace getBlockFaceFromYaw(double yaw) { //Make sure the yaw is between 0 and 360 yaw = normalizeYaw(yaw); if (yaw == 0) { return BlockFace.SOUTH; } else if (yaw == 90) { return BlockFace.WEST; } else if (yaw == 180) { return BlockFace.NORTH; } else if (yaw == 270) { return BlockFace.EAST; } else { throw new IllegalArgumentException("Invalid yaw given. Yaw must be divisible by 90."); } } /** * Gets a direction vector given a yaw * * @param yawThe yaw to convert to a direction vector
* @returnThe direction vector pointing in the same direction as the yaw
*/ public static Vector getDirectionVectorFromYaw(double yaw) { //Make sure the yaw is between 0 and 360 yaw = normalizeYaw(yaw); if (yaw == 0) { return new Vector(0, 0, 1); } else if (yaw == 90) { return new Vector(-1, 0, 0); } else if (yaw == 180) { return new Vector(0, 0, -1); } else if (yaw == 270) { return new Vector(1, 0, 0); } else { throw new IllegalArgumentException(String.format("Invalid yaw %f given", yaw)); } } /** * Moves a location by the given amounts * *The right, down and out work the same as for the relative block vector. Looking a the front of a portal, * right goes rightwards, down goes downwards and out goes towards the observer.
* * @param locationThe location to start at
* @param rightThe amount to go right
* @param downThe amount to go downward
* @param outThe amount to go outward
* @param yawThe yaw when looking directly outwards from a portal
* @returnA location relative to the given location
*/ public static Location moveLocation(Location location, double right, double down, double out, double yaw) { return location.add(getCoordinateVectorFromRelativeVector(right, down, out, yaw)); } /** * Gets a vector in Minecraft's normal X,Y,Z-space from a relative block vector * * @param rightThe amount of rightward steps from the top-left origin
* @param downThe amount of downward steps from the top-left origin
* @param outThe distance outward from the top-left origin
* @param yawThe yaw when looking directly outwards from a portal
* @returnA normal vector
*/ public static Vector getCoordinateVectorFromRelativeVector(double right, double down, double out, double yaw) { Vector distanceVector = DirectionHelper.getDirectionVectorFromYaw(yaw); distanceVector.multiply(out); Vector rightVector = DirectionHelper.getDirectionVectorFromYaw(yaw - 90); rightVector.multiply(right); Vector depthVector = new Vector(0, -1, 0); depthVector.multiply(down); return distanceVector.add(rightVector).add(depthVector); } /** * Normalizes a yaw to make it positive and no larger than 360 degrees * * @param yawThe yaw to normalize
* @returnThe normalized yaw
*/ private static double normalizeYaw(double yaw) { while (yaw < 0) { yaw += 360; } yaw = yaw % 360; return yaw; } }