Fork of Poseidon providing Bukkit #1060 to older Beta versions (b1.0-b1.7.3)
at develop 462 lines 12 kB view raw
1package org.bukkit; 2 3import org.bukkit.block.Block; 4import org.bukkit.util.Vector; 5 6/** 7 * Represents a 3-dimensional position in a world 8 */ 9public class Location implements Cloneable { 10 private World world; 11 private double x; 12 private double y; 13 private double z; 14 private float pitch; 15 private float yaw; 16 17 /** 18 * Constructs a new Location with the given coordinates 19 * 20 * @param world The world in which this location resides 21 * @param x The x-coordinate of this new location 22 * @param y The y-coordinate of this new location 23 * @param z The z-coordinate of this new location 24 */ 25 public Location(final World world, final double x, final double y, final double z) { 26 this(world, x, y, z, 0, 0); 27 } 28 29 /** 30 * Constructs a new Location with the given coordinates and direction 31 * 32 * @param world The world in which this location resides 33 * @param x The x-coordinate of this new location 34 * @param y The y-coordinate of this new location 35 * @param z The z-coordinate of this new location 36 * @param yaw The absolute rotation on the x-plane, in degrees 37 * @param pitch The absolute rotation on the y-plane, in degrees 38 */ 39 public Location(final World world, final double x, final double y, final double z, final float yaw, final float pitch) { 40 this.world = world; 41 this.x = x; 42 this.y = y; 43 this.z = z; 44 this.pitch = pitch; 45 this.yaw = yaw; 46 } 47 48 /** 49 * Sets the world that this location resides in 50 * 51 * @param world New world that this location resides in 52 */ 53 public void setWorld(World world) { 54 this.world = world; 55 } 56 57 /** 58 * Gets the world that this location resides in 59 * 60 * @return World that contains this location 61 */ 62 public World getWorld() { 63 return world; 64 } 65 66 /** 67 * Gets the block at the represented location 68 * 69 * @return Block at the represented location 70 */ 71 public Block getBlock() { 72 return world.getBlockAt(this); 73 } 74 75 /** 76 * Sets the x-coordinate of this location 77 * 78 * @param x X-coordinate 79 */ 80 public void setX(double x) { 81 this.x = x; 82 } 83 84 /** 85 * Gets the x-coordinate of this location 86 * 87 * @return x-coordinate 88 */ 89 public double getX() { 90 return x; 91 } 92 93 /** 94 * Gets the floored value of the X component, indicating the block that 95 * this location is contained with. 96 * 97 * @return block X 98 */ 99 public int getBlockX() { 100 return locToBlock(x); 101 } 102 103 /** 104 * Sets the y-coordinate of this location 105 * 106 * @param y y-coordinate 107 */ 108 public void setY(double y) { 109 this.y = y; 110 } 111 112 /** 113 * Gets the y-coordinate of this location 114 * 115 * @return y-coordinate 116 */ 117 public double getY() { 118 return y; 119 } 120 121 /** 122 * Gets the floored value of the Y component, indicating the block that 123 * this location is contained with. 124 * 125 * @return block y 126 */ 127 public int getBlockY() { 128 return locToBlock(y); 129 } 130 131 /** 132 * Sets the z-coordinate of this location 133 * 134 * @param z z-coordinate 135 */ 136 public void setZ(double z) { 137 this.z = z; 138 } 139 140 /** 141 * Gets the z-coordinate of this location 142 * 143 * @return z-coordinate 144 */ 145 public double getZ() { 146 return z; 147 } 148 149 /** 150 * Gets the floored value of the Z component, indicating the block that 151 * this location is contained with. 152 * 153 * @return block z 154 */ 155 public int getBlockZ() { 156 return locToBlock(z); 157 } 158 159 /** 160 * Sets the yaw of this location 161 * 162 * @param yaw New yaw 163 */ 164 public void setYaw(float yaw) { 165 this.yaw = yaw; 166 } 167 168 /** 169 * Gets the yaw of this location 170 * 171 * @return Yaw 172 */ 173 public float getYaw() { 174 return yaw; 175 } 176 177 /** 178 * Sets the pitch of this location 179 * 180 * @param pitch New pitch 181 */ 182 public void setPitch(float pitch) { 183 this.pitch = pitch; 184 } 185 186 /** 187 * Gets the pitch of this location 188 * 189 * @return Pitch 190 */ 191 public float getPitch() { 192 return pitch; 193 } 194 195 /** 196 * Gets a Vector pointing in the direction that this Location is facing 197 * 198 * @return Vector 199 */ 200 public Vector getDirection() { 201 Vector vector = new Vector(); 202 203 double rotX = this.getYaw(); 204 double rotY = this.getPitch(); 205 206 vector.setY(-Math.sin(Math.toRadians(rotY))); 207 208 double h = Math.cos(Math.toRadians(rotY)); 209 210 vector.setX(-h * Math.sin(Math.toRadians(rotX))); 211 vector.setZ(h * Math.cos(Math.toRadians(rotX))); 212 213 return vector; 214 } 215 216 /** 217 * Adds the location by another. 218 * 219 * @param vec 220 * @return the same location 221 * @throws IllegalArgumentException for differing worlds 222 * @see Vector 223 */ 224 public Location add(Location vec) { 225 if (vec == null || vec.getWorld() != getWorld()) { 226 throw new IllegalArgumentException("Cannot add Locations of differing worlds"); 227 } 228 229 x += vec.x; 230 y += vec.y; 231 z += vec.z; 232 return this; 233 } 234 235 /** 236 * Adds the location by another. Not world-aware. 237 * 238 * @param x 239 * @param y 240 * @param z 241 * @return the same location 242 * @see Vector 243 */ 244 public Location add(double x, double y, double z) { 245 this.x += x; 246 this.y += y; 247 this.z += z; 248 return this; 249 } 250 251 /** 252 * Subtracts the location by another. 253 * 254 * @param vec 255 * @return the same location 256 * @throws IllegalArgumentException for differing worlds 257 * @see Vector 258 */ 259 public Location subtract(Location vec) { 260 if (vec == null || vec.getWorld() != getWorld()) { 261 throw new IllegalArgumentException("Cannot add Locations of differing worlds"); 262 } 263 264 x -= vec.x; 265 y -= vec.y; 266 z -= vec.z; 267 return this; 268 } 269 270 /** 271 * Subtracts the location by another. Not world-aware and 272 * orientation independent. 273 * 274 * @param x 275 * @param y 276 * @param z 277 * @return the same location 278 * @see Vector 279 */ 280 public Location subtract(double x, double y, double z) { 281 this.x -= x; 282 this.y -= y; 283 this.z -= z; 284 return this; 285 } 286 287 /** 288 * Gets the magnitude of the location, defined as sqrt(x^2+y^2+z^2). The value 289 * of this method is not cached and uses a costly square-root function, so 290 * do not repeatedly call this method to get the location's magnitude. NaN 291 * will be returned if the inner result of the sqrt() function overflows, 292 * which will be caused if the length is too long. Not world-aware and 293 * orientation independent. 294 * 295 * @return the magnitude 296 * @see Vector 297 */ 298 public double length() { 299 return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2)); 300 } 301 302 /** 303 * Gets the magnitude of the location squared. Not world-aware and 304 * orientation independent. 305 * 306 * @return the magnitude 307 * @see Vector 308 */ 309 public double lengthSquared() { 310 return Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2); 311 } 312 313 /** 314 * Get the distance between this location and another. The value 315 * of this method is not cached and uses a costly square-root function, so 316 * do not repeatedly call this method to get the location's magnitude. NaN 317 * will be returned if the inner result of the sqrt() function overflows, 318 * which will be caused if the distance is too long. 319 * 320 * @param o 321 * @return the distance 322 * @throws IllegalArgumentException for differing worlds 323 * @see Vector 324 */ 325 public double distance(Location o) { 326 if (o == null || o.getWorld() != getWorld()) { 327 throw new IllegalArgumentException("Cannot measure distance between worlds or to null"); 328 } 329 330 return Math.sqrt(Math.pow(x - o.x, 2) + Math.pow(y - o.y, 2) + Math.pow(z - o.z, 2)); 331 } 332 333 /** 334 * Get the squared distance between this location and another. 335 * 336 * @param o 337 * @return the distance 338 * @throws IllegalArgumentException for differing worlds 339 * @see Vector 340 */ 341 public double distanceSquared(Location o) { 342 if (o == null || o.getWorld() != getWorld()) { 343 throw new IllegalArgumentException("Cannot measure distance between worlds or to null"); 344 } 345 346 return Math.pow(x - o.x, 2) + Math.pow(y - o.y, 2) + Math.pow(z - o.z, 2); 347 } 348 349 /** 350 * Performs scalar multiplication, multiplying all components with a scalar. 351 * Not world-aware. 352 * 353 * @param m 354 * @return the same location 355 * @see Vector 356 */ 357 public Location multiply(double m) { 358 x *= m; 359 y *= m; 360 z *= m; 361 return this; 362 } 363 364 /** 365 * Zero this location's components. Not world-aware. 366 * 367 * @return the same location 368 * @see Vector 369 */ 370 public Location zero() { 371 x = 0; 372 y = 0; 373 z = 0; 374 return this; 375 } 376 377 @Override 378 public boolean equals(Object obj) { 379 if (obj == null) { 380 return false; 381 } 382 if (getClass() != obj.getClass()) { 383 return false; 384 } 385 final Location other = (Location) obj; 386 387 if (this.world != other.world && (this.world == null || !this.world.equals(other.world))) { 388 return false; 389 } 390 if (Double.doubleToLongBits(this.x) != Double.doubleToLongBits(other.x)) { 391 return false; 392 } 393 if (Double.doubleToLongBits(this.y) != Double.doubleToLongBits(other.y)) { 394 return false; 395 } 396 if (Double.doubleToLongBits(this.z) != Double.doubleToLongBits(other.z)) { 397 return false; 398 } 399 if (Float.floatToIntBits(this.pitch) != Float.floatToIntBits(other.pitch)) { 400 return false; 401 } 402 if (Float.floatToIntBits(this.yaw) != Float.floatToIntBits(other.yaw)) { 403 return false; 404 } 405 return true; 406 } 407 408 @Override 409 public int hashCode() { 410 int hash = 3; 411 412 hash = 19 * hash + (this.world != null ? this.world.hashCode() : 0); 413 hash = 19 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32)); 414 hash = 19 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32)); 415 hash = 19 * hash + (int) (Double.doubleToLongBits(this.z) ^ (Double.doubleToLongBits(this.z) >>> 32)); 416 hash = 19 * hash + Float.floatToIntBits(this.pitch); 417 hash = 19 * hash + Float.floatToIntBits(this.yaw); 418 return hash; 419 } 420 421 @Override 422 public String toString() { 423 return "Location{" + "world=" + world + "x=" + x + "y=" + y + "z=" + z + "pitch=" + pitch + "yaw=" + yaw + '}'; 424 } 425 426 /** 427 * Constructs a new {@link Vector} based on this Location 428 * 429 * @return New Vector containing the coordinates represented by this Location 430 */ 431 public Vector toVector() { 432 return new Vector(x, y, z); 433 } 434 435 @Override 436 public Location clone() { 437 try { 438 Location l = (Location) super.clone(); 439 440 l.world = world; 441 l.x = x; 442 l.y = y; 443 l.z = z; 444 l.yaw = yaw; 445 l.pitch = pitch; 446 return l; 447 } catch (CloneNotSupportedException e) { 448 e.printStackTrace(); 449 } 450 return null; 451 } 452 453 /** 454 * Safely converts a double (location coordinate) to an int (block coordinate) 455 * 456 * @param loc Precise coordinate 457 * @return Block coordinate 458 */ 459 public static int locToBlock(double loc) { 460 return (int) Math.floor(loc); 461 } 462}