001    package org.bukkit.util;
002    
003    import java.util.Map;
004    import org.bukkit.configuration.serialization.SerializableAs;
005    
006    /**
007     * A vector with a hash function that floors the X, Y, Z components, a la
008     * BlockVector in WorldEdit. BlockVectors can be used in hash sets and
009     * hash maps. Be aware that BlockVectors are mutable, but it is important
010     * that BlockVectors are never changed once put into a hash set or hash map.
011     */
012    @SerializableAs("BlockVector")
013    public class BlockVector extends Vector {
014    
015        /**
016         * Construct the vector with all components as 0.
017         */
018        public BlockVector() {
019            this.x = 0;
020            this.y = 0;
021            this.z = 0;
022        }
023    
024        /**
025         * Construct the vector with another vector.
026         *
027         * @param vec The other vector.
028         */
029        public BlockVector(Vector vec) {
030            this.x = vec.getX();
031            this.y = vec.getY();
032            this.z = vec.getZ();
033        }
034    
035        /**
036         * Construct the vector with provided integer components.
037         *
038         * @param x X component
039         * @param y Y component
040         * @param z Z component
041         */
042        public BlockVector(int x, int y, int z) {
043            this.x = x;
044            this.y = y;
045            this.z = z;
046        }
047    
048        /**
049         * Construct the vector with provided double components.
050         *
051         * @param x X component
052         * @param y Y component
053         * @param z Z component
054         */
055        public BlockVector(double x, double y, double z) {
056            this.x = x;
057            this.y = y;
058            this.z = z;
059        }
060    
061        /**
062         * Construct the vector with provided float components.
063         *
064         * @param x X component
065         * @param y Y component
066         * @param z Z component
067         */
068        public BlockVector(float x, float y, float z) {
069            this.x = x;
070            this.y = y;
071            this.z = z;
072        }
073    
074        /**
075         * Checks if another object is equivalent.
076         *
077         * @param obj The other object
078         * @return whether the other object is equivalent
079         */
080        @Override
081        public boolean equals(Object obj) {
082            if (!(obj instanceof BlockVector)) {
083                return false;
084            }
085            BlockVector other = (BlockVector) obj;
086    
087            return (int) other.getX() == (int) this.x && (int) other.getY() == (int) this.y && (int) other.getZ() == (int) this.z;
088    
089        }
090    
091        /**
092         * Returns a hash code for this vector.
093         *
094         * @return hash code
095         */
096        @Override
097        public int hashCode() {
098            return (Integer.valueOf((int) x).hashCode() >> 13) ^ (Integer.valueOf((int) y).hashCode() >> 7) ^ Integer.valueOf((int) z).hashCode();
099        }
100    
101        /**
102         * Get a new block vector.
103         *
104         * @return vector
105         */
106        @Override
107        public BlockVector clone() {
108            return (BlockVector) super.clone();
109        }
110    
111        public static BlockVector deserialize(Map<String, Object> args) {
112            double x = 0;
113            double y = 0;
114            double z = 0;
115    
116            if (args.containsKey("x")) {
117                x = (Double) args.get("x");
118            }
119            if (args.containsKey("y")) {
120                y = (Double) args.get("y");
121            }
122            if (args.containsKey("z")) {
123                z = (Double) args.get("z");
124            }
125    
126            return new BlockVector(x, y, z);
127        }
128    }