Bukkit-API  1.7.9-R0.2
The inofficial Bukkit-API
Location.java
1 package org.bukkit;
2 
3 import org.bukkit.block.Block;
5 import org.bukkit.util.Vector;
6 
7 /**
8  * Represents a 3-dimensional position in a world
9  */
10 public class Location implements Cloneable {
11  private World world;
12  private double x;
13  private double y;
14  private double z;
15  private float pitch;
16  private float yaw;
17 
18  /**
19  * Constructs a new Location with the given coordinates
20  *
21  * @param world The world in which this location resides
22  * @param x The x-coordinate of this new location
23  * @param y The y-coordinate of this new location
24  * @param z The z-coordinate of this new location
25  */
26  public Location(final World world, final double x, final double y, final double z) {
27  this(world, x, y, z, 0, 0);
28  }
29 
30  /**
31  * Constructs a new Location with the given coordinates and direction
32  *
33  * @param world The world in which this location resides
34  * @param x The x-coordinate of this new location
35  * @param y The y-coordinate of this new location
36  * @param z The z-coordinate of this new location
37  * @param yaw The absolute rotation on the x-plane, in degrees
38  * @param pitch The absolute rotation on the y-plane, in degrees
39  */
40  public Location(final World world, final double x, final double y, final double z, final float yaw, final float pitch) {
41  this.world = world;
42  this.x = x;
43  this.y = y;
44  this.z = z;
45  this.pitch = pitch;
46  this.yaw = yaw;
47  }
48 
49  /**
50  * Sets the world that this location resides in
51  *
52  * @param world New world that this location resides in
53  */
54  public void setWorld(World world) {
55  this.world = world;
56  }
57 
58  /**
59  * Gets the world that this location resides in
60  *
61  * @return World that contains this location
62  */
63  public World getWorld() {
64  return world;
65  }
66 
67  /**
68  * Gets the chunk at the represented location
69  *
70  * @return Chunk at the represented location
71  */
72  public Chunk getChunk() {
73  return world.getChunkAt(this);
74  }
75 
76  /**
77  * Gets the block at the represented location
78  *
79  * @return Block at the represented location
80  */
81  public Block getBlock() {
82  return world.getBlockAt(this);
83  }
84 
85  /**
86  * Sets the x-coordinate of this location
87  *
88  * @param x X-coordinate
89  */
90  public void setX(double x) {
91  this.x = x;
92  }
93 
94  /**
95  * Gets the x-coordinate of this location
96  *
97  * @return x-coordinate
98  */
99  public double getX() {
100  return x;
101  }
102 
103  /**
104  * Gets the floored value of the X component, indicating the block that
105  * this location is contained with.
106  *
107  * @return block X
108  */
109  public int getBlockX() {
110  return locToBlock(x);
111  }
112 
113  /**
114  * Sets the y-coordinate of this location
115  *
116  * @param y y-coordinate
117  */
118  public void setY(double y) {
119  this.y = y;
120  }
121 
122  /**
123  * Gets the y-coordinate of this location
124  *
125  * @return y-coordinate
126  */
127  public double getY() {
128  return y;
129  }
130 
131  /**
132  * Gets the floored value of the Y component, indicating the block that
133  * this location is contained with.
134  *
135  * @return block y
136  */
137  public int getBlockY() {
138  return locToBlock(y);
139  }
140 
141  /**
142  * Sets the z-coordinate of this location
143  *
144  * @param z z-coordinate
145  */
146  public void setZ(double z) {
147  this.z = z;
148  }
149 
150  /**
151  * Gets the z-coordinate of this location
152  *
153  * @return z-coordinate
154  */
155  public double getZ() {
156  return z;
157  }
158 
159  /**
160  * Gets the floored value of the Z component, indicating the block that
161  * this location is contained with.
162  *
163  * @return block z
164  */
165  public int getBlockZ() {
166  return locToBlock(z);
167  }
168 
169  /**
170  * Sets the yaw of this location, measured in degrees.
171  * <ul>
172  * <li>A yaw of 0 or 360 represents the positive z direction.
173  * <li>A yaw of 180 represents the negative z direction.
174  * <li>A yaw of 90 represents the negative x direction.
175  * <li>A yaw of 270 represents the positive x direction.
176  * </ul>
177  * Increasing yaw values are the equivalent of turning to your
178  * right-facing, increasing the scale of the next respective axis, and
179  * decreasing the scale of the previous axis.
180  *
181  * @param yaw new rotation's yaw
182  */
183  public void setYaw(float yaw) {
184  this.yaw = yaw;
185  }
186 
187  /**
188  * Gets the yaw of this location, measured in degrees.
189  * <ul>
190  * <li>A yaw of 0 or 360 represents the positive z direction.
191  * <li>A yaw of 180 represents the negative z direction.
192  * <li>A yaw of 90 represents the negative x direction.
193  * <li>A yaw of 270 represents the positive x direction.
194  * </ul>
195  * Increasing yaw values are the equivalent of turning to your
196  * right-facing, increasing the scale of the next respective axis, and
197  * decreasing the scale of the previous axis.
198  *
199  * @return the rotation's yaw
200  */
201  public float getYaw() {
202  return yaw;
203  }
204 
205  /**
206  * Sets the pitch of this location, measured in degrees.
207  * <ul>
208  * <li>A pitch of 0 represents level forward facing.
209  * <li>A pitch of 90 represents downward facing, or negative y
210  * direction.
211  * <li>A pitch of -90 represents upward facing, or positive y direction.
212  * <ul>
213  * Increasing pitch values the equivalent of looking down.
214  *
215  * @param pitch new incline's pitch
216  */
217  public void setPitch(float pitch) {
218  this.pitch = pitch;
219  }
220 
221  /**
222  * Sets the pitch of this location, measured in degrees.
223  * <ul>
224  * <li>A pitch of 0 represents level forward facing.
225  * <li>A pitch of 90 represents downward facing, or negative y
226  * direction.
227  * <li>A pitch of -90 represents upward facing, or positive y direction.
228  * <ul>
229  * Increasing pitch values the equivalent of looking down.
230  *
231  * @return the incline's pitch
232  */
233  public float getPitch() {
234  return pitch;
235  }
236 
237  /**
238  * Gets a unit-vector pointing in the direction that this Location is
239  * facing.
240  *
241  * @return a vector pointing the direction of this location's {@link
242  * #getPitch() pitch} and {@link #getYaw() yaw}
243  */
244  public Vector getDirection() {
245  Vector vector = new Vector();
246 
247  double rotX = this.getYaw();
248  double rotY = this.getPitch();
249 
250  vector.setY(-Math.sin(Math.toRadians(rotY)));
251 
252  double xz = Math.cos(Math.toRadians(rotY));
253 
254  vector.setX(-xz * Math.sin(Math.toRadians(rotX)));
255  vector.setZ(xz * Math.cos(Math.toRadians(rotX)));
256 
257  return vector;
258  }
259 
260  /**
261  * Sets the {@link #getYaw() yaw} and {@link #getPitch() pitch} to point
262  * in the direction of the vector.
263  */
264  public Location setDirection(Vector vector) {
265  /*
266  * Sin = Opp / Hyp
267  * Cos = Adj / Hyp
268  * Tan = Opp / Adj
269  *
270  * x = -Opp
271  * z = Adj
272  */
273  final double _2PI = 2 * Math.PI;
274  final double x = vector.getX();
275  final double z = vector.getZ();
276 
277  if (x == 0 && z == 0) {
278  pitch = vector.getY() > 0 ? -90 : 90;
279  return this;
280  }
281 
282  double theta = Math.atan2(-x, z);
283  yaw = (float) Math.toDegrees((theta + _2PI) % _2PI);
284 
285  double x2 = NumberConversions.square(x);
286  double z2 = NumberConversions.square(z);
287  double xz = Math.sqrt(x2 + z2);
288  pitch = (float) Math.toDegrees(Math.atan(-vector.getY() / xz));
289 
290  return this;
291  }
292 
293  /**
294  * Adds the location by another.
295  *
296  * @see Vector
297  * @param vec The other location
298  * @return the same location
299  * @throws IllegalArgumentException for differing worlds
300  */
301  public Location add(Location vec) {
302  if (vec == null || vec.getWorld() != getWorld()) {
303  throw new IllegalArgumentException("Cannot add Locations of differing worlds");
304  }
305 
306  x += vec.x;
307  y += vec.y;
308  z += vec.z;
309  return this;
310  }
311 
312  /**
313  * Adds the location by a vector.
314  *
315  * @see Vector
316  * @param vec Vector to use
317  * @return the same location
318  */
319  public Location add(Vector vec) {
320  this.x += vec.getX();
321  this.y += vec.getY();
322  this.z += vec.getZ();
323  return this;
324  }
325 
326  /**
327  * Adds the location by another. Not world-aware.
328  *
329  * @see Vector
330  * @param x X coordinate
331  * @param y Y coordinate
332  * @param z Z coordinate
333  * @return the same location
334  */
335  public Location add(double x, double y, double z) {
336  this.x += x;
337  this.y += y;
338  this.z += z;
339  return this;
340  }
341 
342  /**
343  * Subtracts the location by another.
344  *
345  * @see Vector
346  * @param vec The other location
347  * @return the same location
348  * @throws IllegalArgumentException for differing worlds
349  */
350  public Location subtract(Location vec) {
351  if (vec == null || vec.getWorld() != getWorld()) {
352  throw new IllegalArgumentException("Cannot add Locations of differing worlds");
353  }
354 
355  x -= vec.x;
356  y -= vec.y;
357  z -= vec.z;
358  return this;
359  }
360 
361  /**
362  * Subtracts the location by a vector.
363  *
364  * @see Vector
365  * @param vec The vector to use
366  * @return the same location
367  */
368  public Location subtract(Vector vec) {
369  this.x -= vec.getX();
370  this.y -= vec.getY();
371  this.z -= vec.getZ();
372  return this;
373  }
374 
375  /**
376  * Subtracts the location by another. Not world-aware and
377  * orientation independent.
378  *
379  * @see Vector
380  * @param x X coordinate
381  * @param y Y coordinate
382  * @param z Z coordinate
383  * @return the same location
384  */
385  public Location subtract(double x, double y, double z) {
386  this.x -= x;
387  this.y -= y;
388  this.z -= z;
389  return this;
390  }
391 
392  /**
393  * Gets the magnitude of the location, defined as sqrt(x^2+y^2+z^2). The
394  * value of this method is not cached and uses a costly square-root
395  * function, so do not repeatedly call this method to get the location's
396  * magnitude. NaN will be returned if the inner result of the sqrt()
397  * function overflows, which will be caused if the length is too long. Not
398  * world-aware and orientation independent.
399  *
400  * @see Vector
401  * @return the magnitude
402  */
403  public double length() {
404  return Math.sqrt(NumberConversions.square(x) + NumberConversions.square(y) + NumberConversions.square(z));
405  }
406 
407  /**
408  * Gets the magnitude of the location squared. Not world-aware and
409  * orientation independent.
410  *
411  * @see Vector
412  * @return the magnitude
413  */
414  public double lengthSquared() {
415  return NumberConversions.square(x) + NumberConversions.square(y) + NumberConversions.square(z);
416  }
417 
418  /**
419  * Get the distance between this location and another. The value of this
420  * method is not cached and uses a costly square-root function, so do not
421  * repeatedly call this method to get the location's magnitude. NaN will
422  * be returned if the inner result of the sqrt() function overflows, which
423  * will be caused if the distance is too long.
424  *
425  * @see Vector
426  * @param o The other location
427  * @return the distance
428  * @throws IllegalArgumentException for differing worlds
429  */
430  public double distance(Location o) {
431  return Math.sqrt(distanceSquared(o));
432  }
433 
434  /**
435  * Get the squared distance between this location and another.
436  *
437  * @see Vector
438  * @param o The other location
439  * @return the distance
440  * @throws IllegalArgumentException for differing worlds
441  */
442  public double distanceSquared(Location o) {
443  if (o == null) {
444  throw new IllegalArgumentException("Cannot measure distance to a null location");
445  } else if (o.getWorld() == null || getWorld() == null) {
446  throw new IllegalArgumentException("Cannot measure distance to a null world");
447  } else if (o.getWorld() != getWorld()) {
448  throw new IllegalArgumentException("Cannot measure distance between " + getWorld().getName() + " and " + o.getWorld().getName());
449  }
450 
451  return NumberConversions.square(x - o.x) + NumberConversions.square(y - o.y) + NumberConversions.square(z - o.z);
452  }
453 
454  /**
455  * Performs scalar multiplication, multiplying all components with a
456  * scalar. Not world-aware.
457  *
458  * @param m The factor
459  * @see Vector
460  * @return the same location
461  */
462  public Location multiply(double m) {
463  x *= m;
464  y *= m;
465  z *= m;
466  return this;
467  }
468 
469  /**
470  * Zero this location's components. Not world-aware.
471  *
472  * @see Vector
473  * @return the same location
474  */
475  public Location zero() {
476  x = 0;
477  y = 0;
478  z = 0;
479  return this;
480  }
481 
482  @Override
483  public boolean equals(Object obj) {
484  if (obj == null) {
485  return false;
486  }
487  if (getClass() != obj.getClass()) {
488  return false;
489  }
490  final Location other = (Location) obj;
491 
492  if (this.world != other.world && (this.world == null || !this.world.equals(other.world))) {
493  return false;
494  }
495  if (Double.doubleToLongBits(this.x) != Double.doubleToLongBits(other.x)) {
496  return false;
497  }
498  if (Double.doubleToLongBits(this.y) != Double.doubleToLongBits(other.y)) {
499  return false;
500  }
501  if (Double.doubleToLongBits(this.z) != Double.doubleToLongBits(other.z)) {
502  return false;
503  }
504  if (Float.floatToIntBits(this.pitch) != Float.floatToIntBits(other.pitch)) {
505  return false;
506  }
507  if (Float.floatToIntBits(this.yaw) != Float.floatToIntBits(other.yaw)) {
508  return false;
509  }
510  return true;
511  }
512 
513  @Override
514  public int hashCode() {
515  int hash = 3;
516 
517  hash = 19 * hash + (this.world != null ? this.world.hashCode() : 0);
518  hash = 19 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32));
519  hash = 19 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32));
520  hash = 19 * hash + (int) (Double.doubleToLongBits(this.z) ^ (Double.doubleToLongBits(this.z) >>> 32));
521  hash = 19 * hash + Float.floatToIntBits(this.pitch);
522  hash = 19 * hash + Float.floatToIntBits(this.yaw);
523  return hash;
524  }
525 
526  @Override
527  public String toString() {
528  return "Location{" + "world=" + world + ",x=" + x + ",y=" + y + ",z=" + z + ",pitch=" + pitch + ",yaw=" + yaw + '}';
529  }
530 
531  /**
532  * Constructs a new {@link Vector} based on this Location
533  *
534  * @return New Vector containing the coordinates represented by this
535  * Location
536  */
537  public Vector toVector() {
538  return new Vector(x, y, z);
539  }
540 
541  @Override
542  public Location clone() {
543  try {
544  return (Location) super.clone();
545  } catch (CloneNotSupportedException e) {
546  throw new Error(e);
547  }
548  }
549 
550  /**
551  * Safely converts a double (location coordinate) to an int (block
552  * coordinate)
553  *
554  * @param loc Precise coordinate
555  * @return Block coordinate
556  */
557  public static int locToBlock(double loc) {
558  return NumberConversions.floor(loc);
559  }
560 }
Location(final World world, final double x, final double y, final double z)
Definition: Location.java:26
Location(final World world, final double x, final double y, final double z, final float yaw, final float pitch)
Definition: Location.java:40
void setX(double x)
Definition: Location.java:90
Location setDirection(Vector vector)
Definition: Location.java:264
Location multiply(double m)
Definition: Location.java:462
Block getBlockAt(int x, int y, int z)
void setPitch(float pitch)
Definition: Location.java:217
Location add(Location vec)
Definition: Location.java:301
Chunk getChunkAt(int x, int z)
double distanceSquared(Location o)
Definition: Location.java:442
Vector getDirection()
Definition: Location.java:244
void setYaw(float yaw)
Definition: Location.java:183
Location subtract(Vector vec)
Definition: Location.java:368
Vector setX(int x)
Definition: Vector.java:420
Location add(Vector vec)
Definition: Location.java:319
Vector setY(int y)
Definition: Vector.java:453
String getName()
double lengthSquared()
Definition: Location.java:414
Vector setZ(int z)
Definition: Vector.java:486
static int locToBlock(double loc)
Definition: Location.java:557
void setY(double y)
Definition: Location.java:118
double distance(Location o)
Definition: Location.java:430
void setWorld(World world)
Definition: Location.java:54
Location subtract(Location vec)
Definition: Location.java:350
void setZ(double z)
Definition: Location.java:146
Location add(double x, double y, double z)
Definition: Location.java:335
Location subtract(double x, double y, double z)
Definition: Location.java:385