001 package org.bukkit.material; 002 003 import java.util.Arrays; 004 import java.util.EnumSet; 005 006 import org.bukkit.Material; 007 import org.bukkit.block.BlockFace; 008 009 /** 010 * Represents a vine 011 */ 012 public class Vine extends MaterialData { 013 private static final int VINE_NORTH = 0x4; 014 private static final int VINE_EAST = 0x8; 015 private static final int VINE_WEST = 0x2; 016 private static final int VINE_SOUTH = 0x1; 017 EnumSet<BlockFace> possibleFaces = EnumSet.of(BlockFace.WEST, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST); 018 019 public Vine() { 020 super(Material.VINE); 021 } 022 023 /** 024 * 025 * @deprecated Magic value 026 */ 027 @Deprecated 028 public Vine(int type, byte data){ 029 super(type, data); 030 } 031 032 /** 033 * 034 * @deprecated Magic value 035 */ 036 @Deprecated 037 public Vine(byte data) { 038 super(Material.VINE, data); 039 } 040 041 public Vine(BlockFace... faces) { 042 this(EnumSet.copyOf(Arrays.asList(faces))); 043 } 044 045 public Vine(EnumSet<BlockFace> faces) { 046 this((byte) 0); 047 faces.retainAll(possibleFaces); 048 049 byte data = 0; 050 051 if (faces.contains(BlockFace.WEST)) { 052 data |= VINE_WEST; 053 } 054 055 if (faces.contains(BlockFace.NORTH)) { 056 data |= VINE_NORTH; 057 } 058 059 if (faces.contains(BlockFace.SOUTH)) { 060 data |= VINE_SOUTH; 061 } 062 063 if (faces.contains(BlockFace.EAST)) { 064 data |= VINE_EAST; 065 } 066 067 setData(data); 068 } 069 070 /** 071 * Check if the vine is attached to the specified face of an adjacent 072 * block. You can check two faces at once by passing e.g. {@link 073 * BlockFace#NORTH_EAST}. 074 * 075 * @param face The face to check. 076 * @return Whether it is attached to that face. 077 */ 078 public boolean isOnFace(BlockFace face) { 079 switch (face) { 080 case WEST: 081 return (getData() & VINE_WEST) == VINE_WEST; 082 case NORTH: 083 return (getData() & VINE_NORTH) == VINE_NORTH; 084 case SOUTH: 085 return (getData() & VINE_SOUTH) == VINE_SOUTH; 086 case EAST: 087 return (getData() & VINE_EAST) == VINE_EAST; 088 case NORTH_EAST: 089 return isOnFace(BlockFace.EAST) && isOnFace(BlockFace.NORTH); 090 case NORTH_WEST: 091 return isOnFace(BlockFace.WEST) && isOnFace(BlockFace.NORTH); 092 case SOUTH_EAST: 093 return isOnFace(BlockFace.EAST) && isOnFace(BlockFace.SOUTH); 094 case SOUTH_WEST: 095 return isOnFace(BlockFace.WEST) && isOnFace(BlockFace.SOUTH); 096 case UP: // It's impossible to be accurate with this since it's contextual 097 return true; 098 default: 099 return false; 100 } 101 } 102 103 /** 104 * Attach the vine to the specified face of an adjacent block. 105 * 106 * @param face The face to attach. 107 */ 108 public void putOnFace(BlockFace face) { 109 switch(face) { 110 case WEST: 111 setData((byte) (getData() | VINE_WEST)); 112 break; 113 case NORTH: 114 setData((byte) (getData() | VINE_NORTH)); 115 break; 116 case SOUTH: 117 setData((byte) (getData() | VINE_SOUTH)); 118 break; 119 case EAST: 120 setData((byte) (getData() | VINE_EAST)); 121 break; 122 case NORTH_WEST: 123 putOnFace(BlockFace.WEST); 124 putOnFace(BlockFace.NORTH); 125 break; 126 case SOUTH_WEST: 127 putOnFace(BlockFace.WEST); 128 putOnFace(BlockFace.SOUTH); 129 break; 130 case NORTH_EAST: 131 putOnFace(BlockFace.EAST); 132 putOnFace(BlockFace.NORTH); 133 break; 134 case SOUTH_EAST: 135 putOnFace(BlockFace.EAST); 136 putOnFace(BlockFace.SOUTH); 137 break; 138 case UP: 139 break; 140 default: 141 throw new IllegalArgumentException("Vines can't go on face " + face.toString()); 142 } 143 } 144 145 /** 146 * Detach the vine from the specified face of an adjacent block. 147 * 148 * @param face The face to detach. 149 */ 150 public void removeFromFace(BlockFace face) { 151 switch(face) { 152 case WEST: 153 setData((byte) (getData() & ~VINE_WEST)); 154 break; 155 case NORTH: 156 setData((byte) (getData() & ~VINE_NORTH)); 157 break; 158 case SOUTH: 159 setData((byte) (getData() & ~VINE_SOUTH)); 160 break; 161 case EAST: 162 setData((byte) (getData() & ~VINE_EAST)); 163 break; 164 case NORTH_WEST: 165 removeFromFace(BlockFace.WEST); 166 removeFromFace(BlockFace.NORTH); 167 break; 168 case SOUTH_WEST: 169 removeFromFace(BlockFace.WEST); 170 removeFromFace(BlockFace.SOUTH); 171 break; 172 case NORTH_EAST: 173 removeFromFace(BlockFace.EAST); 174 removeFromFace(BlockFace.NORTH); 175 break; 176 case SOUTH_EAST: 177 removeFromFace(BlockFace.EAST); 178 removeFromFace(BlockFace.SOUTH); 179 break; 180 case UP: 181 break; 182 default: 183 throw new IllegalArgumentException("Vines can't go on face " + face.toString()); 184 } 185 } 186 187 @Override 188 public String toString() { 189 return "VINE"; 190 } 191 192 @Override 193 public Vine clone() { 194 return (Vine) super.clone(); 195 } 196 }