package com.supaham.commons.minecraft.world.space; import com.google.common.base.Preconditions; import javax.annotation.Nonnull; import pluginbase.config.annotation.SerializeWith; @SerializeWith(PositionSerializer.class) public class Position extends Vector { public static final Position ZERO = new Position(0, 0, 0, 0, 0); public static final Position ONE = new Position(1, 1, 1, 0, 0); protected float yaw; protected float pitch; public Position(double x, double y, double z) { super(x, y, z); } public Position(double x, double y, double z, float yaw, float pitch) { super(x, y, z); this.yaw = yaw; this.pitch = pitch; } public float getYaw() { return yaw; } public Position setYaw(float yaw) { return yaw == this.yaw ? this : new Position(x, y, z, yaw, pitch); } public float getPitch() { return pitch; } public Position setPitch(float pitch) { return pitch == this.pitch ? this : new Position(x, y, z, yaw, pitch); } /** * Creates a new {@link Vector} of this vector plus another {@link Vector}. If * the given vector is equals to {@link #ZERO} this same Point instance is returned. * * @param o the other vector to add * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position add(@Nonnull Vector o) { Preconditions.checkNotNull(o, "o cannot be null."); return ZERO.equals(o) ? this : new Position(this.x + o.x, this.y + o.y, this.z + o.z, this.yaw, this.pitch); } /** * Creates a new {@link Vector} of this vector plus the three given components. If * the given components are equal to 0 this same Point instance is returned. * * @param x how much to add on the x axis * @param y how much to add on the y axis * @param z how much to add on the z axis * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position add(double x, double y, double z) { return x == 0 && y == 0 && z == 0 ? this : new Position(this.x + x, this.y + y, this.z + z, this.yaw, this.pitch); } /** * Creates a new {@link Vector} of this vector plus the given int constant on all axes. * If the given constant is equal to 0, this same Point instance is returned. * * @param a constant to add to all three components * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position add(int a) { return a == 0 ? this : new Position(this.x + a, this.y + a, this.z + a, this.yaw, this.pitch); } /** * Creates a new {@link Vector} of this vector plus the given double constant on all * axes. If the given constant is equal to 0, this same Point instance is returned. * * @param a constant to add to all three components * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position add(double a) { return a == 0 ? this : new Position(this.x + a, this.y + a, this.z + a, this.yaw, this.pitch); } /** * Creates a new {@link Vector} of this vector plus the given float constant on all * axes. If the given constant is equal to 0, this same Point instance is returned. * * @param a constant to add to all three components * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position add(float a) { return a == 0 ? this : new Position(this.x + a, this.y + a, this.z + a, this.yaw, this.pitch); } /** * Creates a new {@link Vector} of this vector minus another {@link Vector}. If * the given vector is equals to {@link #ZERO} this same Point instance is returned. * * @param o the other vector to subtract * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position subtract(@Nonnull Vector o) { Preconditions.checkNotNull(o, "o cannot be null."); return ZERO.equals(o) ? this : new Position(this.x - o.x, this.y - o.y, this.z - o.z, this.yaw, this.pitch); } /** * Creates a new {@link Vector} of this vector minus the three given components. If * the given components are equal to 0 this same Point instance is returned. * * @param x how much to subtract on the x axis * @param y how much to subtract on the y axis * @param z how much to subtract on the z axis * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position subtract(double x, double y, double z) { return x == 0 && y == 0 && z == 0 ? this : new Position(this.x - x, this.y - y, this.z - z, this.yaw, this.pitch); } /** * Creates a new {@link Vector} of this vector minus the given int constant on all axes. * If the given constant is equal to 0, this same Point instance is returned. * * @param a constant to subtract from all three components * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position subtract(int a) { return a == 0 ? this : new Position(this.x - a, this.y - a, this.z - a, this.yaw, this.pitch); } /** * Creates a new {@link Vector} of this vector minus the given double constant on all * axes. If the given constant is equal to 0, this same Point instance is returned. * * @param a constant to subtract from all three components * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position subtract(double a) { return a == 0 ? this : new Position(this.x - a, this.y - a, this.z - a, this.yaw, this.pitch); } /** * Creates a new {@link Vector} of this vector minus the given float constant on all * axes. If the given constant is equal to 0, this same Point instance is returned. * * @param a constant to subtract from all three components * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position subtract(float a) { return a == 0 ? this : new Position(this.x - a, this.y - a, this.z - a, this.yaw, this.pitch); } /** * Creates a new {@link Vector} of this vector divided by another {@link * Vector}. If the given vector is equals to {@link #ONE} this same Point * instance is returned. * * @param o the other vector to divide by * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position divide(@Nonnull Vector o) { Preconditions.checkNotNull(o, "o cannot be null."); return ONE.equals(o) ? this : new Position(this.x / o.x, this.y / o.y, this.z / o.z, this.yaw, this.pitch); } /** * Creates a new {@link Vector} of this vector divided by the three given components. If * the given components are equal to 1 this same Point instance is returned. * * @param x how much to divide by on the x axis * @param y how much to divide by on the y axis * @param z how much to divide by on the z axis * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position divide(double x, double y, double z) { return x == 1 && y == 1 && z == 1 ? this : new Position(this.x / x, this.y / y, this.z / z, this.yaw, this.pitch); } /** * Creates a new {@link Vector} of this vector divided by the given int constant on all * axes. If the given constant is equal to 1, this same Point instance is returned. * * @param d constant to divide by for all three components * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position divide(int d) { return d == 1 ? this : new Position(this.x / d, this.y / d, this.z / d, this.yaw, this.pitch); } /** * Creates a new {@link Vector} of this vector divided by the given double constant on * all axes. If the given constant is equal to 1, this same Point instance is returned. * * @param d constant to divide by for all three components * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position divide(double d) { return d == 1 ? this : new Position(this.x / d, this.y / d, this.z / d, this.yaw, this.pitch); } /** * Creates a new {@link Vector} of this vector divided by the given float constant on * all axes. If the given constant is equal to 1, this same Point instance is returned. * * @param d constant to divide by for all three components * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position divide(float d) { return d == 1 ? this : new Position(this.x / d, this.y / d, this.z / d, this.yaw, this.pitch); } /** * Creates a new {@link Vector} of this vector multiplied by another {@link * Vector}. If the given vector is equals to {@link #ONE} this same Point * instance is returned. * * @param o the other vector to multiply by * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position multiply(@Nonnull Vector o) { Preconditions.checkNotNull(o, "o cannot be null."); return ONE.equals(o) ? this : new Position(this.x * o.x, this.y * o.y, this.z * o.z, this.yaw, this.pitch); } /** * Creates a new {@link Vector} of this vector multiplied by the three given components. * If the given components are equal to 1 this same Point instance is returned. * * @param x how much to multiply by on the x axis * @param y how much to multiply by on the y axis * @param z how much to multiply by on the z axis * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position multiply(double x, double y, double z) { return x == 1 && y == 1 && z == 1 ? this : new Position(this.x * x, this.y * y, this.z * z, this.yaw, this.pitch); } /** * Creates a new {@link Vector} of this vector multiplied by the given int constant on * all axes. If the given constant is equal to 1, this same Point instance is returned. * * @param m constant to multiply by for all three components * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position multiply(int m) { return m == 1 ? this : new Position(this.x * m, this.y * m, this.z * m, this.yaw, this.pitch); } /** * Creates a new {@link Vector} of this vector multiplied by the given double constant * on all axes. If the given constant is equal to 1, this same Point instance is * returned. * * @param m constant to multiply by for all three components * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position multiply(double m) { return m == 1 ? this : new Position(this.x * m, this.y * m, this.z * m, this.yaw, this.pitch); } /** * Returns a new {@link Vector} of this vector multiplied by the given float constant * on all axes. If the given constant is equal to 1, this same Point instance is * returned. * * @param m constant to multiply by for all three components * * @return a new {@link Vector} or the same instance if no modification was made */ @Nonnull public Position multiply(float m) { return m == 1 ? this : new Position(this.x * m, this.y * m, this.z * m, this.yaw, this.pitch); } /** * Returns a new {@link Vector} of the midpoint vector between this vector and another * {@link Vector}. If the given constant is {@link #equals(Object)} to the given vector * {@code o}, this same Point instance is returned. * * @param o the other vector * * @return a new {@link Vector} of the midpoint */ @Nonnull public Position midpoint(@Nonnull Vector o) { Preconditions.checkNotNull(o, "o cannot be null."); return equals(o) ? this : new Position((this.x + o.x) / 2.0D, (this.y + o.y) / 2.0D, (this.z + o.z) / 2.0D, this.yaw, this.pitch); } /** * Returns a new {@link Vector} of the cross product of this vector with another {@link * Vector}. The cross product is defined as: * <ul> * <li>x = y1 * z2 - y2 * z1 * <li>y = z1 * x2 - z2 * x1 * <li>z = x1 * y2 - x2 * y1 * </ul> * * @param o the other vector * * @return a new {@link Vector} of the cross product */ @Nonnull public Position crossProduct(@Nonnull Vector o) { Preconditions.checkNotNull(o, "o cannot be null."); return equals(o) ? this : new Position(this.y * o.z - o.y * this.z, this.z * o.x - o.z * this.x, this.x * o.y - o.x * this.y, this.yaw, this.pitch); } /** * Returns a new {@link Vector} of this vector to a unit vector (a vector with length * of 1). * * @return a new {@link Vector} of the unit vector */ @Nonnull public Position normalize() { return divide(length()); } /** * Returns a new {@link Position} with the three {@code x, y, z} components negated. Where a * {@code Position[-1,0,1,2,3].negate()} occurs, the returned position will be {@code Position[1,0,-1,2,3]}. * <p /> * <b>Note: The yaw and pitch are not affected by this operation.</b> This is done to ensure consistent behaviour * with all instances of {@link Vector}. * * @return negated position * @see #negate(boolean) */ @Override public Position negate() { return negate(false); } /** * Returns a new {@link Position} with the three {@code x, y, z} components negated. If {@code direction} is true, * the yaw and pitch will be negated as well. * <p /> * Where a {@code Position[-1,0,1,2,3].negate(false)} occurs, the returned position will be {@code * Position[1,0,-1,2,3]}. * <br /> * Where a {@code Position[-1,0,1,2,3].negate(true)} occurs, the returned position will be {@code * Position[1,0,-1,-2,-3]}. * * @param direction whether to negate the direction * * @return negated position * @see #negateDirection() */ public Position negate(boolean direction) { return new Position(x == 0 ? 0 : -x, y == 0 ? 0 : -y, z == 0 ? 0 : -z, yaw != 0 && direction ? -this.yaw : this.yaw, pitch != 0 && direction ? -this.pitch : this.pitch); } /** * Returns a new {@link Position} with the direction negated. * <p /> * Where a {@code Position[-1,0,1,2,3].negateDirection()} occurs, the returned position will be * {@code Position[1,0,-1,-2,-3]}. * * @return postion with negated direction */ public Position negateDirection() { return new Position(x, y, z, yaw == 0 ? 0 : -yaw, pitch == 0 ? 0 : -pitch); } @Nonnull public Position copy() { return new Position(x, y, z, yaw, pitch); } @Nonnull @Override public Position toPosition() { return super.toPosition(this.yaw, this.pitch); } @Nonnull @Override public MutablePosition toMutablePosition() { return super.toMutablePosition(this.yaw, this.pitch); } }