package com.asteria.game.location;
import com.asteria.utility.RandomGen;
/**
* The container class that represents a coordinate anywhere in the world.
*
* @author lare96 <http://github.com/lare96>
* @author blakeman8192
*/
public class Position {
/**
* The {@code X} coordinate.
*/
private int x;
/**
* The {@code Y} coordinate.
*/
private int y;
/**
* The {@code Z} coordinate.
*/
private int z;
/**
* Creates a new {@link Position}.
*
* @param x
* the {@code X} coordinate.
* @param y
* the {@code Y} coordinate.
* @param z
* the {@code Z} coordinate.
*/
public Position(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
/**
* Creates a new {@link Position} with the {@code Z} coordinate value as
* {@code 0}.
*
* @param x
* the {@code X} coordinate.
* @param y
* the {@code Y} coordinate.
*/
public Position(int x, int y) {
this(x, y, 0);
}
@Override
public String toString() {
return "POSITION[x= " + x + ", y= " + y + ", z= " + z + "]";
}
@Override
public final int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
result = prime * result + z;
return result;
}
@Override
public final boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Position))
return false;
Position other = (Position) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
if (z != other.z)
return false;
return true;
}
/**
* Returns the delta coordinates. Note that the returned position is not an
* actual position, instead it's values represent the delta values between
* the two arguments.
*
* @param a
* the first position.
* @param b
* the second position.
* @return the delta coordinates contained within a position.
*/
public static Position delta(Position a, Position b) {
return new Position(b.x - a.x, b.y - a.y);
}
/**
* A substitute for {@link Object#clone()} that creates another 'copy' of
* this instance. The created copy <i>safe</i> meaning it does not hold
* <b>any</b> references to the original instance.
*
* @return the copy of this instance that does not hold any references.
*/
public Position copy() {
return new Position(x, y, z);
}
/**
* Determines if this position is viewable from {@code other}.
*
* @param other
* the other position to determine if viewable from.
* @return {@code true} if this position is viewable, {@code false}
* otherwise.
*/
public final boolean isViewableFrom(Position other) {
if (this.getZ() != other.getZ())
return false;
Position p = Position.delta(this, other);
return p.x <= 14 && p.x >= -15 && p.y <= 14 && p.y >= -15;
}
/**
* Determines if this position is within {@code amount} distance of
* {@code other}.
*
* @param other
* the position to check the distance for.
* @param amount
* the distance to check.
* @return {@code true} if this position is within the distance,
* {@code false} otherwise.
*/
public final boolean withinDistance(Position other, int amount) {
if (this.z != other.z)
return false;
return Math.abs(other.x - this.x) <= amount && Math.abs(other.y - this.y) <= amount;
}
/**
* Increments the {@code X}, {@code Y}, and {@code Z} coordinate values
* within this container by {@code amountX}, {@code amountY}, and
* {@code amountZ}.
*
* @param amountX
* the amount to increment the {@code X} coordinate by.
* @param amountY
* the amount to increment the {@code Y} coordinate by.
* @param amountZ
* the amount to increment the {@code Z} coordinate by.
* @return an instance of this position.
*/
public final Position move(int amountX, int amountY, int amountZ) {
this.x += amountX;
this.y += amountY;
this.z += amountZ;
return this;
}
/**
* Increments the {@code X} and {@code Y} coordinate values within this
* container by {@code amountX} and {@code amountY}.
*
* @param amountX
* the amount to increment the {@code X} coordinate by.
* @param amountY
* the amount to increment the {@code Y} coordinate by.
* @return an instance of this position.
*/
public final Position move(int amountX, int amountY) {
return move(amountX, amountY, 0);
}
/**
* Increments the {@code X} and {@code Y} coordinate values within this
* container by random amounts positive and negative of {@code amount}.
*
* @return an instance of this position.
*/
public final Position random(int amount) {
RandomGen random = new RandomGen();
int x = random.inclusive(amount);
int y = random.inclusive(amount);
switch (random.inclusive(3)) {
case 1:
return move(-x, -y);
case 2:
return move(-x, y);
case 3:
return move(x, -y);
default:
return move(x, y);
}
}
/**
* Gets the {@code X} coordinate of the region containing this position.
*
* @return the {@code X} coordinate of the region.
*/
public final int getRegionX() {
return (x >> 3) - 6;
}
/**
* Gets the {@code Y} coordinate of the region containing this position.
*
* @return the {@code Y} coordinate of the region
*/
public final int getRegionY() {
return (y >> 3) - 6;
}
/**
* Gets the local {@code X} coordinate relative to {@code base}.
*
* @param base
* the relative base position.
* @return the local {@code X} coordinate.
*/
public final int getLocalX(Position base) {
return x - 8 * base.getRegionX();
}
/**
* Gets the local {@code Y} coordinate relative to {@code base}.
*
* @param base
* the relative base position.
* @return the local {@code Y} coordinate.
*/
public final int getLocalY(Position base) {
return y - 8 * base.getRegionY();
}
/**
* Gets the local {@code X} coordinate relative to this position.
*
* @return the local {@code X} coordinate.
*/
public final int getLocalX() {
return getLocalX(this);
}
/**
* Gets the local {@code Y} coordinate relative to this Position.
*
* @return the local {@code Y} coordinate.
*/
public final int getLocalY() {
return getLocalY(this);
}
/**
* Gets the {@code X} region chunk relative to this position.
*
* @return the {@code X} region chunk.
*/
public final int getChunkX() {
return (x >> 6);
}
/**
* Gets the {@code Y} region chunk relative to this position.
*
* @return the {@code Y} region chunk.
*/
public final int getChunkY() {
return (y >> 6);
}
/**
* Gets the region identification relative to this position.
*
* @return the region identification.
*/
public final int getRegion() {
return ((getChunkX() << 8) + getChunkY());
}
/**
* Gets the {@code X} coordinate.
*
* @return the {@code X} coordinate.
*/
public final int getX() {
return x;
}
/**
* Sets the {@code X} coordinate.
*
* @param x
* the new {@code X} coordinate.
*/
public final void setX(int x) {
this.x = x;
}
/**
* Gets the {@code Y} coordinate.
*
* @return the {@code Y} coordinate.
*/
public final int getY() {
return y;
}
/**
* Sets the {@code Y} coordinate.
*
* @param y
* the new {@code Y} coordinate.
*/
public final void setY(int y) {
this.y = y;
}
/**
* Gets the {@code Z} coordinate.
*
* @return the {@code Z} coordinate.
*/
public final int getZ() {
return z;
}
/**
* Sets the {@code Z} coordinate.
*
* @param z
* the new {@code Z} coordinate.
*/
public final void setZ(int z) {
this.z = z;
}
}