From 0d665744071072e805e95b3d48be7a11921e797e Mon Sep 17 00:00:00 2001
From: ryanbennitt <ryanbennitt@googlemail.com>
Date: Sun, 3 Jan 2016 18:05:29 +0000
Subject: [PATCH] Fixed door direction mask


diff --git a/src/main/java/org/bukkit/material/Door.java b/src/main/java/org/bukkit/material/Door.java
index 27bb681..9c7f7f0 100644
--- a/src/main/java/org/bukkit/material/Door.java
+++ b/src/main/java/org/bukkit/material/Door.java
@@ -1,6 +1,7 @@
 package org.bukkit.material;
 
 import org.bukkit.Material;
+import org.bukkit.TreeSpecies;
 import org.bukkit.block.BlockFace;
 
 /**
@@ -9,6 +10,14 @@ import org.bukkit.block.BlockFace;
  * This class was previously deprecated, but has been retrofitted to
  * work with modern doors. Some methods are undefined dependant on <code>isTopHalf()</code>
  * due to Minecraft's internal representation of doors.
+ *
+ * @see Material.WOODEN_DOOR
+ * @see Material.IRON_DOOR_BLOCK
+ * @see Material.SPRUCE_DOOR
+ * @see Material.BIRCH_DOOR
+ * @see Material.JUNGLE_DOOR
+ * @see Material.ACACIA_DOOR
+ * @see Material.DARK_OAK_DOOR
  */
 public class Door extends MaterialData implements Directional, Openable {
 
@@ -37,6 +46,123 @@ public class Door extends MaterialData implements Directional, Openable {
     }
 
     /**
+     * Constructs the bottom half of a door of the given material type, facing the specified direction and set to closed
+     *
+     * @param type The type of material this door is made of. This must match the type of the block above.
+     * @param face The direction the door is facing.
+     *
+     * @see Material.WOODEN_DOOR
+     * @see Material.IRON_DOOR_BLOCK
+     * @see Material.SPRUCE_DOOR
+     * @see Material.BIRCH_DOOR
+     * @see Material.JUNGLE_DOOR
+     * @see Material.ACACIA_DOOR
+     * @see Material.DARK_OAK_DOOR
+     *
+     * @see BlockFace.WEST
+     * @see BlockFace.NORTH
+     * @see BlockFace.EAST
+     * @see BlockFace.SOUTH
+     */
+    public Door(final Material type, BlockFace face) {
+        this(type,face,false);
+    }
+
+    /**
+     * Constructs the bottom half of a door of the given material type, facing the specified direction and set to open or closed
+     *
+     * @param type The type of material this door is made of. This must match the type of the block above.
+     * @param face The direction the door is facing.
+     * @param isOpen Whether the door is currently opened.
+     *
+     * @see Material.WOODEN_DOOR
+     * @see Material.IRON_DOOR_BLOCK
+     * @see Material.SPRUCE_DOOR
+     * @see Material.BIRCH_DOOR
+     * @see Material.JUNGLE_DOOR
+     * @see Material.ACACIA_DOOR
+     * @see Material.DARK_OAK_DOOR
+     *
+     * @see BlockFace.WEST
+     * @see BlockFace.NORTH
+     * @see BlockFace.EAST
+     * @see BlockFace.SOUTH
+     */
+    public Door(final Material type, BlockFace face, boolean isOpen) {
+        super(type);
+        setTopHalf(false);
+        setFacingDirection(face);
+        setOpen(isOpen);
+    }
+
+    /**
+     * Constructs the top half of door of the given material type and with the hinge on the left or right
+     * 
+     * @param type The type of material this door is made of. This must match the type of the block below.
+     * @param isHingeRight True if the hinge is on the right hand side, false if the hinge is on the left hand side.
+     *
+     * @see Material.WOODEN_DOOR
+     * @see Material.IRON_DOOR_BLOCK
+     * @see Material.SPRUCE_DOOR
+     * @see Material.BIRCH_DOOR
+     * @see Material.JUNGLE_DOOR
+     * @see Material.ACACIA_DOOR
+     * @see Material.DARK_OAK_DOOR
+     */
+    public Door(final Material type, boolean isHingeRight) {
+        super(type);
+        setTopHalf(true);
+        setHinge(isHingeRight);
+    }
+
+    /**
+     * Constructs the bottom half of a wooden door of the given species, facing the specified direction and set to closed
+     *
+     * @param species The species this wooden door is made of. This must match the species of the block above.
+     * @param face The direction the door is facing.
+     *
+     * @see TreeSpecies
+     *
+     * @see BlockFace.WEST
+     * @see BlockFace.NORTH
+     * @see BlockFace.EAST
+     * @see BlockFace.SOUTH
+     */
+    public Door(final TreeSpecies species, BlockFace face) {
+        this(getWoodDoorOfSpecies(species),face,false);
+    }
+
+    /**
+     * Constructs the bottom half of a wooden door of the given species, facing the specified direction and set to open or closed
+     *
+     * @param species The species this wooden door is made of. This must match the species of the block above.
+     * @param face The direction the door is facing.
+     * @param isOpen Whether the door is currently opened.
+     *
+     * @see TreeSpecies
+     *
+     * @see BlockFace.WEST
+     * @see BlockFace.NORTH
+     * @see BlockFace.EAST
+     * @see BlockFace.SOUTH
+     */
+    public Door(final TreeSpecies species, BlockFace face, boolean isOpen) {
+        this(getWoodDoorOfSpecies(species),face,isOpen);
+    }
+
+    /**
+     * Constructs the top half of a wooden door of the given species and with the hinge on the left or right
+     * 
+     * @param species The species this wooden door is made of. This must match the species of the block below.
+     * @param isHingeRight True if the hinge is on the right hand side, false if the hinge is on the left hand side.
+     *
+     * @see TreeSpecies
+     */
+    public Door(final TreeSpecies species, boolean isHingeRight) {
+        this(getWoodDoorOfSpecies(species),isHingeRight);
+    }
+
+    /**
      * @param type the raw type id
      * @param data the raw data value
      * @deprecated Magic value
@@ -57,8 +183,42 @@ public class Door extends MaterialData implements Directional, Openable {
     }
 
     /**
+     * Returns the item type of a wooden door for the given tree species.
+     *
+     * @param species The species of wood door required.
+     * @return The item type for the given species.
+     *
+     * @see Material.WOODEN_DOOR
+     * @see Material.SPRUCE_DOOR
+     * @see Material.BIRCH_DOOR
+     * @see Material.JUNGLE_DOOR
+     * @see Material.ACACIA_DOOR
+     * @see Material.DARK_OAK_DOOR
+     */
+    public static Material getWoodDoorOfSpecies(TreeSpecies species)
+    {
+        switch(species)
+        {
+        default:
+        case GENERIC:
+            return Material.WOODEN_DOOR;
+        case BIRCH:
+            return Material.BIRCH_DOOR;
+        case REDWOOD:
+            return Material.SPRUCE_DOOR;
+        case JUNGLE:
+            return Material.JUNGLE_DOOR;
+        case ACACIA:
+            return Material.ACACIA_DOOR;
+        case DARK_OAK:
+            return Material.DARK_OAK_DOOR;
+        }
+    }
+
+    /**
      * Result is undefined if <code>isTopHalf()</code> is true.
      */
+    @SuppressWarnings("deprecation")
     public boolean isOpen() {
         return ((getData() & 0x4) == 0x4);
     }
@@ -66,6 +226,7 @@ public class Door extends MaterialData implements Directional, Openable {
     /**
      * Set whether the door is open. Undefined if <code>isTopHalf()</code> is true.
      */
+    @SuppressWarnings("deprecation")
     public void setOpen(boolean isOpen) {
         setData((byte) (isOpen ? (getData() | 0x4) : (getData() & ~0x4)));
     }
@@ -73,6 +234,7 @@ public class Door extends MaterialData implements Directional, Openable {
     /**
      * @return whether this is the top half of the door
      */
+    @SuppressWarnings("deprecation")
     public boolean isTopHalf() {
         return ((getData() & 0x8) == 0x8);
     }
@@ -82,6 +244,7 @@ public class Door extends MaterialData implements Directional, Openable {
      *
      * @param isTopHalf True to make it the top half.
      */
+    @SuppressWarnings("deprecation")
     public void setTopHalf(boolean isTopHalf) {
         setData((byte) (isTopHalf ? (getData() | 0x8) : (getData() & ~0x8)));
     }
@@ -107,8 +270,9 @@ public class Door extends MaterialData implements Directional, Openable {
      *
      * @param face the direction
      */
+    @SuppressWarnings("deprecation")
     public void setFacingDirection(BlockFace face) {
-        byte data = (byte) (getData() & 0x12);
+        byte data = (byte) (getData() & 0xC);
         switch (face) {
         case WEST:
             data |= 0x0;
@@ -125,6 +289,9 @@ public class Door extends MaterialData implements Directional, Openable {
         case SOUTH:
             data |= 0x3;
             break;
+
+        default:
+            break;
         }
         setData(data);
     }
@@ -136,6 +303,7 @@ public class Door extends MaterialData implements Directional, Openable {
      *
      * @return the direction
      */
+    @SuppressWarnings("deprecation")
     public BlockFace getFacing() {
         byte data = (byte) (getData() & 0x3);
         switch (data) {
@@ -161,6 +329,7 @@ public class Door extends MaterialData implements Directional, Openable {
      *
      * @return false for left hinge, true for right hinge
      */
+    @SuppressWarnings("deprecation")
     public boolean getHinge() {
         return (getData() & 0x1) == 1;
     }
@@ -169,9 +338,12 @@ public class Door extends MaterialData implements Directional, Openable {
      * Set whether the hinge is on the left or right side. Left is false, right is true.
      *
      * Undefined if <code>isTopHalf()</code> is false.
+     *
+     * @param isHingeRight True if the hinge is on the right hand side, false if the hinge is on the left hand side.
      */
-    public void setHinge(boolean hinge) {
-        setData((byte) (hinge ? (getData() | 0x1) : (getData() & ~0x1)));
+    @SuppressWarnings("deprecation")
+    public void setHinge(boolean isHingeRight) {
+        setData((byte) (isHingeRight ? (getData() | 0x1) : (getData() & ~0x1)));
     }
 
     @Override
diff --git a/src/test/java/org/bukkit/materials/MaterialDataTest.java b/src/test/java/org/bukkit/materials/MaterialDataTest.java
index 00e6f63..99270ce 100644
--- a/src/test/java/org/bukkit/materials/MaterialDataTest.java
+++ b/src/test/java/org/bukkit/materials/MaterialDataTest.java
@@ -6,6 +6,7 @@ import static org.junit.Assert.assertThat;
 import org.bukkit.Material;
 import org.bukkit.TreeSpecies;
 import org.bukkit.block.BlockFace;
+import org.bukkit.material.Door;
 import org.bukkit.material.Leaves;
 import org.bukkit.material.Tree;
 import org.bukkit.material.Wood;
@@ -172,4 +173,53 @@ public class MaterialDataTest {
             }
         }
     }
+    
+    @Test
+    public void testDoor()
+    {
+        @SuppressWarnings("deprecation")
+        Door door = new Door();
+        assertThat("Constructed with default door type",door.getItemType(),equalTo(Material.WOODEN_DOOR));
+        assertThat("Constructed with default top or bottom",door.isTopHalf(),equalTo(false));
+        assertThat("Constructed with default direction",door.getFacing(),equalTo(BlockFace.WEST));
+        assertThat("Constructed with default open state",door.isOpen(),equalTo(false));
+        
+        Material[] types = new Material[] { Material.WOODEN_DOOR,
+                Material.IRON_DOOR_BLOCK, Material.SPRUCE_DOOR,
+                Material.BIRCH_DOOR, Material.JUNGLE_DOOR,
+                Material.ACACIA_DOOR, Material.DARK_OAK_DOOR };
+        BlockFace[] directions = new BlockFace[] { BlockFace.WEST, BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH };
+        boolean[] openStates = new boolean[] {false, true};
+        boolean[] hingeStates = new boolean[] {false, true};
+        for(Material type : types)
+        {
+            // Test bottom half
+            for(BlockFace facing : directions)
+            {
+                door = new Door(type,facing);
+                assertThat("Constructed with correct door type",door.getItemType(),equalTo(type));
+                assertThat("Constructed with default top or bottom",door.isTopHalf(),equalTo(false));
+                assertThat("Constructed with correct direction",door.getFacing(),equalTo(facing));
+                assertThat("Constructed with default open state",door.isOpen(),equalTo(false));
+
+                for(boolean openState : openStates)
+                {
+                    door = new Door(type,facing,openState);
+                    assertThat("Constructed with correct door type",door.getItemType(),equalTo(type));
+                    assertThat("Constructed with default top or bottom",door.isTopHalf(),equalTo(false));
+                    assertThat("Constructed with correct direction",door.getFacing(),equalTo(facing));
+                    assertThat("Constructed with correct open state",door.isOpen(),equalTo(openState));
+                }
+            }
+
+            // Test top half
+            for(boolean hingeState : hingeStates)
+            {
+                door = new Door(type,hingeState);
+                assertThat("Constructed with correct door type",door.getItemType(),equalTo(type));
+                assertThat("Constructed with default top or bottom",door.isTopHalf(),equalTo(true));
+                assertThat("Constructed with correct direction",door.getHinge(),equalTo(hingeState));
+            }
+        }
+    }
 }
-- 
1.9.5.msysgit.1