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 }