org.marinemc.util.Location.java Source code

Java tutorial

Introduction

Here is the source code for org.marinemc.util.Location.java

Source

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// MarineStandalone is a minecraft server software and API.
// Copyright (C) MarineMC (marinemc.org)
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

package org.marinemc.util;

import org.json.simple.JSONAware;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.marinemc.server.Marine;
import org.marinemc.util.vectors.Vector3;
import org.marinemc.util.vectors.Vector3d;
import org.marinemc.world.World;
import org.marinemc.world.chunk.Chunk;

/**
 * Location class Used for precise positioning (entity location etc)
 *
 * @author Citymonstret
 * @author Fozie
 */
public class Location extends Vector3d implements JSONAware, Cloneable, Comparable<Location> { //

    protected World world;
    protected float yaw;
    protected float pitch;

    private boolean onGround;

    /**
     * Create a new world with default yaw and pitch (0, 0)
     *
     * @param world
     *            World
     * @param x
     *            X Coord
     * @param y
     *            Y Coord
     * @param z
     *            Z Coord
     */
    public Location(final World world, final double x, final double y, final double z) {
        this(world, x, y, z, 0f, 0f);
    }

    /**
     * Get a new location based on a world and a vector
     *
     * @param world
     *            World
     * @param v
     *            Vector3
     */
    @SuppressWarnings("rawtypes")
    public Location(final World world, final Vector3 v) {
        this(world, (double) v.getX(), (double) v.getY(), (double) v.getZ());
    }

    /**
     * Create a new location from a json string
     *
     * @param json
     *            JSON string
     */
    public Location(final String json) {
        super(0d, 0d, 0d);
        final JSONObject object = (JSONObject) JSONValue.parse(json);
        world = Marine.getWorld(object.get("world").toString());
        setX((double) object.get("x"));
        setY((double) object.get("y"));
        setZ((double) object.get("z"));
        yaw = (float) object.get("yaw");
        pitch = (float) object.get("pitch");
    }

    /**
     * Create a new location
     *
     * @param w
     *            World
     * @param x
     *            X Coord
     * @param y
     *            Y Coord
     * @param z
     *            Z Coord
     * @param yaw
     *            Yaw
     * @param pitch
     *            Pitch
     */
    public Location(final World w, final double x, final double y, final double z, final float yaw,
            final float pitch) {
        this(w, x, y, z, yaw, pitch, false);
    }

    public Location(final World world, final double x, final double y, final double z, final float yaw,
            final float pitch, final boolean onGround) {
        super(x, y, z);
        this.yaw = yaw;
        this.pitch = pitch;
        this.world = world;
        this.onGround = onGround;
    }

    /**
     * Create a new location
     *
     * @param spawnLocation
     *            Spawn position
     * @param w
     *            World
     */
    public Location(final Position spawnLocation, final World w) {
        this(w, spawnLocation.getX(), spawnLocation.getY(), spawnLocation.getZ());
    }

    /**
     * Get the world
     *
     * @return world
     */
    public World getWorld() {
        return world;
    }

    /**
     * Sets the world the location are in
     *
     * @param w
     *            World
     */
    public void setWorld(final World w) {
        world = w;
    }

    /**
     * Get the yaw
     *
     * @return yaw
     */
    public float getYaw() {
        return yaw;
    }

    /**
     * Set the yaw
     *
     * @param v
     *            new yaw
     */
    public void setYaw(final float v) {
        yaw = v;
    }

    /**
     * Get the relative position
     *
     * @return Position at rounded values
     */
    public Position getRelativePosition() {
        return new Position(getX().intValue(), getY().intValue(), getZ().intValue());
    }

    /**
     * Get the pitch
     *
     * @return pitch
     */
    public float getPitch() {
        return pitch;
    }

    /**
     * Set the pitch
     *
     * @param v
     *            new pitch
     */
    public void setPitch(final float v) {
        pitch = v;
    }

    /**
     * Face the yaw towards the specified location
     *
     * @param p
     *            Location too look towards
     * @return New Location (this)
     */
    public Location lookAt(final Location p) {
        final double l = p.getX() - getX();
        final double w = p.getZ() - getX();
        final double c = Math.sqrt(l * l + w * w);
        final double alpha1 = -Math.asin(l / c) / Math.PI * 180;
        final double alpha2 = Math.acos(w / c) / Math.PI * 180;
        yaw = (float) (alpha2 > 90 ? 180 - alpha1 : alpha1);
        return this;
    }

    @Override
    public String toJSONString() {
        final JSONObject o = new JSONObject();
        o.put("x", getX());
        o.put("y", getY());
        o.put("z", getZ());
        o.put("yaw", getYaw());
        o.put("pitch", getPitch());
        o.put("world", getWorld().getName());
        return o.toJSONString();
    }

    /**
     * Turn the location into a JSON Object <br>
     * Contains: x, y, z, yaw, pitch & world
     *
     * @return JSON Object
     */
    public org.json.JSONObject toJSONObject() {
        final org.json.JSONObject o = new org.json.JSONObject();
        try {
            o.put("x", getX());
            o.put("y", getY());
            o.put("z", getZ());
            o.put("yaw", getYaw());
            o.put("pitch", getPitch());
            o.put("world", getWorld().getName());
        } catch (final Exception e) {
            e.printStackTrace();
        }
        return o;
    }

    public JSONObject toSimpleJSONObject() {
        final JSONObject o = new JSONObject();
        try {
            o.put("x", getX());
            o.put("y", getY());
            o.put("z", getZ());
            o.put("yaw", getYaw());
            o.put("pitch", getPitch());
            o.put("world", getWorld().getName());
        } catch (final Exception e) {
            e.printStackTrace();
        }
        return o;
    }

    @Override
    public String toString() {
        return String.format("\"location\": {\"world\": \"%s\", \"x\": %f, \"y\": %f, \"z\": %f}",
                getWorld().getName(), getX(), getY(), getZ());
    }

    /**
     * Where the actual distance is important
     *
     * @param vector3d
     *            Other location
     * @return distance (actual)
     */
    public double getEuclideanDistance(final Vector3d vector3d) {
        double x = getX() - vector3d.getX();
        double y = getY() - vector3d.getY();
        double z = getZ() - vector3d.getZ();
        x *= x;
        y *= y;
        z *= z;
        return Math.sqrt(x + y + z);
    }

    /**
     * Where distance isn't really important, you just want to compare them
     *
     * @param l2
     *            Other location
     * @return distance squared
     */
    public double getEuclideanDistanceSquared(final Vector3d l2) {
        final double x = getX() - l2.getX(), y = getY() - l2.getY(), z = getZ() - l2.getZ();
        return x * x + y * y + z * z;
    }

    @Override
    public int hashCode() {
        int hash = 127;
        final int x = getX().intValue(), y = getY().intValue(), z = getZ().intValue();
        hash = hash * 31 + x;
        hash = hash * 31 + y;
        hash = hash * 31 + z;
        hash = (int) (hash * 31 + getYaw());
        hash = (int) (hash * 31 + getPitch());
        return hash * 31 + (world == null ? 127 : world.getName().hashCode());
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        Location object;
        try {
            object = (Location) super.clone();
        } catch (final Throwable e) {
            object = null;
        }
        if (object == null || !object.getX().equals(getX()) || !object.getY().equals(getY())
                || !object.getZ().equals(getZ()) || !getWorld().getName().equals(object.getWorld().getName()))
            return new Location(getWorld(), getX(), getY(), getZ(), getYaw(), getPitch());
        else
            return object;
    }

    /**
     * Is this on ground?
     *
     * @return Is this on ground?
     */
    public boolean isOnGround() {
        return onGround;
    }

    /**
     * Decide if this is on ground
     *
     * @param v
     *            On ground
     */
    public void setOnGround(final boolean v) {
        onGround = v;
    }

    /**
     * Check if the location is in a cube
     *
     * @param min
     *            Min Loc
     * @param max
     *            Max Loc
     * @return boolean
     */
    public boolean isInAABB(final Location min, final Location max) {
        return x >= min.x && x <= max.x && y >= min.y && y <= max.y && z >= max.z && z <= max.z;
    }

    /**
     * Check if the location is in the specified sphere
     *
     * @param origin
     *            Sphere origin
     * @param radius
     *            Sphere radius
     * @return boolean
     */
    public boolean isInSphere(final Location origin, final int radius) {
        return getEuclideanDistanceSquared(origin) < radius * radius;
    }

    /**
     * Get the chunk at this location
     *
     * @return chunk at the specified location
     */
    public Chunk getChunk() {
        return world.getChunkForce(x.intValue() >> 4, z.intValue() >> 4);
    }

    /**
     * Get an directional vector from this location
     * @return An directional Vector3d calculated out of the pitch and yaw
     */
    public Vector3d getDirectionVector() {
        return new Vector3d(-Math.cos(pitch) * Math.sin(yaw), -Math.sin(pitch), Math.cos(pitch) * Math.cos(yaw));
    }

    /**
     * Rotate the yaw to look at an X and Z cordinate
     * @param x The X to look at
     * @param z The Z to look at 
     */
    public void lookAt(double x, double z) {
        double l = this.x - x;
        double w = this.z - z;
        double c = Math.sqrt(l * l + w * w);

        if ((Math.asin(w / c) / Math.PI * 180) > 90)
            setYaw((float) (180 - (-Math.asin(l / c) / Math.PI * 180)));
        else
            setYaw((float) (-Math.asin(l / c) / Math.PI * 180));
    }

    @Override
    public boolean equals(Object l) {
        if (l instanceof Location) {
            final Location loc = (Location) l;
            return loc.getX().equals(getX()) && loc.getY().equals(getY()) && loc.getZ().equals(getZ())
                    && loc.getYaw() == getYaw() && loc.getPitch() == getPitch()
                    && loc.getWorld().getName().equals(getWorld().getName());

        } else if (l instanceof Vector3d) {
            final Vector3d v = (Vector3d) l;
            return v.x == this.x && v.y == this.y && v.z == this.z;
        } else
            return false;
    }

    @Override
    public int compareTo(final Location o) {
        if (o == null)
            throw new NullPointerException("Object specified was null");
        final double x1 = getX(), x2 = o.getX(), y1 = getY(), y2 = o.getY(), z1 = getZ(), z2 = o.getZ();
        if (x1 == x2 && y1 == y2 && z1 == z2)
            return 0;
        if (x1 < x2 && y1 < y2 && z1 < z2)
            return -1;
        return 1;
    }

    protected Location self() {
        return this;
    }

}