package am2.api.math;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.MathHelper;
import net.minecraft.util.Vec3;
public class AMVector3
{
public float x;
public float y;
public float z;
public AMVector3(double x, double y, double z)
{
this.x = (float)x;
this.y = (float)y;
this.z = (float)z;
}
public AMVector3(TileEntity tile)
{
this.x = (tile.xCoord);
this.y = (tile.yCoord);
this.z = (tile.zCoord);
}
public AMVector3(Vec3 vec){
this.x = (float) vec.xCoord;
this.y = (float) vec.yCoord;
this.z = (float) vec.zCoord;
}
public AMVector3(AMVector3 a, AMVector3 b){
this.x = a.x - b.x; // Get the X value of our new vector
this.y = a.y - b.y; // Get the Y value of our new vector
this.z = a.z - b.z; // Get the Z value of our new vector
}
public AMVector3(Entity entity)
{
this(entity.posX, entity.posY, entity.posZ);
}
public AMVector3 add(AMVector3 vec)
{
this.x += vec.x;
this.y += vec.y;
this.z += vec.z;
return this;
}
public AMVector3 sub(AMVector3 vec)
{
this.x -= vec.x;
this.y -= vec.y;
this.z -= vec.z;
return this;
}
public AMVector3 scale(float scale)
{
this.x *= scale;
this.y *= scale;
this.z *= scale;
return this;
}
public AMVector3 scale(float scalex, float scaley, float scalez)
{
this.x *= scalex;
this.y *= scaley;
this.z *= scalez;
return this;
}
public AMVector3 modulo(float divisor){
this.x %= divisor;
this.y %= divisor;
this.z %= divisor;
return this;
}
public AMVector3 normalize()
{
float length = length();
this.x /= length;
this.y /= length;
this.z /= length;
return this;
}
public float length()
{
return (float)Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
}
public float lengthPow2()
{
return this.x * this.x + this.y * this.y + this.z * this.z;
}
public AMVector3 copy()
{
return new AMVector3(this.x, this.y, this.z);
}
public static AMVector3 crossProduct(AMVector3 vec1, AMVector3 vec2)
{
return new AMVector3(vec1.y * vec2.z - vec1.z * vec2.y, vec1.z * vec2.x - vec1.x * vec2.z, vec1.x * vec2.y - vec1.y * vec2.x);
}
public static AMVector3 xCrossProduct(AMVector3 vec)
{
return new AMVector3(0.0D, vec.z, -vec.y);
}
public static AMVector3 zCrossProduct(AMVector3 vec)
{
return new AMVector3(-vec.y, vec.x, 0.0D);
}
public static float dotProduct(AMVector3 vec1, AMVector3 vec2)
{
return (vec1.x * vec2.x) + (vec1.y * vec2.y) + (vec1.z * vec2.z);
}
public static float angle(AMVector3 vec1, AMVector3 vec2)
{
return anglePreNorm(vec1.copy().normalize(), vec2.copy().normalize());
}
public static float anglePreNorm(AMVector3 vec1, AMVector3 vec2)
{
return (float)Math.acos(dotProduct(vec1, vec2));
}
public static AMVector3 zero(){
return new AMVector3(0,0,0);
}
public AMVector3 rotate(float angle, AMVector3 axis)
{
return AMMatrix4.rotationMat(angle, axis).translate(this);
}
@Override
public String toString()
{
return "[" + this.x + "," + this.y + "," + this.z + "]";
}
public Vec3 toVec3D()
{
return Vec3.createVectorHelper(this.x, this.y, this.z);
}
public static AMVector3 getPerpendicular(AMVector3 vec)
{
if (vec.z == 0.0F) {
return zCrossProduct(vec);
}
return xCrossProduct(vec);
}
public boolean isZero()
{
return (this.x == 0.0F) && (this.y == 0.0F) && (this.z == 0.0F);
}
public boolean isWithinRange(float min, float max)
{
return (this.x >= min && x <= max) && (this.y >= min && this.y <= max) && (this.z >= min && this.z <= max);
}
public double distanceTo(AMVector3 target){
double var2 = target.x - this.x;
double var4 = target.y - this.y;
double var6 = target.z - this.z;
return MathHelper.sqrt_double(var2 * var2 + var4 * var4 + var6 * var6);
}
public double distanceSqTo(AMVector3 target){
double var2 = target.x - this.x;
double var4 = target.y - this.y;
double var6 = target.z - this.z;
return var2 * var2 + var4 * var4 + var6 * var6;
}
/**
* Rounds all values in this Vector to their integral floors
*/
public void floorToI(){
this.x = (float) Math.floor(this.x);
this.y = (float) Math.floor(this.y);
this.z = (float) Math.floor(this.z);
}
/**
* Rounds all values in this Vector to their integral logical roundings
*/
public void roundToI(){
this.x = Math.round(this.x);
this.y = Math.round(this.y);
this.z = Math.round(this.z);
}
/**
* Rounds all values in this Vector to their integral ceilings
*/
public void ceilToI(){
this.x = (float) Math.ceil(this.x);
this.y = (float) Math.ceil(this.y);
this.z = (float) Math.ceil(this.z);
}
/**
* Writes the vector3 to the specified compound - note that the way this function works, only one vector3 can be written to a compound at a time.
* Use sub-compounds if you need more!
*/
public void writeToNBT(NBTTagCompound compound){
compound.setFloat("Vec3_x", x);
compound.setFloat("Vec3_y", y);
compound.setFloat("Vec3_z", z);
}
public static AMVector3 readFromNBT(NBTTagCompound compound){
return new AMVector3(compound.getFloat("Vec3_x"), compound.getFloat("Vec3_y"), compound.getFloat("Vec3_z"));
}
@Override
public boolean equals(Object obj) {
if (obj instanceof AMVector3){
AMVector3 comp = (AMVector3) obj;
return (comp.x == this.x && comp.y == this.y && comp.z == this.z);
}
return false;
}
@Override
public int hashCode() {
return (int) (x + y + z);
}
}