package net.glowstone.constants;
import net.glowstone.inventory.MaterialMatcher;
import net.glowstone.util.WeightedRandom.Choice;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.inventory.ItemStack;
/**
* Definitions of enchantment types.
*/
public final class GlowEnchantment extends Enchantment implements Choice {
private static final MaterialMatcher SWORD_OR_AXE = item -> EnchantmentTarget.WEAPON.includes(item)
|| item.equals(Material.WOOD_AXE)
|| item.equals(Material.STONE_AXE)
|| item.equals(Material.IRON_AXE)
|| item.equals(Material.DIAMOND_AXE)
|| item.equals(Material.GOLD_AXE);
private static final MaterialMatcher BASE_TOOLS = item -> item.equals(Material.WOOD_SPADE)
|| item.equals(Material.STONE_SPADE)
|| item.equals(Material.IRON_SPADE)
|| item.equals(Material.DIAMOND_SPADE)
|| item.equals(Material.GOLD_SPADE)
|| item.equals(Material.WOOD_PICKAXE)
|| item.equals(Material.STONE_PICKAXE)
|| item.equals(Material.IRON_PICKAXE)
|| item.equals(Material.DIAMOND_PICKAXE)
|| item.equals(Material.GOLD_PICKAXE)
|| item.equals(Material.WOOD_AXE)
|| item.equals(Material.STONE_AXE)
|| item.equals(Material.IRON_AXE)
|| item.equals(Material.DIAMOND_AXE)
|| item.equals(Material.GOLD_AXE);
private static final MaterialMatcher DIGGING_TOOLS = material -> BASE_TOOLS.matches(material)
|| material == Material.SHEARS;
private static final MaterialMatcher ALL_THINGS = material -> EnchantmentTarget.TOOL.includes(material)
|| EnchantmentTarget.WEAPON.includes(material)
|| EnchantmentTarget.ARMOR.includes(material)
|| material == Material.FISHING_ROD
|| material == Material.BOW
|| material == Material.CARROT_STICK;
private static final int GROUP_NONE = 0;
private static final int GROUP_PROTECT = 1;
private static final int GROUP_ATTACK = 2;
private static final int GROUP_DIG = 3;
private final Impl impl;
private GlowEnchantment(Impl impl) {
super(impl.id);
this.impl = impl;
}
/**
* Register all enchantment types with Enchantment.
*/
public static void register() {
for (Impl impl : Impl.values()) {
registerEnchantment(new GlowEnchantment(impl));
}
stopAcceptingRegistrations();
}
@Override
public String getName() {
// nb: returns enum name, not text name
return impl.name();
}
@Override
public int getMaxLevel() {
return impl.maxLevel;
}
@Override
public int getStartLevel() {
return 1;
}
@Override
public EnchantmentTarget getItemTarget() {
return impl.target;
}
@Override
public boolean conflictsWith(Enchantment other) {
return impl.group != GROUP_NONE && impl.group == ((GlowEnchantment) other).impl.group;
}
@Override
public boolean canEnchantItem(ItemStack item) {
return impl.matcher.matches(item.getType());
}
/**
* The rarity of the enchantment, kept for compatibility with Bukkit.
*
* @see #getRarity()
*/
@Override
public int getWeight() {
return getRarity().getWeight();
}
/**
* Treasure enchantments can only be obtained from chest loot, fishing, or trading for enchanted books.
*
* @return true if the enchantment is a treasure, otherwise false
*/
public boolean isTreasure() {
return impl.treasure;
}
@Override
public boolean isCursed() {
return impl.cursed;
}
/**
* Represents the rarity of obtaining an enchantment.
*
* @return the rarity of the enchantment
*/
public Rarity getRarity() {
return impl.rarity;
}
public boolean isInRange(int level, int modifier) {
return modifier >= impl.getMinRange(level) && modifier <= impl.getMaxRange(level);
}
private enum Impl {
PROTECTION_ENVIRONMENTAL(0, "Protection", 4, Rarity.COMMON, 1, 11, 20, EnchantmentTarget.ARMOR, GROUP_PROTECT),
PROTECTION_FIRE(1, "Fire Protection", 4, Rarity.UNCOMMON, 10, 8, 12, EnchantmentTarget.ARMOR, GROUP_PROTECT),
PROTECTION_FALL(2, "Feather Falling", 4, Rarity.UNCOMMON, 5, 6, 10, EnchantmentTarget.ARMOR_FEET, GROUP_PROTECT),
PROTECTION_EXPLOSIONS(3, "Blast Protection", 4, Rarity.RARE, 5, 8, 12, EnchantmentTarget.ARMOR),
PROTECTION_PROJECTILE(4, "Projectile Protection", 4, Rarity.UNCOMMON, 3, 6, 15, EnchantmentTarget.ARMOR, GROUP_PROTECT),
OXYGEN(5, "Respiration", 3, Rarity.RARE, 10, 10, 30, EnchantmentTarget.ARMOR_HEAD),
WATER_WORKER(6, "Aqua Affinity", 1, Rarity.RARE, 1, 0, 40, EnchantmentTarget.ARMOR_HEAD),
THORNS(7, "Thorns", 3, Rarity.VERY_RARE, 10, 20, 50, false, EnchantmentTarget.ARMOR_TORSO, new MatcherAdapter(EnchantmentTarget.ARMOR)),
DEPTH_STRIDER(8, "Depth Strider", 3, Rarity.RARE, 10, 10, 15, EnchantmentTarget.ARMOR_FEET),
FROST_WALKER(9, "Frost Walker", 2, Rarity.RARE, 10, 10, 15, EnchantmentTarget.ARMOR_FEET),
BINDING_CURSE(10, "Curse of Binding", 1, Rarity.VERY_RARE, true, true, 25, 25, 50, false, EnchantmentTarget.ARMOR, new MatcherAdapter(EnchantmentTarget.ARMOR), GROUP_NONE),
DAMAGE_ALL(16, "Sharpness", 5, Rarity.COMMON, 1, 11, 20, EnchantmentTarget.WEAPON, SWORD_OR_AXE, GROUP_ATTACK),
DAMAGE_UNDEAD(17, "Smite", 5, Rarity.UNCOMMON, 5, 8, 20, EnchantmentTarget.WEAPON, SWORD_OR_AXE, GROUP_ATTACK),
DAMAGE_ARTHROPODS(18, "Bane of Arthropods", 5, Rarity.UNCOMMON, 5, 8, 20, EnchantmentTarget.WEAPON, SWORD_OR_AXE, GROUP_ATTACK),
KNOCKBACK(19, "Knockback", 2, Rarity.UNCOMMON, 5, 20, 50, false, EnchantmentTarget.WEAPON),
FIRE_ASPECT(20, "Fire Aspect", 2, Rarity.RARE, 10, 20, 50, false, EnchantmentTarget.WEAPON),
LOOT_BONUS_MOBS(21, "Looting", 3, Rarity.RARE, 15, 9, 50, false, EnchantmentTarget.WEAPON),
SWEEPING_EDGE(22, "Sweeping Edge", 3, Rarity.RARE, 25, 25, 50, EnchantmentTarget.WEAPON), // TODO: correct range values
DIG_SPEED(32, "Efficiency", 5, Rarity.COMMON, 1, 10, 50, false, EnchantmentTarget.TOOL, DIGGING_TOOLS),
SILK_TOUCH(33, "Silk Touch", 1, Rarity.VERY_RARE, false, 15, 0, 50, false, EnchantmentTarget.TOOL, DIGGING_TOOLS, GROUP_DIG),
DURABILITY(34, "Unbreaking", 3, Rarity.UNCOMMON, 5, 8, 50, false, EnchantmentTarget.TOOL, ALL_THINGS),
LOOT_BONUS_BLOCKS(35, "Fortune", 3, Rarity.RARE, 15, 9, 50, EnchantmentTarget.TOOL, BASE_TOOLS, GROUP_DIG),
ARROW_DAMAGE(48, "Power", 5, Rarity.COMMON, 1, 10, 15, EnchantmentTarget.BOW),
ARROW_KNOCKBACK(49, "Punch", 2, Rarity.RARE, 12, 20, 25, EnchantmentTarget.BOW),
ARROW_FIRE(50, "Flame", 1, Rarity.RARE, 20, 0, 30, EnchantmentTarget.BOW),
ARROW_INFINITE(51, "Infinity", 1, Rarity.VERY_RARE, 20, 0, 30, EnchantmentTarget.BOW),
LUCK(61, "Luck of the Sea", 3, Rarity.RARE, 15, 9, 50, false, EnchantmentTarget.FISHING_ROD),
LURE(62, "Lure", 3, Rarity.RARE, 15, 9, 50, false, EnchantmentTarget.FISHING_ROD),
MENDING(70, "Mending", 1, Rarity.RARE, 25, 25, 50, EnchantmentTarget.ALL),
VANISHING_CURSE(71, "Curse of Vanishing", 1, Rarity.VERY_RARE, true, true, 25, 25, 50, false, EnchantmentTarget.ALL, new MatcherAdapter(EnchantmentTarget.ALL), GROUP_NONE);
private final int id;
private final String name;
private final int maxLevel;
private final EnchantmentTarget target;
private final MaterialMatcher matcher;
private final int group;
private final Rarity rarity;
private final int minValue, minIncrement;
private final int maxIncrement;
private final boolean treasure;
private final boolean simpleRange;
private final boolean cursed;
Impl(int id, String name, int max, Rarity rarity, int minValue, int minInc, int maxInc, EnchantmentTarget target) {
this(id, name, max, rarity, false, minValue, minInc, maxInc, true, target, new MatcherAdapter(target), GROUP_NONE);
}
Impl(int id, String name, int max, Rarity rarity, int minValue, int minInc, int maxInc, boolean simpleRange, EnchantmentTarget target) {
this(id, name, max, rarity, false, minValue, minInc, maxInc, simpleRange, target, new MatcherAdapter(target), GROUP_NONE);
}
Impl(int id, String name, int max, Rarity rarity, int minValue, int minInc, int maxInc, EnchantmentTarget target, int group) {
this(id, name, max, rarity, false, minValue, minInc, maxInc, true, target, new MatcherAdapter(target), group);
}
Impl(int id, String name, int max, Rarity rarity, int minValue, int minInc, int maxInc, boolean simpleRange, EnchantmentTarget target, MaterialMatcher matcher) {
this(id, name, max, rarity, false, minValue, minInc, maxInc, simpleRange, target, matcher, GROUP_NONE);
}
Impl(int id, String name, int max, Rarity rarity, int minValue, int minInc, int maxInc, boolean simpleRange, EnchantmentTarget target, MatcherAdapter matcher) {
this(id, name, max, rarity, false, minValue, minInc, maxInc, simpleRange, target, matcher, GROUP_NONE);
}
Impl(int id, String name, int max, Rarity rarity, int minValue, int minInc, int maxInc, EnchantmentTarget target, MaterialMatcher matcher, int group) {
this(id, name, max, rarity, false, minValue, minInc, maxInc, true, target, matcher, group);
}
Impl(int id, String name, int max, Rarity rarity, boolean treasure, int minValue, int minInc, int maxInc, boolean simpleRange, EnchantmentTarget target, MaterialMatcher matcher, int group) {
this(id, name, max, rarity, treasure, false, minValue, minInc, maxInc, true, target, matcher, group);
}
Impl(int id, String name, int max, Rarity rarity, boolean treasure, boolean cursed, int minValue, int minInc, int maxInc, boolean simpleRange, EnchantmentTarget target, MaterialMatcher matcher, int group) {
this.id = id;
this.name = name;
maxLevel = max;
this.rarity = rarity;
this.target = target;
this.matcher = matcher;
this.group = group;
this.minValue = minValue;
minIncrement = minInc;
maxIncrement = maxInc;
this.simpleRange = simpleRange;
this.treasure = treasure;
this.cursed = cursed;
}
int getMinRange(int modifier) {
modifier = modifier - 1; // Formula depends on input 1 being 0 for "no offset"
return minIncrement * modifier + minValue;
}
int getMaxRange(int modifier) {
return (simpleRange ? getMinRange(modifier) : 1 + modifier * 10) + maxIncrement;
}
}
private static class MatcherAdapter implements MaterialMatcher {
private final EnchantmentTarget target;
public MatcherAdapter(EnchantmentTarget target) {
this.target = target;
}
@Override
public boolean matches(Material material) {
return target.includes(material);
}
}
private enum Rarity {
COMMON(10),
UNCOMMON(5),
RARE(2),
VERY_RARE(1);
private final int weight;
Rarity(int weight) {
this.weight = weight;
}
public int getWeight() {
return weight;
}
}
}