001    import java.util.HashMap;
002    import java.util.Map;
003    
004    /**
005     * Block.java - Provides some way of making/editing blocks
006     * 
007     * @author James
008     */
009    public class Block {
010        /**
011         * Type - Used to identify blocks
012         */
013        public enum Type {
014            Air(0),
015            Stone(1),
016            Grass(2),
017            Dirt(3),
018            Cobblestone(4),
019            Wood(5),
020            Sapling(6),
021            Bedrock(7),
022            Water(8),
023            StationaryWater(9),
024            Lava(10),
025            StationaryLava(11),
026            Sand(12),
027            Gravel(13),
028            GoldOre(14),
029            IronOre(15),
030            CoalOre(16),
031            Log(17),
032            Leaves(18),
033            Sponge(19),
034            Glass(20),
035            Cloth(35),
036            YellowFlower(37),
037            RedRose(38),
038            BrownMushroom(39),
039            RedMushroom(40),
040            GoldBlock(41),
041            IronBlock(42),
042            DoubleStep(43),
043            Step(44),
044            Brick(45),
045            TNT(46),
046            BookShelf(47),
047            MossyCobblestone(48),
048            Obsidian(49),
049            Torch(50),
050            Fire(51),
051            MobSpawner(52),
052            WoodStairs(53),
053            Chest(54),
054            RedstoneWire(55),
055            DiamondOre(56),
056            Workbench(58),
057            Crops(59),
058            Soil(60),
059            Furnace(61),
060            BurningFurnace(62),
061            SignPost(63),
062            WoodDoor(64),
063            Ladder(65),
064            Rails(66),
065            CobblestoneStairs(67),
066            WallSign(68),
067            Lever(69),
068            StonePlate(70),
069            IronDoor(71),
070            WoodPlate(72),
071            RedstoneOre(73),
072            GlowingRedstoneOre(74),
073            RedstoneTorchOff(75),
074            RedstoneTorchOn(76),
075            StoneButton(77),
076            Snow(78),
077            Ice(79),
078            SnowBlock(80),
079            Cactus(81),
080            Clay(82),
081            Reed(83),
082            Jukebox(84),
083            Fence(85),
084            Pumpkin(86),
085            Netherstone(87),
086            SlowSand(88),
087            LightStone(89),
088            Portal(90),
089            JackOLantern(91)
090            ;
091    
092            private int id;
093            private static Map<Integer, Type> map;
094    
095            private Type(int id){
096                this.id = id;
097                add( id, this );
098            }
099    
100            private static void add( int type, Type name ) {
101                if (map == null) {
102                    map = new HashMap<Integer, Type>();
103                }
104    
105                map.put(type, name);
106            }
107    
108            public int getType() {
109                return id;
110            }
111    
112            public static Type fromId(final int type) {
113                return map.get(type);
114            }
115        }
116    
117        /**
118         * Face - Used for what face of the block was clicked
119         */
120        public enum Face {
121    
122            /**
123             * The top of the block
124             */
125            Top(1),
126            /**
127             * The bottom of the block
128             */
129            Bottom(0),
130            /**
131             * The left (Z-wise) of the block (Faces west)
132             */
133            Left(3),
134            /**
135             * The right (Z-wise) of the block (Faces east)
136             */
137            Right(2),
138            /**
139             * The front (X-wise) of the block (Faces south)
140             */
141            Front(5),
142            /**
143             * The back (X-wise) of the block (Faces north)
144             */
145            Back(4);
146            private final int id;
147    
148            private Face(int id) {
149                this.id = id;
150            }
151    
152            /**
153             * Returns a Face according to the specified ID
154             * 
155             * @param id
156             *            id of face
157             * @return face
158             */
159            public static Face fromId(final int id) {
160                for (Face e : Face.values()) {
161                    if (e.id == id) {
162                        return e;
163                    }
164                }
165                return null;
166            }
167        }
168        private int type, x, y, z;
169        private Face faceClicked;
170        public Type blockType;
171        private int status, data;
172    
173        /**
174         * Create a block with no type, x, y or z.
175         */
176        public Block() {
177        }
178    
179        /**
180         * Creates a block of specified type
181         * 
182         * @param type
183         */
184        public Block(int type) {
185            this.type = type;
186            this.blockType = Type.fromId(type);
187        }
188    
189        /**
190         * Creates a block of specified type and specified x, y and z
191         * 
192         * @param type
193         *            Type of block
194         * @param x
195         * @param y
196         * @param z
197         */
198        public Block(int type, int x, int y, int z) {
199            this.type = type;
200            this.blockType = Type.fromId(type);
201            this.x = x;
202            this.y = y;
203            this.z = z;
204        }
205    
206        /**
207         * Creates a block of specified type and specified x, y and z
208         * 
209         * @param type
210         *            Type of block
211         * @param x
212         * @param y
213         * @param z
214         * @param data
215         */
216        public Block(int type, int x, int y, int z, int data) {
217            this.type = type;
218            this.blockType = Type.fromId(type);
219            this.x = x;
220            this.y = y;
221            this.z = z;
222            this.data = data;
223        }
224    
225        /**
226         * Type of block
227         * 
228         * @return type
229         */
230        public int getType() {
231            return type;
232        }
233    
234        /**
235         * Set type of block
236         * 
237         * @param type
238         */
239        public void setType(int type) {
240            this.blockType = Type.fromId(type);
241            this.type = type;
242        }
243    
244        /**
245         * Gets X location
246         * 
247         * @return x
248         */
249        public int getX() {
250            return x;
251        }
252    
253        /**
254         * Sets X location
255         * 
256         * @param x
257         */
258        public void setX(int x) {
259            this.x = x;
260        }
261    
262        /**
263         * Gets Y location
264         * 
265         * @return y
266         */
267        public int getY() {
268            return y;
269        }
270    
271        /**
272         * Sets Y location
273         * 
274         * @param y
275         */
276        public void setY(int y) {
277            this.y = y;
278        }
279    
280        /**
281         * Gets Z location
282         * 
283         * @return z
284         */
285        public int getZ() {
286            return z;
287        }
288    
289        /**
290         * Sets Z location
291         * 
292         * @param z
293         */
294        public void setZ(int z) {
295            this.z = z;
296        }
297    
298        /**
299         * If this block was clicked, this will return the face that was clicked.
300         * 
301         * @return face clicked
302         */
303        public Face getFaceClicked() {
304            return faceClicked;
305        }
306    
307        /**
308         * Sets the face that was clicked
309         * 
310         * @param faceClicked
311         *            face clicked
312         */
313        public void setFaceClicked(Face faceClicked) {
314            this.faceClicked = faceClicked;
315        }
316    
317        /**
318         * Returns the destruction status of this block.
319         * 
320         * @return 0 = Started Digging, 1 = Digging, 2 = Stopped digging, 3 = Block
321         *         broken. Note: You have to return true for onBlockDestroy for all
322         *         of these (except 2) to prevent the block from being destroyed.
323         *         Returning false just on block broken will not work. Another note
324         *         is that 0 is called often, far less than 1 but is still called.
325         *         Good for toggling something.
326         */
327        public int getStatus() {
328            return status;
329        }
330    
331        /**
332         * Sets the current destruction status of this block.
333         * 
334         * @param status
335         */
336        public void setStatus(int status) {
337            this.status = status;
338        }
339    
340        /**
341         * Returns this block's data
342         * 
343         * @return
344         */
345        public int getData() {
346            return data;
347        }
348    
349        /**
350         * Sets this block's data
351         * 
352         * @param data
353         */
354        public void setData(int data) {
355            this.data = data;
356        }
357    
358        /**
359         * Updates this block to the server.
360         */
361        public void update() {
362            etc.getServer().setBlock(this);
363        }
364    
365        /**
366         * Returns the block at the given Face
367         * 
368         * @param face the block face of which to return
369         * @return Block at the specified Face
370         */
371        public Block getFace(Face face) {
372            if (face == null) return null;
373    
374            switch (face) {
375                case Front:
376                    return getRelative(1, 0, 0);
377                case Back:
378                    return getRelative(-1, 0, 0);
379                case Top:
380                    return getRelative(0, 1, 0);
381                case Bottom:
382                    return getRelative(0, -1, 0);
383                case Left:
384                    return getRelative(0, 0, 1);
385                case Right:
386                    return getRelative(0, 0, -1);
387            }
388    
389            return null;
390        }
391    
392        /**
393         * Synchronises this Block with the server, abandoning all local
394         * changes and refreshing the data with the current actual values
395         */
396        public void refresh() {
397            type = etc.getServer().getBlockIdAt(x, y, z);
398            data = etc.getServer().getBlockData(x, y, z);
399            status = 0;
400        }
401    
402        /**
403         * Finds a Block relative to this Block
404         * 
405         * @param x amount to shift the x coordinate
406         * @param y amount to shift the y coordinate
407         * @param z amount to shift the z coordinate
408         * 
409         * @return Block at the requested location
410         */
411        public Block getRelative(int x, int y, int z) {
412            return etc.getServer().getBlockAt(this.getX() + x, this.getY() + y, this.getZ() + z);
413        }
414    
415        /**
416         * Checks if this block is being powered through redstone
417         * 
418         * @return true if the block is being powered
419         */
420        public boolean isPowered() {
421            return etc.getServer().isBlockPowered(this);
422        }
423    
424        /**
425         * Checks if this block is being indirectly powered through redstone
426         *
427         * @return true if the block is being indirectly powered
428         */
429        public boolean isIndirectlyPowered() {
430            return etc.getServer().isBlockIndirectlyPowered(this);
431        }
432    
433        /**
434         * Returns a String value representing this Block
435         * 
436         * @return String representation of this block
437         */
438        @Override
439        public String toString() {
440            return String.format("Block[x=%d, y=%d, z=%d, type=%d]", x, y, z, type);
441        }
442    
443        /**
444         * Tests the given object to see if it equals this object
445         * 
446         * @param obj the object to test
447         * @return true if the two objects match
448         */
449        @Override
450        public boolean equals(Object obj) {
451            if (obj == null) {
452                return false;
453            }
454            if (getClass() != obj.getClass()) {
455                return false;
456            }
457            final Block other = (Block) obj;
458            if (this.x != other.x) {
459                return false;
460            }
461            if (this.y != other.y) {
462                return false;
463            }
464            if (this.z != other.z) {
465                return false;
466            }
467            return true;
468        }
469    
470        /**
471         * Returns a semi-unique hashcode for this block
472         * 
473         * @return hashcode
474         */
475        @Override
476        public int hashCode() {
477            int hash = 7;
478            hash = 97 * hash + this.x;
479            hash = 97 * hash + this.y;
480            hash = 97 * hash + this.z;
481            return hash;
482        }
483    
484    }