001 package org.bukkit.potion;
002
003 import java.util.HashMap;
004 import java.util.Map;
005
006 import org.apache.commons.lang.Validate;
007
008 /**
009 * Represents a type of potion and its effect on an entity.
010 */
011 public abstract class PotionEffectType {
012 /**
013 * Increases movement speed.
014 */
015 public static final PotionEffectType SPEED = new PotionEffectTypeWrapper(1);
016
017 /**
018 * Decreases movement speed.
019 */
020 public static final PotionEffectType SLOW = new PotionEffectTypeWrapper(2);
021
022 /**
023 * Increases dig speed.
024 */
025 public static final PotionEffectType FAST_DIGGING = new PotionEffectTypeWrapper(3);
026
027 /**
028 * Decreases dig speed.
029 */
030 public static final PotionEffectType SLOW_DIGGING = new PotionEffectTypeWrapper(4);
031
032 /**
033 * Increases damage dealt.
034 */
035 public static final PotionEffectType INCREASE_DAMAGE = new PotionEffectTypeWrapper(5);
036
037 /**
038 * Heals an entity.
039 */
040 public static final PotionEffectType HEAL = new PotionEffectTypeWrapper(6);
041
042 /**
043 * Hurts an entity.
044 */
045 public static final PotionEffectType HARM = new PotionEffectTypeWrapper(7);
046
047 /**
048 * Increases jump height.
049 */
050 public static final PotionEffectType JUMP = new PotionEffectTypeWrapper(8);
051
052 /**
053 * Warps vision on the client.
054 */
055 public static final PotionEffectType CONFUSION = new PotionEffectTypeWrapper(9);
056
057 /**
058 * Regenerates health.
059 */
060 public static final PotionEffectType REGENERATION = new PotionEffectTypeWrapper(10);
061
062 /**
063 * Decreases damage dealt to an entity.
064 */
065 public static final PotionEffectType DAMAGE_RESISTANCE = new PotionEffectTypeWrapper(11);
066
067 /**
068 * Stops fire damage.
069 */
070 public static final PotionEffectType FIRE_RESISTANCE = new PotionEffectTypeWrapper(12);
071
072 /**
073 * Allows breathing underwater.
074 */
075 public static final PotionEffectType WATER_BREATHING = new PotionEffectTypeWrapper(13);
076
077 /**
078 * Grants invisibility.
079 */
080 public static final PotionEffectType INVISIBILITY = new PotionEffectTypeWrapper(14);
081
082 /**
083 * Blinds an entity.
084 */
085 public static final PotionEffectType BLINDNESS = new PotionEffectTypeWrapper(15);
086
087 /**
088 * Allows an entity to see in the dark.
089 */
090 public static final PotionEffectType NIGHT_VISION = new PotionEffectTypeWrapper(16);
091
092 /**
093 * Increases hunger.
094 */
095 public static final PotionEffectType HUNGER = new PotionEffectTypeWrapper(17);
096
097 /**
098 * Decreases damage dealt by an entity.
099 */
100 public static final PotionEffectType WEAKNESS = new PotionEffectTypeWrapper(18);
101
102 /**
103 * Deals damage to an entity over time.
104 */
105 public static final PotionEffectType POISON = new PotionEffectTypeWrapper(19);
106
107 /**
108 * Deals damage to an entity over time and gives the health to the shooter.
109 */
110 public static final PotionEffectType WITHER = new PotionEffectTypeWrapper(20);
111
112 private final int id;
113
114 protected PotionEffectType(int id) {
115 this.id = id;
116 }
117
118 /**
119 * Creates a PotionEffect from this PotionEffectType, applying duration modifiers and checks.
120 *
121 * @see PotionBrewer#createEffect(PotionEffectType, int, int)
122 * @param duration time in ticks
123 * @param amplifier the effect's amplifier
124 * @return a resulting potion effect
125 */
126 public PotionEffect createEffect(int duration, int amplifier) {
127 return Potion.getBrewer().createEffect(this, duration, amplifier);
128 }
129
130 /**
131 * Returns the duration modifier applied to effects of this type.
132 *
133 * @return duration modifier
134 */
135 public abstract double getDurationModifier();
136
137 /**
138 * Returns the unique ID of this type.
139 *
140 * @return Unique ID
141 */
142 public int getId() {
143 return id;
144 }
145
146 /**
147 * Returns the name of this effect type.
148 *
149 * @return The name of this effect type
150 */
151 public abstract String getName();
152
153 /**
154 * Returns whether the effect of this type happens once, immediately.
155 *
156 * @return whether this type is normally instant
157 */
158 public abstract boolean isInstant();
159
160 @Override
161 public boolean equals(Object obj) {
162 if (obj == null) {
163 return false;
164 }
165 if (!(obj instanceof PotionEffectType)) {
166 return false;
167 }
168 final PotionEffectType other = (PotionEffectType) obj;
169 if (this.id != other.id) {
170 return false;
171 }
172 return true;
173 }
174
175 @Override
176 public int hashCode() {
177 return id;
178 }
179
180 @Override
181 public String toString() {
182 return "PotionEffectType[" + id + ", " + getName() + "]";
183 }
184
185 private static final PotionEffectType[] byId = new PotionEffectType[21];
186 private static final Map<String, PotionEffectType> byName = new HashMap<String, PotionEffectType>();
187 // will break on updates.
188 private static boolean acceptingNew = true;
189
190 /**
191 * Gets the effect type specified by the unique id.
192 *
193 * @param id Unique ID to fetch
194 * @return Resulting type, or null if not found.
195 */
196 public static PotionEffectType getById(int id) {
197 if (id >= byId.length || id < 0)
198 return null;
199 return byId[id];
200 }
201
202 /**
203 * Gets the effect type specified by the given name.
204 *
205 * @param name Name of PotionEffectType to fetch
206 * @return Resulting PotionEffectType, or null if not found.
207 */
208 public static PotionEffectType getByName(String name) {
209 Validate.notNull(name, "name cannot be null");
210 return byName.get(name.toLowerCase());
211 }
212
213 /**
214 * Registers an effect type with the given object.
215 * <p />
216 * Generally not to be used from within a plugin.
217 *
218 * @param type PotionType to register
219 */
220 public static void registerPotionEffectType(PotionEffectType type) {
221 if (byId[type.id] != null || byName.containsKey(type.getName().toLowerCase())) {
222 throw new IllegalArgumentException("Cannot set already-set type");
223 } else if (!acceptingNew) {
224 throw new IllegalStateException(
225 "No longer accepting new potion effect types (can only be done by the server implementation)");
226 }
227
228 byId[type.id] = type;
229 byName.put(type.getName().toLowerCase(), type);
230 }
231
232 /**
233 * Stops accepting any effect type registrations.
234 */
235 public static void stopAcceptingRegistrations() {
236 acceptingNew = false;
237 }
238
239 /**
240 * Returns an array of all the registered {@link PotionEffectType}s.
241 *
242 * @return Array of types.
243 */
244 public static PotionEffectType[] values() {
245 return byId.clone();
246 }
247 }