001    package org.bukkit.enchantments;
002    
003    import java.util.HashMap;
004    import java.util.Map;
005    
006    import org.bukkit.command.defaults.EnchantCommand;
007    import org.bukkit.inventory.ItemStack;
008    
009    /**
010     * The various type of enchantments that may be added to armour or weapons
011     */
012    public abstract class Enchantment {
013        /**
014         * Provides protection against environmental damage
015         */
016        public static final Enchantment PROTECTION_ENVIRONMENTAL = new EnchantmentWrapper(0);
017    
018        /**
019         * Provides protection against fire damage
020         */
021        public static final Enchantment PROTECTION_FIRE = new EnchantmentWrapper(1);
022    
023        /**
024         * Provides protection against fall damage
025         */
026        public static final Enchantment PROTECTION_FALL = new EnchantmentWrapper(2);
027    
028        /**
029         * Provides protection against explosive damage
030         */
031        public static final Enchantment PROTECTION_EXPLOSIONS = new EnchantmentWrapper(3);
032    
033        /**
034         * Provides protection against projectile damage
035         */
036        public static final Enchantment PROTECTION_PROJECTILE = new EnchantmentWrapper(4);
037    
038        /**
039         * Decreases the rate of air loss whilst underwater
040         */
041        public static final Enchantment OXYGEN = new EnchantmentWrapper(5);
042    
043        /**
044         * Increases the speed at which a player may mine underwater
045         */
046        public static final Enchantment WATER_WORKER = new EnchantmentWrapper(6);
047    
048        /**
049         * Damages the attacker
050         */
051        public static final Enchantment THORNS = new EnchantmentWrapper(7);
052    
053        /**
054         * Increases damage against all targets
055         */
056        public static final Enchantment DAMAGE_ALL = new EnchantmentWrapper(16);
057    
058        /**
059         * Increases damage against undead targets
060         */
061        public static final Enchantment DAMAGE_UNDEAD = new EnchantmentWrapper(17);
062    
063        /**
064         * Increases damage against arthropod targets
065         */
066        public static final Enchantment DAMAGE_ARTHROPODS = new EnchantmentWrapper(18);
067    
068        /**
069         * All damage to other targets will knock them back when hit
070         */
071        public static final Enchantment KNOCKBACK = new EnchantmentWrapper(19);
072    
073        /**
074         * When attacking a target, has a chance to set them on fire
075         */
076        public static final Enchantment FIRE_ASPECT = new EnchantmentWrapper(20);
077    
078        /**
079         * Provides a chance of gaining extra loot when killing monsters
080         */
081        public static final Enchantment LOOT_BONUS_MOBS = new EnchantmentWrapper(21);
082    
083        /**
084         * Increases the rate at which you mine/dig
085         */
086        public static final Enchantment DIG_SPEED = new EnchantmentWrapper(32);
087    
088        /**
089         * Allows blocks to drop themselves instead of fragments (for example,
090         * stone instead of cobblestone)
091         */
092        public static final Enchantment SILK_TOUCH = new EnchantmentWrapper(33);
093    
094        /**
095         * Decreases the rate at which a tool looses durability
096         */
097        public static final Enchantment DURABILITY = new EnchantmentWrapper(34);
098    
099        /**
100         * Provides a chance of gaining extra loot when destroying blocks
101         */
102        public static final Enchantment LOOT_BONUS_BLOCKS = new EnchantmentWrapper(35);
103    
104        /**
105         * Provides extra damage when shooting arrows from bows
106         */
107        public static final Enchantment ARROW_DAMAGE = new EnchantmentWrapper(48);
108    
109        /**
110         * Provides a knockback when an entity is hit by an arrow from a bow
111         */
112        public static final Enchantment ARROW_KNOCKBACK = new EnchantmentWrapper(49);
113    
114        /**
115         * Sets entities on fire when hit by arrows shot from a bow
116         */
117        public static final Enchantment ARROW_FIRE = new EnchantmentWrapper(50);
118    
119        /**
120         * Provides infinite arrows when shooting a bow
121         */
122        public static final Enchantment ARROW_INFINITE = new EnchantmentWrapper(51);
123    
124        /**
125         * Decreases odds of catching worthless junk
126         */
127        public static final Enchantment LUCK = new EnchantmentWrapper(61);
128    
129        /**
130         * Increases rate of fish biting your hook
131         */
132        public static final Enchantment LURE = new EnchantmentWrapper(62);
133    
134        private static final Map<Integer, Enchantment> byId = new HashMap<Integer, Enchantment>();
135        private static final Map<String, Enchantment> byName = new HashMap<String, Enchantment>();
136        private static boolean acceptingNew = true;
137        private final int id;
138    
139        public Enchantment(int id) {
140            this.id = id;
141        }
142    
143        /**
144         * Gets the unique ID of this enchantment
145         *
146         * @return Unique ID
147         * @deprecated Magic value
148         */
149        @Deprecated
150        public int getId() {
151            return id;
152        }
153    
154        /**
155         * Gets the unique name of this enchantment
156         *
157         * @return Unique name
158         */
159        public abstract String getName();
160    
161        /**
162         * Gets the maximum level that this Enchantment may become.
163         *
164         * @return Maximum level of the Enchantment
165         */
166        public abstract int getMaxLevel();
167    
168        /**
169         * Gets the level that this Enchantment should start at
170         *
171         * @return Starting level of the Enchantment
172         */
173        public abstract int getStartLevel();
174    
175        /**
176         * Gets the type of {@link ItemStack} that may fit this Enchantment.
177         *
178         * @return Target type of the Enchantment
179         */
180        public abstract EnchantmentTarget getItemTarget();
181    
182        /**
183         * Check if this enchantment conflicts with another enchantment.
184         *
185         * @param other The enchantment to check against
186         * @return True if there is a conflict.
187         */
188        public abstract boolean conflictsWith(Enchantment other);
189    
190        /**
191         * Checks if this Enchantment may be applied to the given {@link
192         * ItemStack}.
193         * <p>
194         * This does not check if it conflicts with any enchantments already
195         * applied to the item.
196         *
197         * @param item Item to test
198         * @return True if the enchantment may be applied, otherwise False
199         */
200        public abstract boolean canEnchantItem(ItemStack item);
201    
202        @Override
203        public boolean equals(Object obj) {
204            if (obj == null) {
205                return false;
206            }
207            if (!(obj instanceof Enchantment)) {
208                return false;
209            }
210            final Enchantment other = (Enchantment) obj;
211            if (this.id != other.id) {
212                return false;
213            }
214            return true;
215        }
216    
217        @Override
218        public int hashCode() {
219            return id;
220        }
221    
222        @Override
223        public String toString() {
224            return "Enchantment[" + id + ", " + getName() + "]";
225        }
226    
227        /**
228         * Registers an enchantment with the given ID and object.
229         * <p>
230         * Generally not to be used from within a plugin.
231         *
232         * @param enchantment Enchantment to register
233         */
234        public static void registerEnchantment(Enchantment enchantment) {
235            if (byId.containsKey(enchantment.id) || byName.containsKey(enchantment.getName())) {
236                throw new IllegalArgumentException("Cannot set already-set enchantment");
237            } else if (!isAcceptingRegistrations()) {
238                throw new IllegalStateException("No longer accepting new enchantments (can only be done by the server implementation)");
239            }
240    
241            byId.put(enchantment.id, enchantment);
242            byName.put(enchantment.getName(), enchantment);
243        }
244    
245        /**
246         * Checks if this is accepting Enchantment registrations.
247         *
248         * @return True if the server Implementation may add enchantments
249         */
250        public static boolean isAcceptingRegistrations() {
251            return acceptingNew;
252        }
253    
254        /**
255         * Stops accepting any enchantment registrations
256         */
257        public static void stopAcceptingRegistrations() {
258            acceptingNew = false;
259            EnchantCommand.buildEnchantments();
260        }
261    
262        /**
263         * Gets the Enchantment at the specified ID
264         *
265         * @param id ID to fetch
266         * @return Resulting Enchantment, or null if not found
267         * @deprecated Magic value
268         */
269        @Deprecated
270        public static Enchantment getById(int id) {
271            return byId.get(id);
272        }
273    
274        /**
275         * Gets the Enchantment at the specified name
276         *
277         * @param name Name to fetch
278         * @return Resulting Enchantment, or null if not found
279         */
280        public static Enchantment getByName(String name) {
281            return byName.get(name);
282        }
283    
284        /**
285         * Gets an array of all the registered {@link Enchantment}s
286         *
287         * @return Array of enchantments
288         */
289        public static Enchantment[] values() {
290            return byId.values().toArray(new Enchantment[byId.size()]);
291        }
292    }