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 }