package org.bukkit.potion;
import com.google.common.collect.ImmutableMap;
import org.apache.commons.lang.Validate;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.SerializableAs;
import org.bukkit.entity.LivingEntity;
import java.util.Map;
import java.util.NoSuchElementException;
/**
* Represents a potion effect, that can be added to a {@link LivingEntity}. A
* potion effect has a duration that it will last for, an amplifier that will
* enhance its effects, and a {@link PotionEffectType}, that represents its
* effect on an entity.
*/
@SerializableAs("PotionEffect")
public class PotionEffect implements ConfigurationSerializable
{
private static final String AMPLIFIER = "amplifier";
private static final String DURATION = "duration";
private static final String TYPE = "effect";
private static final String AMBIENT = "ambient";
private final int amplifier;
private final int duration;
private final PotionEffectType type;
private final boolean ambient;
/**
* Creates a potion effect.
*
* @param type effect type
* @param duration measured in ticks, see {@link
* PotionEffect#getDuration()}
* @param amplifier the amplifier, see {@link PotionEffect#getAmplifier()}
* @param ambient the ambient status, see {@link PotionEffect#isAmbient()}
*/
public PotionEffect(PotionEffectType type, int duration, int amplifier, boolean ambient)
{
Validate.notNull(type, "effect type cannot be null");
this.type = type;
this.duration = duration;
this.amplifier = amplifier;
this.ambient = ambient;
}
/**
* Creates a potion effect. Assumes ambient is true.
*
* @param type Effect type
* @param duration measured in ticks
* @param amplifier the amplifier for the effect
* @see PotionEffect#PotionEffect(PotionEffectType, int, int, boolean)
*/
public PotionEffect(PotionEffectType type, int duration, int amplifier)
{
this(type, duration, amplifier, true);
}
/**
* Constructor for deserialization.
*
* @param map the map to deserialize from
*/
public PotionEffect(Map<String, Object> map)
{
this(getEffectType(map), getInt(map, DURATION), getInt(map, AMPLIFIER), getBool(map, AMBIENT));
}
private static PotionEffectType getEffectType(Map<?, ?> map)
{
int type = getInt(map, TYPE);
PotionEffectType effect = PotionEffectType.getById(type);
if(effect != null)
{
return effect;
}
throw new NoSuchElementException(map + " does not contain " + TYPE);
}
private static int getInt(Map<?, ?> map, Object key)
{
Object num = map.get(key);
if(num instanceof Integer)
{
return (Integer) num;
}
throw new NoSuchElementException(map + " does not contain " + key);
}
private static boolean getBool(Map<?, ?> map, Object key)
{
Object bool = map.get(key);
if(bool instanceof Boolean)
{
return (Boolean) bool;
}
throw new NoSuchElementException(map + " does not contain " + key);
}
public Map<String, Object> serialize()
{
return ImmutableMap.<String, Object>of(
TYPE, type.getId(),
DURATION, duration,
AMPLIFIER, amplifier,
AMBIENT, ambient
);
}
/**
* Attempts to add the effect represented by this object to the given
* {@link LivingEntity}.
*
* @param entity The entity to add this effect to
* @return Whether the effect could be added
* @see LivingEntity#addPotionEffect(PotionEffect)
*/
public boolean apply(LivingEntity entity)
{
return entity.addPotionEffect(this);
}
@Override
public boolean equals(Object obj)
{
if(this == obj)
{
return true;
}
if(!(obj instanceof PotionEffect))
{
return false;
}
PotionEffect that = (PotionEffect) obj;
return this.type.equals(that.type) && this.ambient == that.ambient && this.amplifier == that.amplifier && this.duration == that.duration;
}
/**
* Returns the amplifier of this effect. A higher amplifier means the
* potion effect happens more often over its duration and in some cases
* has more effect on its target.
*
* @return The effect amplifier
*/
public int getAmplifier()
{
return amplifier;
}
/**
* Returns the duration (in ticks) that this effect will run for when
* applied to a {@link LivingEntity}.
*
* @return The duration of the effect
*/
public int getDuration()
{
return duration;
}
/**
* Returns the {@link PotionEffectType} of this effect.
*
* @return The potion type of this effect
*/
public PotionEffectType getType()
{
return type;
}
/**
* Makes potion effect produce more, translucent, particles.
*
* @return if this effect is ambient
*/
public boolean isAmbient()
{
return ambient;
}
@Override
public int hashCode()
{
int hash = 1;
hash = hash * 31 + type.hashCode();
hash = hash * 31 + amplifier;
hash = hash * 31 + duration;
hash ^= 0x22222222 >> (ambient ? 1 : -1);
return hash;
}
@Override
public String toString()
{
return type.getName() + (ambient ? ":(" : ":") + duration + "t-x" + amplifier + (ambient ? ")" : "");
}
}