Bukkit  1.4.7-R1.0
 All Classes Namespaces Files Functions Variables Enumerator Pages
Potion.java
Go to the documentation of this file.
1 package org.bukkit.potion;
2 
3 import java.util.Collection;
4 
5 import org.apache.commons.lang.Validate;
6 import org.bukkit.Material;
7 import org.bukkit.entity.LivingEntity;
8 import org.bukkit.inventory.ItemStack;
9 
10 import com.google.common.collect.ImmutableList;
11 
15 public class Potion {
16  private boolean extended = false;
17  private boolean splash = false;
18  private int level = 1;
19  private int name = -1;
20  private PotionType type;
21 
29  public Potion(PotionType type) {
30  this.type = type;
31  if (type != null) {
32  this.name = type.getDamageValue();
33  }
34  if (type == null || type == PotionType.WATER) {
35  this.level = 0;
36  }
37  }
38 
40  @SuppressWarnings("javadoc")
41  @Deprecated
42  public Potion(PotionType type, Tier tier) {
43  this(type, tier == Tier.TWO ? 2 : 1);
44  Validate.notNull(type, "Type cannot be null");
45  }
46 
48  @SuppressWarnings("javadoc")
49  @Deprecated
50  public Potion(PotionType type, Tier tier, boolean splash) {
51  this(type, tier == Tier.TWO ? 2 : 1, splash);
52  }
53 
55  @SuppressWarnings("javadoc")
56  @Deprecated
57  public Potion(PotionType type, Tier tier, boolean splash, boolean extended) {
58  this(type, tier, splash);
59  this.extended = extended;
60  }
61 
67  public Potion(PotionType type, int level) {
68  this(type);
69  Validate.notNull(type, "Type cannot be null");
70  Validate.isTrue(type != PotionType.WATER, "Water bottles don't have a level!");
71  Validate.isTrue(level > 0 && level < 3, "Level must be 1 or 2");
72  this.level = level;
73  }
74 
82  @Deprecated
83  public Potion(PotionType type, int level, boolean splash) {
84  this(type, level);
85  this.splash = splash;
86  }
87 
97  @Deprecated
98  public Potion(PotionType type, int level, boolean splash, boolean extended) {
99  this(type, level, splash);
100  this.extended = extended;
101  }
102 
107  public Potion(int name) {
108  this(PotionType.getByDamageValue(name & POTION_BIT));
109  this.name = name & NAME_BIT;
110  if ((name & POTION_BIT) == 0) {
111  // If it's 0 it would've become PotionType.WATER, but it should actually be mundane potion
112  this.type = null;
113  }
114  }
115 
120  public Potion splash() {
121  setSplash(true);
122  return this;
123  }
124 
129  public Potion extend() {
131  return this;
132  }
133 
140  public void apply(ItemStack to) {
141  Validate.notNull(to, "itemstack cannot be null");
142  Validate.isTrue(to.getType() == Material.POTION, "given itemstack is not a potion");
144  }
145 
153  public void apply(LivingEntity to) {
154  Validate.notNull(to, "entity cannot be null");
156  }
157 
158  @Override
159  public boolean equals(Object obj) {
160  if (this == obj) {
161  return true;
162  }
163  if (obj == null || getClass() != obj.getClass()) {
164  return false;
165  }
166  Potion other = (Potion) obj;
167  return extended == other.extended && splash == other.splash && level == other.level && type == other.type;
168  }
169 
178  public Collection<PotionEffect> getEffects() {
179  if (type == null) return ImmutableList.<PotionEffect>of();
181  }
182 
188  public int getLevel() {
189  return level;
190  }
191 
197  @Deprecated
198  public Tier getTier() {
199  return level == 2 ? Tier.TWO : Tier.ONE;
200  }
201 
207  public PotionType getType() {
208  return type;
209  }
210 
216  public boolean hasExtendedDuration() {
217  return extended;
218  }
219 
220  @Override
221  public int hashCode() {
222  final int prime = 31;
223  int result = prime + level;
224  result = prime * result + (extended ? 1231 : 1237);
225  result = prime * result + (splash ? 1231 : 1237);
226  result = prime * result + ((type == null) ? 0 : type.hashCode());
227  return result;
228  }
229 
235  public boolean isSplash() {
236  return splash;
237  }
238 
245  public void setHasExtendedDuration(boolean isExtended) {
246  Validate.isTrue(type == null || !type.isInstant(), "Instant potions cannot be extended");
247  extended = isExtended;
248  }
249 
257  public void setSplash(boolean isSplash) {
258  splash = isSplash;
259  }
260 
267  @Deprecated
268  public void setTier(Tier tier) {
269  Validate.notNull(tier, "tier cannot be null");
270  this.level = (tier == Tier.TWO ? 2 : 1);
271  }
272 
279  public void setType(PotionType type) {
280  this.type = type;
281  }
282 
288  public void setLevel(int level) {
289  Validate.notNull(this.type, "No-effect potions don't have a level.");
290  int max = type.getMaxLevel();
291  Validate.isTrue(level > 0 && level <= max, "Level must be " + (max == 1 ? "" : "between 1 and ") + max + " for this potion");
292  this.level = level;
293  }
294 
301  public short toDamageValue() {
302  short damage;
303  if (type == PotionType.WATER) {
304  return 0;
305  } else if (type == null) {
306  // Without this, mundanePotion.toDamageValue() would return 0
307  damage = (short) (name == 0 ? 8192 : name);
308  } else {
309  damage = (short) (level - 1);
310  damage <<= TIER_SHIFT;
311  damage |= (short) type.getDamageValue();
312  }
313  if (splash) {
314  damage |= SPLASH_BIT;
315  }
316  if (extended) {
317  damage |= EXTENDED_BIT;
318  }
319  return damage;
320  }
321 
329  public ItemStack toItemStack(int amount) {
330  return new ItemStack(Material.POTION, amount, toDamageValue());
331  }
332 
333  @Deprecated
334  public enum Tier {
335  ONE(0),
336  TWO(0x20);
337 
338  private int damageBit;
339 
340  Tier(int bit) {
341  damageBit = bit;
342  }
343 
344  public int getDamageBit() {
345  return damageBit;
346  }
347 
348  public static Tier getByDamageBit(int damageBit) {
349  for (Tier tier : Tier.values()) {
350  if (tier.damageBit == damageBit)
351  return tier;
352  }
353  return null;
354  }
355  }
356 
357  private static PotionBrewer brewer;
358 
359  private static final int EXTENDED_BIT = 0x40;
360  private static final int POTION_BIT = 0xF;
361  private static final int SPLASH_BIT = 0x4000;
362  private static final int TIER_BIT = 0x20;
363  private static final int TIER_SHIFT = 5;
364  private static final int NAME_BIT = 0x3F;
365 
366  public static Potion fromDamage(int damage) {
367  PotionType type = PotionType.getByDamageValue(damage & POTION_BIT);
368  Potion potion;
369  if (type == null || (type == PotionType.WATER && damage != 0)) {
370  potion = new Potion(damage & NAME_BIT);
371  } else {
372  int level = (damage & TIER_BIT) >> TIER_SHIFT;
373  level++;
374  potion = new Potion(type, level);
375  }
376  if ((damage & SPLASH_BIT) > 0) {
377  potion = potion.splash();
378  }
379  if ((damage & EXTENDED_BIT) > 0) {
380  potion = potion.extend();
381  }
382  return potion;
383  }
384 
385  public static Potion fromItemStack(ItemStack item) {
386  Validate.notNull(item, "item cannot be null");
387  if (item.getType() != Material.POTION)
388  throw new IllegalArgumentException("item is not a potion");
389  return fromDamage(item.getDurability());
390  }
391 
397  public static PotionBrewer getBrewer() {
398  return brewer;
399  }
400 
407  public static void setPotionBrewer(PotionBrewer other) {
408  if (brewer != null)
409  throw new IllegalArgumentException("brewer can only be set internally");
410  brewer = other;
411  }
412 
413  public int getNameId() {
414  return name;
415  }
416 }