From f517b6e6a95a7a7f5498bce806a9b997e433f75b Mon Sep 17 00:00:00 2001 From: ryanbennitt Date: Mon, 11 Jan 2016 18:07:51 +0000 Subject: SPIGOT-1393: Fixed door direction mask --- src/main/java/org/bukkit/material/Door.java | 217 ++++++++++++++++++--- .../org/bukkit/materials/MaterialDataTest.java | 61 ++++++ 2 files changed, 248 insertions(+), 30 deletions(-) create mode 100644 src/test/java/org/bukkit/materials/MaterialDataTest.java diff --git a/src/main/java/org/bukkit/material/Door.java b/src/main/java/org/bukkit/material/Door.java index 27bb6814..e02d8e66 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 isTopHalf() * 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 { @@ -36,6 +45,126 @@ public class Door extends MaterialData implements Directional, Openable { super(type); } + /** + * 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 @@ -56,6 +185,37 @@ public class Door extends MaterialData implements Directional, Openable { super(type, data); } + /** + * 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 isTopHalf() is true. */ @@ -108,23 +268,20 @@ public class Door extends MaterialData implements Directional, Openable { * @param face the direction */ public void setFacingDirection(BlockFace face) { - byte data = (byte) (getData() & 0x12); + byte data = (byte) (getData() & 0xC); switch (face) { - case WEST: - data |= 0x0; - break; - - case NORTH: - data |= 0x1; - break; - - case EAST: - data |= 0x2; - break; - - case SOUTH: - data |= 0x3; - break; + case WEST: + data |= 0x0; + break; + case NORTH: + data |= 0x1; + break; + case EAST: + data |= 0x2; + break; + case SOUTH: + data |= 0x3; + break; } setData(data); } @@ -139,19 +296,17 @@ public class Door extends MaterialData implements Directional, Openable { public BlockFace getFacing() { byte data = (byte) (getData() & 0x3); switch (data) { - case 0: - return BlockFace.WEST; - - case 1: - return BlockFace.NORTH; - - case 2: - return BlockFace.EAST; - - case 3: - return BlockFace.SOUTH; + case 0: + return BlockFace.WEST; + case 1: + return BlockFace.NORTH; + case 2: + return BlockFace.EAST; + case 3: + return BlockFace.SOUTH; + default: + throw new IllegalStateException("Unknown door facing (data: " + data + ")"); } - return null; // shouldn't happen } /** @@ -169,9 +324,11 @@ 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 isTopHalf() 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))); + 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 new file mode 100644 index 00000000..e888381d --- /dev/null +++ b/src/test/java/org/bukkit/materials/MaterialDataTest.java @@ -0,0 +1,61 @@ +package org.bukkit.materials; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; + +import org.bukkit.Material; +import org.bukkit.block.BlockFace; +import org.bukkit.material.Door; +import org.junit.Test; + +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)); + } + } + } +} -- cgit v1.2.3