001    package org.bukkit.material;
002    
003    import java.util.EnumSet;
004    import java.util.Set;
005    
006    import org.apache.commons.lang.Validate;
007    import org.bukkit.Material;
008    import org.bukkit.block.BlockFace;
009    
010    /**
011     * Represents a huge mushroom block
012     */
013    public class Mushroom extends MaterialData {
014        private static final byte SHROOM_NONE = 0;
015        private static final byte SHROOM_STEM = 10;
016        private static final byte NORTH_LIMIT = 4;
017        private static final byte SOUTH_LIMIT = 6;
018        private static final byte EAST_WEST_LIMIT = 3;
019        private static final byte EAST_REMAINDER = 0;
020        private static final byte WEST_REMAINDER = 1;
021        private static final byte NORTH_SOUTH_MOD = 3;
022        private static final byte EAST_WEST_MOD = 1;
023    
024        public Mushroom(Material shroom) {
025            super(shroom);
026            Validate.isTrue(shroom == Material.HUGE_MUSHROOM_1 || shroom == Material.HUGE_MUSHROOM_2, "Not a mushroom!");
027        }
028    
029        /**
030         *
031         * @deprecated Magic value
032         */
033        @Deprecated
034        public Mushroom(Material shroom, byte data) {
035            super(shroom, data);
036            Validate.isTrue(shroom == Material.HUGE_MUSHROOM_1 || shroom == Material.HUGE_MUSHROOM_2, "Not a mushroom!");
037        }
038    
039        /**
040         *
041         * @deprecated Magic value
042         */
043        @Deprecated
044        public Mushroom(int type, byte data){
045            super(type, data);
046            Validate.isTrue(type == Material.HUGE_MUSHROOM_1.getId() || type == Material.HUGE_MUSHROOM_2.getId(), "Not a mushroom!");
047        }
048    
049        /**
050         * @return Whether this is a mushroom stem.
051         */
052        public boolean isStem() {
053            return getData() == SHROOM_STEM;
054        }
055    
056        /**
057         * Sets this to be a mushroom stem.
058         */
059        public void setStem() {
060            setData((byte) 10);
061        }
062    
063        /**
064         * Checks whether a face of the block is painted.
065         *
066         * @param face The face to check.
067         * @return True if it is painted.
068         */
069        public boolean isFacePainted(BlockFace face) {
070            byte data = getData();
071    
072            if (data == SHROOM_NONE || data == SHROOM_STEM) {
073                return false;
074            }
075    
076            switch (face) {
077                case WEST:
078                    return data < NORTH_LIMIT;
079                case EAST:
080                    return data > SOUTH_LIMIT;
081                case NORTH:
082                    return data % EAST_WEST_LIMIT == EAST_REMAINDER;
083                case SOUTH:
084                    return data % EAST_WEST_LIMIT == WEST_REMAINDER;
085                case UP:
086                    return true;
087                default:
088                    return false;
089            }
090        }
091    
092        /**
093         * Set a face of the block to be painted or not. Note that due to the
094         * nature of how the data is stored, setting a face painted or not is not
095         * guaranteed to leave the other faces unchanged.
096         *
097         * @param face The face to paint or unpaint.
098         * @param painted True if you want to paint it, false if you want the
099         *     pores to show.
100         */
101        public void setFacePainted(BlockFace face, boolean painted) {
102            if (painted == isFacePainted(face)) {
103                return;
104            }
105    
106            byte data = getData();
107    
108            if (data == SHROOM_STEM) {
109                data = 5;
110            }
111    
112            switch (face) {
113                case WEST:
114                    if (painted) {
115                        data -= NORTH_SOUTH_MOD;
116                    } else {
117                        data += NORTH_SOUTH_MOD;
118                    }
119    
120                    break;
121                case EAST:
122                    if (painted) {
123                        data += NORTH_SOUTH_MOD;
124                    } else {
125                        data -= NORTH_SOUTH_MOD;
126                    }
127    
128                    break;
129                case NORTH:
130                    if (painted) {
131                        data += EAST_WEST_MOD;
132                    } else {
133                        data -= EAST_WEST_MOD;
134                    }
135    
136                    break;
137                case SOUTH:
138                    if (painted) {
139                        data -= EAST_WEST_MOD;
140                    } else {
141                        data += EAST_WEST_MOD;
142                    }
143    
144                    break;
145                case UP:
146                    if (!painted) {
147                        data = 0;
148                    }
149    
150                    break;
151                default:
152                    throw new IllegalArgumentException("Can't paint that face of a mushroom!");
153            }
154    
155            setData(data);
156        }
157    
158        /**
159         * @return A set of all faces that are currently painted (an empty set if
160         *     it is a stem)
161         */
162        public Set<BlockFace> getPaintedFaces() {
163            EnumSet<BlockFace> faces = EnumSet.noneOf(BlockFace.class);
164    
165            if (isFacePainted(BlockFace.WEST)) {
166                faces.add(BlockFace.WEST);
167            }
168    
169            if (isFacePainted(BlockFace.NORTH)) {
170                faces.add(BlockFace.NORTH);
171            }
172    
173            if (isFacePainted(BlockFace.SOUTH)) {
174                faces.add(BlockFace.SOUTH);
175            }
176    
177            if (isFacePainted(BlockFace.EAST)) {
178                faces.add(BlockFace.EAST);
179            }
180    
181            if (isFacePainted(BlockFace.UP)) {
182                faces.add(BlockFace.UP);
183            }
184    
185            return faces;
186        }
187    
188        @Override
189        public String toString() {
190            return Material.getMaterial(getItemTypeId()).toString() + (isStem() ? "{STEM}" : getPaintedFaces());
191        }
192    
193        @Override
194        public Mushroom clone() {
195            return (Mushroom) super.clone();
196        }
197    }