summaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
authorNathan Adams <dinnerbone@dinnerbone.com>2011-11-27 00:26:31 +0000
committerNathan Adams <dinnerbone@dinnerbone.com>2011-11-27 01:35:47 +0000
commitaba0bbc70f156dda47a10a0bfcf56346ad682441 (patch)
treeec0c7c9df8d766cdd8ac0a8c23f04c9a18d8010b /src/main
parent8cb9352259b804f7e83df9eb13f99ea58d5cbf39 (diff)
downloadbukkit-aba0bbc70f156dda47a10a0bfcf56346ad682441.tar
bukkit-aba0bbc70f156dda47a10a0bfcf56346ad682441.tar.gz
bukkit-aba0bbc70f156dda47a10a0bfcf56346ad682441.tar.lz
bukkit-aba0bbc70f156dda47a10a0bfcf56346ad682441.tar.xz
bukkit-aba0bbc70f156dda47a10a0bfcf56346ad682441.zip
Added Enchantment API
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/org/bukkit/enchantments/Enchantment.java229
-rw-r--r--src/main/java/org/bukkit/enchantments/EnchantmentTarget.java46
-rw-r--r--src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java46
-rw-r--r--src/main/java/org/bukkit/inventory/ItemStack.java125
4 files changed, 437 insertions, 9 deletions
diff --git a/src/main/java/org/bukkit/enchantments/Enchantment.java b/src/main/java/org/bukkit/enchantments/Enchantment.java
new file mode 100644
index 00000000..69615817
--- /dev/null
+++ b/src/main/java/org/bukkit/enchantments/Enchantment.java
@@ -0,0 +1,229 @@
+package org.bukkit.enchantments;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.bukkit.inventory.ItemStack;
+
+/**
+ * The various type of enchantments that may be added to armour or weapons
+ */
+public abstract class Enchantment {
+ /**
+ * Provides protection against environmental damage
+ */
+ public static final Enchantment PROTECTION_ENVIRONMENTAL = new EnchantmentWrapper(0);
+
+ /**
+ * Provides protection against fire damage
+ */
+ public static final Enchantment PROTECTION_FIRE = new EnchantmentWrapper(1);
+
+ /**
+ * Provides protection against fall damage
+ */
+ public static final Enchantment PROTECTION_FALL = new EnchantmentWrapper(2);
+
+ /**
+ * Provides protection against explosive damage
+ */
+ public static final Enchantment PROTECTION_EXPLOSIONS = new EnchantmentWrapper(3);
+
+ /**
+ * Provides protection against projectile damage
+ */
+ public static final Enchantment PROTECTION_PROJECTILE = new EnchantmentWrapper(4);
+
+ /**
+ * Decreases the rate of air loss whilst underwater
+ */
+ public static final Enchantment OXYGEN = new EnchantmentWrapper(5);
+
+ /**
+ * Increases the speed at which a player may mine underwater
+ */
+ public static final Enchantment WATER_WORKER = new EnchantmentWrapper(6);
+
+ /**
+ * Increases damage against all targets
+ */
+ public static final Enchantment DAMAGE_ALL = new EnchantmentWrapper(16);
+
+ /**
+ * Increases damage against undead targets
+ */
+ public static final Enchantment DAMAGE_UNDEAD = new EnchantmentWrapper(17);
+
+ /**
+ * Increases damage against arthropod targets
+ */
+ public static final Enchantment DAMAGE_ARTHROPODS = new EnchantmentWrapper(18);
+
+ /**
+ * All damage to other targets will knock them back when hit
+ */
+ public static final Enchantment KNOCKBACK = new EnchantmentWrapper(19);
+
+ /**
+ * When attacking a target, has a chance to set them on fire
+ */
+ public static final Enchantment FIRE_ASPECT = new EnchantmentWrapper(20);
+
+ /**
+ * Provides a chance of gaining extra loot when killing monsters
+ */
+ public static final Enchantment LOOT_BONUS_MOBS = new EnchantmentWrapper(21);
+
+ /**
+ * Increases the rate at which you mine/dig
+ */
+ public static final Enchantment DIG_SPEED = new EnchantmentWrapper(32);
+
+ /**
+ * Allows blocks to drop themselves instead of fragments (for example, stone instead of cobblestone)
+ */
+ public static final Enchantment SILK_TOUCH = new EnchantmentWrapper(33);
+
+ /**
+ * Decreases the rate at which a tool looses durability
+ */
+ public static final Enchantment DURABILITY = new EnchantmentWrapper(34);
+
+ /**
+ * Provides a chance of gaining extra loot when destroying blocks
+ */
+ public static final Enchantment LOOT_BONUS_BLOCKS = new EnchantmentWrapper(35);
+
+ private static final Map<Integer, Enchantment> byId = new HashMap<Integer, Enchantment>();
+ private static final Map<String, Enchantment> byName = new HashMap<String, Enchantment>();
+ private static boolean acceptingNew = true;
+ private final int id;
+
+ public Enchantment(int id) {
+ this.id = id;
+ }
+
+ /**
+ * Gets the unique ID of this enchantment
+ *
+ * @return Unique ID
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Gets the unique name of this enchantment
+ *
+ * @return Unique name
+ */
+ public abstract String getName();
+
+ /**
+ * Gets the maximum level that this Enchantment may become.
+ *
+ * @return Maximum level of the Enchantment
+ */
+ public abstract int getMaxLevel();
+
+ /**
+ * Gets the level that this Enchantment should start at
+ *
+ * @return Starting level of the Enchantment
+ */
+ public abstract int getStartLevel();
+
+ /**
+ * Gets the type of {@link ItemStack} that may fit this Enchantment.
+ *
+ * @return Target type of the Enchantment
+ */
+ public abstract EnchantmentTarget getItemTarget();
+
+ /**
+ * Checks if this Enchantment may be applied to the given {@link ItemStack}
+ *
+ * @param item Item to test
+ * @return True if the enchantment may be applied, otherwise False
+ */
+ public abstract boolean canEnchantItem(ItemStack item);
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof Enchantment)) {
+ return false;
+ }
+ final Enchantment other = (Enchantment) obj;
+ if (this.id != other.id) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return id;
+ }
+
+ @Override
+ public String toString() {
+ return "Enchantment[" + id + ", " + getName() + "]";
+ }
+
+ /**
+ * Registers an enchantment with the given ID and object.
+ * <p>
+ * Generally not to be used from within a plugin.
+ *
+ * @param id ID of the enchantment
+ * @param enchantment Enchantment to register
+ */
+ public static void registerEnchantment(Enchantment enchantment) {
+ if (byId.containsKey(enchantment.id) || byName.containsKey(enchantment.getName())) {
+ throw new IllegalArgumentException("Cannot set already-set enchantment");
+ } else if (!isAcceptingRegistrations()) {
+ throw new IllegalStateException("No longer accepting new enchantments (can only be done by the server implementation)");
+ }
+
+ byId.put(enchantment.id, enchantment);
+ byName.put(enchantment.getName(), enchantment);
+ }
+
+ /**
+ * Checks if this is accepting Enchantment registrations.
+ *
+ * @return True if the server Implementation may add enchantments
+ */
+ public static boolean isAcceptingRegistrations() {
+ return acceptingNew;
+ }
+
+ /**
+ * Stops accepting any enchantment registrations
+ */
+ public static void stopAcceptingRegistrations() {
+ acceptingNew = false;
+ }
+
+ /**
+ * Gets the Enchantment at the specified ID
+ *
+ * @param id ID to fetch
+ * @return Resulting Enchantment, or null if not found
+ */
+ public static Enchantment getById(int id) {
+ return byId.get(id);
+ }
+
+ /**
+ * Gets the Enchantment at the specified name
+ *
+ * @param name Name to fetch
+ * @return Resulting Enchantment, or null if not found
+ */
+ public static Enchantment getByName(String name) {
+ return byName.get(name);
+ }
+}
diff --git a/src/main/java/org/bukkit/enchantments/EnchantmentTarget.java b/src/main/java/org/bukkit/enchantments/EnchantmentTarget.java
new file mode 100644
index 00000000..74d72234
--- /dev/null
+++ b/src/main/java/org/bukkit/enchantments/EnchantmentTarget.java
@@ -0,0 +1,46 @@
+package org.bukkit.enchantments;
+
+/**
+ * Represents the applicable target for a {@link Enchantment}
+ */
+public enum EnchantmentTarget {
+ /**
+ * Allows the Enchantment to be placed on all items
+ */
+ ALL,
+
+ /**
+ * Allows the Enchantment to be placed on armor
+ */
+ ARMOR,
+
+ /**
+ * Allows the Enchantment to be placed on feet slot armor
+ */
+ ARMOR_FEET,
+
+ /**
+ * Allows the Enchantment to be placed on leg slot armor
+ */
+ ARMOR_LEGS,
+
+ /**
+ * Allows the Enchantment to be placed on torso slot armor
+ */
+ ARMOR_TORSO,
+
+ /**
+ * Allows the Enchantment to be placed on head slot armor
+ */
+ ARMOR_HEAD,
+
+ /**
+ * Allows the Enchantment to be placed on weapons (swords)
+ */
+ WEAPON,
+
+ /**
+ * Allows the Enchantment to be placed on tools (spades, pickaxe, hoes, axes)
+ */
+ TOOL;
+}
diff --git a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java
new file mode 100644
index 00000000..842d34a0
--- /dev/null
+++ b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java
@@ -0,0 +1,46 @@
+package org.bukkit.enchantments;
+
+import org.bukkit.inventory.ItemStack;
+
+/**
+ * A simple wrapper for ease of selecting {@link Enchantment}s
+ */
+public class EnchantmentWrapper extends Enchantment {
+ public EnchantmentWrapper(int id) {
+ super(id);
+ }
+
+ /**
+ * Gets the enchantment bound to this wrapper
+ *
+ * @return Enchantment
+ */
+ public Enchantment getEnchantment() {
+ return Enchantment.getById(getId());
+ }
+
+ @Override
+ public int getMaxLevel() {
+ return getEnchantment().getMaxLevel();
+ }
+
+ @Override
+ public int getStartLevel() {
+ return getEnchantment().getStartLevel();
+ }
+
+ @Override
+ public EnchantmentTarget getItemTarget() {
+ return getEnchantment().getItemTarget();
+ }
+
+ @Override
+ public boolean canEnchantItem(ItemStack item) {
+ return getEnchantment().canEnchantItem(item);
+ }
+
+ @Override
+ public String getName() {
+ return getEnchantment().getName();
+ }
+}
diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java
index b948ccdb..18df0b73 100644
--- a/src/main/java/org/bukkit/inventory/ItemStack.java
+++ b/src/main/java/org/bukkit/inventory/ItemStack.java
@@ -1,10 +1,13 @@
package org.bukkit.inventory;
+import com.google.common.collect.ImmutableMap;
import java.io.Serializable;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
+import org.bukkit.enchantments.Enchantment;
import org.bukkit.material.MaterialData;
/**
@@ -15,6 +18,7 @@ public class ItemStack implements Serializable, ConfigurationSerializable {
private int amount = 0;
private MaterialData data = null;
private short durability = 0;
+ private Map<Enchantment, Integer> enchantments = new HashMap<Enchantment, Integer>();
public ItemStack(final int type) {
this(type, 0);
@@ -213,35 +217,138 @@ public class ItemStack implements Serializable, ConfigurationSerializable {
return hash;
}
+ /**
+ * Checks if this ItemStack contains the given {@link Enchantment}
+ *
+ * @param ench Enchantment to test
+ * @return True if this has the given enchantment
+ */
+ public boolean containsEnchantment(Enchantment ench) {
+ return enchantments.containsKey(ench);
+ }
+
+ /**
+ * Gets the level of the specified enchantment on this item stack
+ *
+ * @param ench Enchantment to check
+ * @return Level of the enchantment, or 0
+ */
+ public int getEnchantmentLevel(Enchantment ench) {
+ return enchantments.get(ench);
+ }
+
+ /**
+ * Gets a map containing all enchantments and their levels on this item.
+ *
+ * @return Map of enchantments.
+ */
+ public Map<Enchantment, Integer> getEnchantments() {
+ return ImmutableMap.copyOf(enchantments);
+ }
+
+ /**
+ * Adds the specified {@link Enchantment} to this item stack.
+ * <p>
+ * If this item stack already contained the given enchantment (at any level), it will be replaced.
+ *
+ * @param ench Enchantment to add
+ * @param level Level of the enchantment
+ */
+ public void addEnchantment(Enchantment ench, int level) {
+ if ((level < ench.getStartLevel()) || (level > ench.getMaxLevel())) {
+ throw new IllegalArgumentException("Enchantment level is either too low or too high (given " + level + ", bounds are " + ench.getStartLevel() + " to " + ench.getMaxLevel());
+ } else if (!ench.canEnchantItem(this)) {
+ throw new IllegalArgumentException("Specified enchantment cannot be applied to this itemstack");
+ }
+
+ addUnsafeEnchantment(ench, level);
+ }
+
+ /**
+ * Adds the specified {@link Enchantment} to this item stack.
+ * <p>
+ * If this item stack already contained the given enchantment (at any level), it will be replaced.
+ * <p>
+ * This method is unsafe and will ignore level restrictions or item type. Use at your own
+ * discretion.
+ *
+ * @param ench Enchantment to add
+ * @param level Level of the enchantment
+ */
+ public void addUnsafeEnchantment(Enchantment ench, int level) {
+ enchantments.put(ench, level);
+ }
+
+ /**
+ * Removes the specified {@link Enchantment} if it exists on this item stack
+ *
+ * @param ench Enchantment to remove
+ * @return Previous level, or 0
+ */
+ public int removeEnchantment(Enchantment ench) {
+ Integer previous = enchantments.remove(ench);
+ return (previous == null) ? 0 : previous;
+ }
+
public Map<String, Object> serialize() {
Map<String, Object> result = new LinkedHashMap<String, Object>();
-
+
result.put("type", getType());
-
+
if (durability != 0) {
result.put("damage", durability);
}
-
+
if (amount != 1) {
result.put("amount", amount);
}
-
+
+ Map<Enchantment, Integer> enchants = getEnchantments();
+
+ if (enchants.size() > 0) {
+ Map<String, Integer> safeEnchants = new HashMap<String, Integer>();
+
+ for (Map.Entry<Enchantment, Integer> entry : enchants.entrySet()) {
+ safeEnchants.put(entry.getKey().getName(), entry.getValue());
+ }
+
+ result.put("enchantments", safeEnchants);
+ }
+
return result;
}
-
+
public static ItemStack deserialize(Map<String, Object> args) {
Material type = Material.getMaterial((String)args.get("type"));
short damage = 0;
int amount = 1;
-
+
if (args.containsKey("damage")) {
damage = (Short)args.get("damage");
}
-
+
if (args.containsKey("amount")) {
amount = (Integer)args.get("amount");
}
-
- return new ItemStack(type, amount, damage);
+
+ ItemStack result = new ItemStack(type, amount, damage);
+
+ if (args.containsKey("enchantments")) {
+ Object raw = args.get("enchantments");
+
+ if (raw instanceof Map) {
+ Map<Object, Object> map = (Map<Object, Object>)raw;
+
+ for (Map.Entry<Object, Object> entry : map.entrySet()) {
+ Enchantment enchantment = Enchantment.getByName(entry.getKey().toString());
+
+ if ((enchantment != null) && (entry.getValue() instanceof Integer)) {
+ result.addEnchantment(enchantment, (Integer)entry.getValue());
+ }
+ }
+ }
+ }
+
+ return result;
}
}