package net.knarcraft.stargate.utility; import org.bukkit.Location; import org.bukkit.block.BlockFace; import org.bukkit.util.Vector; /** * This class helps with direction-dependent 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 with equal x or equal z.

* * @param location1

The first location, which works as the origin

* @param location2

The second location, which the yaw will point at

* @return

The yaw

*/ 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 * * @param yaw

The yaw to use

* @return

The 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"); } } /** * Gets a direction vector given a yaw * * @param yaw

The yaw to use

* @return

The direction vector of 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 relatively * * @param location

The location to move

* @param right

The amount to go right (When looking at the front of a portal)

* @param depth

The amount to go downward (When looking at the front of a portal)

* @param distance

The amount to go outward (When looking a the front of a portal)

* @param yaw

The yaw when looking directly outwards from a portal

* @return

A location relative to the given location

*/ public static Location moveLocation(Location location, double right, double depth, double distance, double yaw) { return location.add(getCoordinateVectorFromRelativeVector(right, depth, distance, yaw)); } /** * Gets a vector in Minecraft's normal X,Y,Z-space from a relative block vector * * @param right

The amount of right steps from the top-left origin

* @param depth

The amount of downward steps from the top-left origin

* @param distance

The distance outward from the top-left origin

* @param yaw

The yaw when looking directly outwards from a portal

* @return

A normal vector

*/ public static Vector getCoordinateVectorFromRelativeVector(double right, double depth, double distance, double yaw) { Vector distanceVector = DirectionHelper.getDirectionVectorFromYaw(yaw); distanceVector.multiply(distance); Vector rightVector = DirectionHelper.getDirectionVectorFromYaw(yaw - 90); rightVector.multiply(right); Vector depthVector = new Vector(0, -1, 0); depthVector.multiply(depth); return distanceVector.add(rightVector).add(depthVector); } /** * Normalizes a yaw to make it positive and no larger than 360 degrees * * @param yaw

The yaw to normalize

* @return

The normalized yaw

*/ private static double normalizeYaw(double yaw) { while (yaw < 0) { yaw += 360; } yaw = yaw % 360; return yaw; } }