Only allow finite x,y,z and yaw,pitch values for Vector and Location

Many API methods rely on these to be finite (especially not NaN).

By: Jonas Konrad <me@yawk.at>
This commit is contained in:
Bukkit/Spigot 2014-12-27 16:48:21 +01:00
parent 1917305f97
commit 70bfc4d702
3 changed files with 110 additions and 115 deletions

View file

@ -42,12 +42,12 @@ public class Location implements Cloneable, ConfigurationSerializable {
* @param pitch The absolute rotation on the y-plane, in degrees * @param pitch The absolute rotation on the y-plane, in degrees
*/ */
public Location(final World world, final double x, final double y, final double z, final float yaw, final float pitch) { public Location(final World world, final double x, final double y, final double z, final float yaw, final float pitch) {
this.world = world; setWorld(world);
this.x = x; setX(x);
this.y = y; setY(y);
this.z = z; setZ(z);
this.pitch = pitch; setPitch(pitch);
this.yaw = yaw; setYaw(yaw);
} }
/** /**
@ -92,6 +92,7 @@ public class Location implements Cloneable, ConfigurationSerializable {
* @param x X-coordinate * @param x X-coordinate
*/ */
public void setX(double x) { public void setX(double x) {
checkFinite(x, "x must be finite");
this.x = x; this.x = x;
} }
@ -120,6 +121,7 @@ public class Location implements Cloneable, ConfigurationSerializable {
* @param y y-coordinate * @param y y-coordinate
*/ */
public void setY(double y) { public void setY(double y) {
checkFinite(y, "y must be finite");
this.y = y; this.y = y;
} }
@ -148,6 +150,7 @@ public class Location implements Cloneable, ConfigurationSerializable {
* @param z z-coordinate * @param z z-coordinate
*/ */
public void setZ(double z) { public void setZ(double z) {
checkFinite(z, "z must be finite");
this.z = z; this.z = z;
} }
@ -185,6 +188,7 @@ public class Location implements Cloneable, ConfigurationSerializable {
* @param yaw new rotation's yaw * @param yaw new rotation's yaw
*/ */
public void setYaw(float yaw) { public void setYaw(float yaw) {
checkFiniteFloat(yaw, "yaw must be finite");
this.yaw = yaw; this.yaw = yaw;
} }
@ -219,6 +223,7 @@ public class Location implements Cloneable, ConfigurationSerializable {
* @param pitch new incline's pitch * @param pitch new incline's pitch
*/ */
public void setPitch(float pitch) { public void setPitch(float pitch) {
checkFiniteFloat(pitch, "pitch must be finite");
this.pitch = pitch; this.pitch = pitch;
} }
@ -282,17 +287,17 @@ public class Location implements Cloneable, ConfigurationSerializable {
final double z = vector.getZ(); final double z = vector.getZ();
if (x == 0 && z == 0) { if (x == 0 && z == 0) {
pitch = vector.getY() > 0 ? -90 : 90; setPitch(vector.getY() > 0 ? -90 : 90);
return this; return this;
} }
double theta = Math.atan2(-x, z); double theta = Math.atan2(-x, z);
yaw = (float) Math.toDegrees((theta + _2PI) % _2PI); setYaw((float) Math.toDegrees((theta + _2PI) % _2PI));
double x2 = NumberConversions.square(x); double x2 = NumberConversions.square(x);
double z2 = NumberConversions.square(z); double z2 = NumberConversions.square(z);
double xz = Math.sqrt(x2 + z2); double xz = Math.sqrt(x2 + z2);
pitch = (float) Math.toDegrees(Math.atan(-vector.getY() / xz)); setPitch((float) Math.toDegrees(Math.atan(-vector.getY() / xz)));
return this; return this;
} }
@ -310,9 +315,9 @@ public class Location implements Cloneable, ConfigurationSerializable {
throw new IllegalArgumentException("Cannot add Locations of differing worlds"); throw new IllegalArgumentException("Cannot add Locations of differing worlds");
} }
x += vec.x; setX(getX() + vec.getX());
y += vec.y; setY(getY() + vec.getY());
z += vec.z; setZ(getZ() + vec.getZ());
return this; return this;
} }
@ -324,9 +329,9 @@ public class Location implements Cloneable, ConfigurationSerializable {
* @return the same location * @return the same location
*/ */
public Location add(Vector vec) { public Location add(Vector vec) {
this.x += vec.getX(); setX(getX() + vec.getX());
this.y += vec.getY(); setY(getY() + vec.getY());
this.z += vec.getZ(); setZ(getZ() + vec.getZ());
return this; return this;
} }
@ -340,9 +345,9 @@ public class Location implements Cloneable, ConfigurationSerializable {
* @return the same location * @return the same location
*/ */
public Location add(double x, double y, double z) { public Location add(double x, double y, double z) {
this.x += x; setX(getX() + x);
this.y += y; setY(getY() + y);
this.z += z; setZ(getZ() + z);
return this; return this;
} }
@ -359,9 +364,9 @@ public class Location implements Cloneable, ConfigurationSerializable {
throw new IllegalArgumentException("Cannot add Locations of differing worlds"); throw new IllegalArgumentException("Cannot add Locations of differing worlds");
} }
x -= vec.x; setX(getX() - vec.getX());
y -= vec.y; setY(getY() - vec.getY());
z -= vec.z; setZ(getZ() - vec.getZ());
return this; return this;
} }
@ -373,9 +378,9 @@ public class Location implements Cloneable, ConfigurationSerializable {
* @return the same location * @return the same location
*/ */
public Location subtract(Vector vec) { public Location subtract(Vector vec) {
this.x -= vec.getX(); setX(getX() - vec.getX());
this.y -= vec.getY(); setY(getY() - vec.getY());
this.z -= vec.getZ(); setZ(getZ() - vec.getZ());
return this; return this;
} }
@ -390,9 +395,9 @@ public class Location implements Cloneable, ConfigurationSerializable {
* @return the same location * @return the same location
*/ */
public Location subtract(double x, double y, double z) { public Location subtract(double x, double y, double z) {
this.x -= x; setX(getX() - x);
this.y -= y; setY(getY() - y);
this.z -= z; setZ(getZ() - z);
return this; return this;
} }
@ -467,9 +472,9 @@ public class Location implements Cloneable, ConfigurationSerializable {
* @return the same location * @return the same location
*/ */
public Location multiply(double m) { public Location multiply(double m) {
x *= m; setX(getX() * m);
y *= m; setY(getY() * m);
z *= m; setZ(getZ() * m);
return this; return this;
} }
@ -480,9 +485,9 @@ public class Location implements Cloneable, ConfigurationSerializable {
* @return the same location * @return the same location
*/ */
public Location zero() { public Location zero() {
x = 0; setX(0D);
y = 0; setY(0D);
z = 0; setZ(0D);
return this; return this;
} }
@ -596,4 +601,16 @@ public class Location implements Cloneable, ConfigurationSerializable {
return new Location(world, NumberConversions.toDouble(args.get("x")), NumberConversions.toDouble(args.get("y")), NumberConversions.toDouble(args.get("z")), NumberConversions.toFloat(args.get("yaw")), NumberConversions.toFloat(args.get("pitch"))); return new Location(world, NumberConversions.toDouble(args.get("x")), NumberConversions.toDouble(args.get("y")), NumberConversions.toDouble(args.get("z")), NumberConversions.toFloat(args.get("yaw")), NumberConversions.toFloat(args.get("pitch")));
} }
private static void checkFinite(double d, String message) {
if (Double.isNaN(d) || Double.isInfinite(d)) {
throw new IllegalArgumentException(message);
}
}
private static void checkFiniteFloat(float d, String message) {
if (Float.isNaN(d) || Float.isInfinite(d)) {
throw new IllegalArgumentException(message);
}
}
} }

View file

@ -16,9 +16,7 @@ public class BlockVector extends Vector {
* Construct the vector with all components as 0. * Construct the vector with all components as 0.
*/ */
public BlockVector() { public BlockVector() {
this.x = 0; super();
this.y = 0;
this.z = 0;
} }
/** /**
@ -27,9 +25,7 @@ public class BlockVector extends Vector {
* @param vec The other vector. * @param vec The other vector.
*/ */
public BlockVector(Vector vec) { public BlockVector(Vector vec) {
this.x = vec.getX(); this(vec.getX(), vec.getY(), vec.getZ());
this.y = vec.getY();
this.z = vec.getZ();
} }
/** /**
@ -40,9 +36,7 @@ public class BlockVector extends Vector {
* @param z Z component * @param z Z component
*/ */
public BlockVector(int x, int y, int z) { public BlockVector(int x, int y, int z) {
this.x = x; super(x, y, z);
this.y = y;
this.z = z;
} }
/** /**
@ -53,9 +47,7 @@ public class BlockVector extends Vector {
* @param z Z component * @param z Z component
*/ */
public BlockVector(double x, double y, double z) { public BlockVector(double x, double y, double z) {
this.x = x; super(x, y, z);
this.y = y;
this.z = z;
} }
/** /**
@ -66,9 +58,7 @@ public class BlockVector extends Vector {
* @param z Z component * @param z Z component
*/ */
public BlockVector(float x, float y, float z) { public BlockVector(float x, float y, float z) {
this.x = x; super(x, y, z);
this.y = y;
this.z = z;
} }
/** /**

View file

@ -33,9 +33,7 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* Construct the vector with all components as 0. * Construct the vector with all components as 0.
*/ */
public Vector() { public Vector() {
this.x = 0; this(0, 0, 0);
this.y = 0;
this.z = 0;
} }
/** /**
@ -46,9 +44,7 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @param z Z component * @param z Z component
*/ */
public Vector(int x, int y, int z) { public Vector(int x, int y, int z) {
this.x = x; this((double) x, (double) y, (double) z);
this.y = y;
this.z = z;
} }
/** /**
@ -59,9 +55,10 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @param z Z component * @param z Z component
*/ */
public Vector(double x, double y, double z) { public Vector(double x, double y, double z) {
this.x = x; // use setters for range checks
this.y = y; setX(x);
this.z = z; setY(y);
setZ(z);
} }
/** /**
@ -72,9 +69,7 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @param z Z component * @param z Z component
*/ */
public Vector(float x, float y, float z) { public Vector(float x, float y, float z) {
this.x = x; this((double) x, (double) y, (double) z);
this.y = y;
this.z = z;
} }
/** /**
@ -84,9 +79,9 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return the same vector * @return the same vector
*/ */
public Vector add(Vector vec) { public Vector add(Vector vec) {
x += vec.x; setX(getX() + vec.getX());
y += vec.y; setY(getY() + vec.getY());
z += vec.z; setZ(getZ() + vec.getZ());
return this; return this;
} }
@ -97,9 +92,9 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return the same vector * @return the same vector
*/ */
public Vector subtract(Vector vec) { public Vector subtract(Vector vec) {
x -= vec.x; setX(getX() - vec.getX());
y -= vec.y; setY(getY() - vec.getY());
z -= vec.z; setZ(getZ() - vec.getZ());
return this; return this;
} }
@ -110,9 +105,9 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return the same vector * @return the same vector
*/ */
public Vector multiply(Vector vec) { public Vector multiply(Vector vec) {
x *= vec.x; setX(getX() * vec.getX());
y *= vec.y; setY(getY() * vec.getY());
z *= vec.z; setZ(getZ() * vec.getZ());
return this; return this;
} }
@ -123,9 +118,9 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return the same vector * @return the same vector
*/ */
public Vector divide(Vector vec) { public Vector divide(Vector vec) {
x /= vec.x; setX(getX() / vec.getX());
y /= vec.y; setY(getY() / vec.getY());
z /= vec.z; setZ(getZ() / vec.getZ());
return this; return this;
} }
@ -136,9 +131,9 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return the same vector * @return the same vector
*/ */
public Vector copy(Vector vec) { public Vector copy(Vector vec) {
x = vec.x; setX(vec.getX());
y = vec.y; setY(vec.getY());
z = vec.z; setZ(vec.getZ());
return this; return this;
} }
@ -207,9 +202,9 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return this same vector (now a midpoint) * @return this same vector (now a midpoint)
*/ */
public Vector midpoint(Vector other) { public Vector midpoint(Vector other) {
x = (x + other.x) / 2; setX((getX() + other.getX()) / 2);
y = (y + other.y) / 2; setY((getY() + other.getY()) / 2);
z = (z + other.z) / 2; setZ((getZ() + other.getZ()) / 2);
return this; return this;
} }
@ -234,10 +229,7 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return the same vector * @return the same vector
*/ */
public Vector multiply(int m) { public Vector multiply(int m) {
x *= m; return multiply((double) m);
y *= m;
z *= m;
return this;
} }
/** /**
@ -248,9 +240,9 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return the same vector * @return the same vector
*/ */
public Vector multiply(double m) { public Vector multiply(double m) {
x *= m; setX(getX() * m);
y *= m; setY(getY() * m);
z *= m; setZ(getZ() * m);
return this; return this;
} }
@ -262,10 +254,7 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return the same vector * @return the same vector
*/ */
public Vector multiply(float m) { public Vector multiply(float m) {
x *= m; return multiply((double) m);
y *= m;
z *= m;
return this;
} }
/** /**
@ -292,13 +281,13 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return the same vector * @return the same vector
*/ */
public Vector crossProduct(Vector o) { public Vector crossProduct(Vector o) {
double newX = y * o.z - o.y * z; double newX = getY() * o.getZ() - o.getY() * getZ();
double newY = z * o.x - o.z * x; double newY = getZ() * o.getX() - o.getZ() * getX();
double newZ = x * o.y - o.x * y; double newZ = getX() * o.getY() - o.getX() * getY();
x = newX; setX(newX);
y = newY; setY(newY);
z = newZ; setZ(newZ);
return this; return this;
} }
@ -310,11 +299,7 @@ public class Vector implements Cloneable, ConfigurationSerializable {
public Vector normalize() { public Vector normalize() {
double length = length(); double length = length();
x /= length; return multiply(1 / length);
y /= length;
z /= length;
return this;
} }
/** /**
@ -323,9 +308,9 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return the same vector * @return the same vector
*/ */
public Vector zero() { public Vector zero() {
x = 0; setX(0D);
y = 0; setY(0D);
z = 0; setZ(0D);
return this; return this;
} }
@ -418,8 +403,7 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return This vector. * @return This vector.
*/ */
public Vector setX(int x) { public Vector setX(int x) {
this.x = x; return setX((double) x);
return this;
} }
/** /**
@ -429,6 +413,7 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return This vector. * @return This vector.
*/ */
public Vector setX(double x) { public Vector setX(double x) {
checkFinite(x, "x must be finite");
this.x = x; this.x = x;
return this; return this;
} }
@ -440,8 +425,7 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return This vector. * @return This vector.
*/ */
public Vector setX(float x) { public Vector setX(float x) {
this.x = x; return setX((double) x);
return this;
} }
/** /**
@ -451,8 +435,7 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return This vector. * @return This vector.
*/ */
public Vector setY(int y) { public Vector setY(int y) {
this.y = y; return setY((double) y);
return this;
} }
/** /**
@ -462,6 +445,7 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return This vector. * @return This vector.
*/ */
public Vector setY(double y) { public Vector setY(double y) {
checkFinite(y, "y must be finite");
this.y = y; this.y = y;
return this; return this;
} }
@ -473,8 +457,7 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return This vector. * @return This vector.
*/ */
public Vector setY(float y) { public Vector setY(float y) {
this.y = y; return setY((double) y);
return this;
} }
/** /**
@ -484,8 +467,7 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return This vector. * @return This vector.
*/ */
public Vector setZ(int z) { public Vector setZ(int z) {
this.z = z; return setZ((double) z);
return this;
} }
/** /**
@ -495,6 +477,7 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return This vector. * @return This vector.
*/ */
public Vector setZ(double z) { public Vector setZ(double z) {
checkFinite(z, "z must be finite");
this.z = z; this.z = z;
return this; return this;
} }
@ -506,8 +489,7 @@ public class Vector implements Cloneable, ConfigurationSerializable {
* @return This vector. * @return This vector.
*/ */
public Vector setZ(float z) { public Vector setZ(float z) {
this.z = z; return setZ((double) z);
return this;
} }
/** /**
@ -664,4 +646,10 @@ public class Vector implements Cloneable, ConfigurationSerializable {
return new Vector(x, y, z); return new Vector(x, y, z);
} }
private static void checkFinite(double d, String message) {
if (Double.isNaN(d) || Double.isInfinite(d)) {
throw new IllegalArgumentException(message);
}
}
} }