package org.shininet.bukkit.itemrenamer.wrappers;
import java.util.Deque;
import java.util.Map;
import org.bukkit.enchantments.Enchantment;
import org.shininet.bukkit.itemrenamer.enchants.HideAttributesEnchanter;
import org.shininet.bukkit.itemrenamer.enchants.HideDurabilityEnchanter;
import org.shininet.bukkit.itemrenamer.enchants.VanillaEnchanter;
import org.shininet.bukkit.itemrenamer.enchants.GlowEnchanter;
import org.shininet.bukkit.itemrenamer.enchants.Enchanter;
import com.google.common.base.Joiner;
import com.google.common.collect.Maps;
import com.google.common.base.Objects;
public class LeveledEnchantment {
public enum CustomEnchantment {
/**
* No custom enchantment.
*/
VANILLA,
/**
* Represents an enchantment that preserves the enchantment glow, but does not show up client side.
*/
GLOW,
/**
* Represents an enchantment that removes all the attribute lines in 1.6.1 and 1.6.2.
*/
NO_ATTRIBUTES,
/**
* Represents an enchanter that removes any visible durability on the item.
*/
NO_DURABILITY;
/**
* Retrieve the parsed custom enchantment, or NULL if not found.
* @param name - the value to parse.
* @return The parsed custom enchantment.
*/
public static CustomEnchantment parse(String name) {
try {
return CustomEnchantment.valueOf(name);
} catch (IllegalArgumentException e) {
return null;
}
}
}
private final CustomEnchantment custom;
private final Enchantment enchantment;
private final int level;
// The current enchanter
private transient Enchanter enchanter;
private static Map<String, Enchantment> byName = Maps.newHashMap();
static {
for (Enchantment enchantment : Enchantment.values()) {
byName.put(enchantment.getName(), enchantment);
}
// Register the rest manually
byName.put("POWER", Enchantment.ARROW_DAMAGE);
byName.put("PUNCH", Enchantment.ARROW_KNOCKBACK);
byName.put("INFINITY", Enchantment.ARROW_INFINITE);
byName.put("FLAME", Enchantment.ARROW_FIRE);
byName.put("SHARPNESS", Enchantment.DAMAGE_ALL);
byName.put("BANE_OF_ARTHROPODS", Enchantment.DAMAGE_ARTHROPODS);
byName.put("SMITE", Enchantment.DAMAGE_UNDEAD);
byName.put("EFFICIENCY", Enchantment.DIG_SPEED);
byName.put("UNBREAKING", Enchantment.DURABILITY);
byName.put("FIRE_ASPECT", Enchantment.FIRE_ASPECT);
byName.put("KNOCKBACK", Enchantment.KNOCKBACK);
byName.put("FORTUNE", Enchantment.LOOT_BONUS_BLOCKS);
byName.put("LOOTING", Enchantment.LOOT_BONUS_MOBS);
byName.put("RESPIRATION", Enchantment.OXYGEN);
byName.put("PROTECTION", Enchantment.PROTECTION_ENVIRONMENTAL);
byName.put("BLAST_PROTECTION", Enchantment.PROTECTION_EXPLOSIONS);
byName.put("FEATHER_FALLING", Enchantment.PROTECTION_FALL);
byName.put("FIRE_PROTECTION", Enchantment.PROTECTION_FIRE);
byName.put("PROJECTILE_PROTECTION", Enchantment.PROTECTION_PROJECTILE);
byName.put("SILK_TOUCH", Enchantment.SILK_TOUCH);
byName.put("THORNS", Enchantment.THORNS);
byName.put("AQUA_AFFINITY", Enchantment.WATER_WORKER);
}
/**
* Represents an enchantment with a associated level.
* @param enchantment - the enchantment.
* @param level - the associated level.
*/
public LeveledEnchantment(Enchantment enchantment, int level) {
if (enchantment == null)
throw new IllegalArgumentException("enchantment cannot be NULL.");
this.custom = CustomEnchantment.VANILLA;
this.enchantment = enchantment;
this.level = level;
}
/**
* Represents a custom enchantment with a associated level.
* @param custom - the custom enchantment.
* @param level - the associated level.
*/
public LeveledEnchantment(CustomEnchantment custom, int level) {
if (custom == null)
throw new IllegalArgumentException("custom cannot be NULL.");
if (custom == CustomEnchantment.VANILLA)
throw new IllegalArgumentException("custom cannot be VANILLA.");
this.custom = custom;
this.enchantment = null;
this.level = level;
}
/**
* Retrieve the associated enchantment.
* <p>
* May be NULL if this leveled enchantment represents a custom enchantment.
* @return The associated enchantment.
*/
public Enchantment getEnchantment() {
return enchantment;
}
/**
* Retrieve the custom enchantment, or {@link CustomEnchantment#VANILLA} if the LeveledEnchantment
* represents a vanilla enchantment.
* @return The custom enchantment.
*/
public CustomEnchantment getCustom() {
return custom;
}
/**
* Retrieve an enchanter that applies the current enchantment to items.
* @return An enchanter.
*/
public Enchanter getEnchanter() {
if (enchanter == null) {
if (custom == CustomEnchantment.VANILLA)
enchanter = new VanillaEnchanter(enchantment, level);
else if (custom == CustomEnchantment.GLOW)
enchanter = new GlowEnchanter();
else if (custom == CustomEnchantment.NO_ATTRIBUTES)
enchanter = new HideAttributesEnchanter();
else if (custom == CustomEnchantment.NO_DURABILITY)
enchanter = new HideDurabilityEnchanter(level);
else
throw new IllegalStateException("Invalid custom enchantment: " + custom);
}
return enchanter;
}
/**
* Retrieve the level of the enchantment.
* @return The level of the enchantment.
*/
public int getLevel() {
return level;
}
/**
* Determine if the given leveled enchantment is of the same type.
* @param other - the other enchantment.
* @return TRUE if it is, FALSE otherwise.
*/
public boolean sameType(LeveledEnchantment other) {
if (hasCustomEnchantment())
return other.hasCustomEnchantment() && other.getCustom() == custom;
else
return !other.hasCustomEnchantment() && other.getEnchantment() == enchantment;
}
/**
* Determine if this leveled enchantment represents a custom type.
* @return TRUE if it does, FALSE otherwise.
*/
public boolean hasCustomEnchantment() {
return custom != null && custom != CustomEnchantment.VANILLA;
}
@Override
public int hashCode(){
return Objects.hashCode(custom, enchantment, level);
}
@Override
public boolean equals(Object object){
if (object == this)
return true;
if (object instanceof LeveledEnchantment) {
LeveledEnchantment that = (LeveledEnchantment) object;
return this.custom == that.custom &&
this.enchantment == that.enchantment &&
this.level == that.level;
}
return false;
}
@Override
public String toString() {
if (custom == CustomEnchantment.VANILLA)
return enchantment + " " + level;
else
return custom + " " + level;
}
/**
* Parse a leveled enchantment from a given text.
* @param value - space-delimited queue.
* @return The parsed enchantment, or NULL if the input cannot be parsed.
*/
public static LeveledEnchantment parse(Deque<String> args) {
StringBuilder search = new StringBuilder();
String candidate = "";
CustomEnchantment parsedCustom = null;
// Take elements until we are done
while (args.peek() != null) {
if (search.length() > 0)
search.append("_");
search.append(args.poll().toUpperCase());
candidate = search.toString();
parsedCustom = CustomEnchantment.parse(candidate);
// And we're done
if (parsedCustom != null)
break;
if (byName.containsKey(candidate)) {
break;
}
}
// Must specify a level
try {
int level = Integer.parseInt(Joiner.on(" ").join(args).trim());
if (parsedCustom != null)
return new LeveledEnchantment(parsedCustom, level);
else
return new LeveledEnchantment(byName.get(candidate), level);
} catch (NumberFormatException e) {
// Either not a valid level, or not specified
return null;
}
}
}