diff --git a/pom.xml b/pom.xml
index 32ddae5..858cdef 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,14 +14,14 @@
org.spigotmc
spigot-api
- 1.10-R0.1-SNAPSHOT
+ 1.11.2-R0.1-SNAPSHOT
provided
org.bukkit
- bukkit
- 1.10-R0.1-SNAPSHOT
+ craftbukkit
+ 1.11.2-R0.1-SNAPSHOT
provided
diff --git a/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java b/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java
index 46f6213..ce7e95d 100644
--- a/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java
+++ b/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java
@@ -15,6 +15,7 @@ public class ArmoredElytra extends EnchantPlugin implements Listener {
Bukkit.getPluginManager().registerEvents(new EventHandlers(this), this);
}
+ // TODO: Remove this after updating elytras on my server.
@Override
public void registerEnchantments() {
EnchantmentAPI.registerCustomEnchantment(new DiamondArmor());
diff --git a/src/main/java/nl/pim16aap2/armoredElytra/EventHandlers.java b/src/main/java/nl/pim16aap2/armoredElytra/EventHandlers.java
index e8d2843..02b77be 100644
--- a/src/main/java/nl/pim16aap2/armoredElytra/EventHandlers.java
+++ b/src/main/java/nl/pim16aap2/armoredElytra/EventHandlers.java
@@ -1,10 +1,11 @@
package nl.pim16aap2.armoredElytra;
+import java.util.Arrays;
import java.util.Map;
import java.util.Random;
import org.bukkit.Material;
-import org.bukkit.attribute.Attribute;
+import org.bukkit.craftbukkit.v1_11_R1.inventory.CraftItemStack;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -15,20 +16,38 @@ import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.AnvilInventory;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.EnchantmentStorageMeta;
+import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.scheduler.BukkitRunnable;
+import net.minecraft.server.v1_11_R1.*;
+
import com.rit.sucy.EnchantmentAPI;
import net.md_5.bungee.api.ChatColor;
public class EventHandlers implements Listener {
+ private int DIAMONDS_TO_FULL = 3;
+ private int LEATHER_TO_FULL = 4;
private final ArmoredElytra plugin;
+ private String[] allowedEnchantments = {"DURABILITY",
+ "PROTECTION_FIRE",
+ "PROTECTION_EXPLOSIONS",
+ "PROTECTION_PROJECTILE",
+ "PROTECTION_ENVIRONMENTAL",
+ "DIAMOND_ARMOR_ITEMS",
+ "THORNS"};
+ private String[] specialEnchantments = {"MENDING",
+ "VANISHING_CURSE",
+ "BINDING_CURSE"};
public EventHandlers(ArmoredElytra plugin) {
this.plugin = plugin;
}
+
+
// Clear the anvil's inventory (destroy all the items in all 3 slots (second slot is not emptied, when repairing you can safely give multiple items)).
public void cleanAnvil(AnvilInventory anvilInventory){
anvilInventory.getItem(0).setAmount(0);
@@ -36,13 +55,105 @@ public class EventHandlers implements Listener {
anvilInventory.getItem(2).setAmount(0);
}
- // Check if the elytra being checked is an armored one.
- public boolean isArmoredElytra(ItemStack elytra) {
- if (EnchantmentAPI.itemHasEnchantment(elytra, "Diamond Armor Tier")) {
- return true;
+
+
+ // Check if the enchantment is allowed on elytras.
+ public boolean isAllowedEnchantment(Enchantment enchant) {
+ for (String s : allowedEnchantments) {
+ if (Enchantment.getByName(s).equals(enchant)) {
+ return true;
+ }
}
return false;
- }
+ }
+
+
+
+ // Check if the enchantment is "special", i.e. cannot be enchanted by the EnchantmentAPI.
+ public boolean isSpecialEnchantment(Enchantment enchant) {
+ for (String s : specialEnchantments) {
+ if (Enchantment.getByName(s).equals(enchant)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+
+ // Check if the elytra being checked is an armored one.
+ public boolean isArmoredElytra(ItemStack elytra) {
+ if (elytra.hasItemMeta() && elytra.getType() == Material.ELYTRA)
+ if (elytra.getItemMeta().hasLore())
+ if (elytra.getItemMeta().getLore().toString().equals("[This is an armored Elytra.]")) {
+ return true;
+ }
+ return false;
+ }
+
+
+
+ // Copy enchants of 2 items to one item.
+ public ItemStack addEnchants(ItemStack itemOne, ItemStack itemTwo, Player p) {
+ // Create the resulting item and apply the diamond armor tier enchantment to it.
+ ItemStack result = itemOne.clone();
+
+ // Get the enchantments of the first and second item in the anvil.
+ Map enchantments0 = itemOne.getEnchantments();
+ Map enchantments1 = itemTwo.getEnchantments();
+ // Enchants from enchanted books have to be access in a different way.
+ if (itemTwo.getType() == Material.ENCHANTED_BOOK && isArmoredElytra(itemOne)) {
+ EnchantmentStorageMeta meta = (EnchantmentStorageMeta)itemTwo.getItemMeta();
+ enchantments1 = meta.getStoredEnchants();
+ }
+
+ // Copy enchantments from item1 to result.
+ if (enchantments1!=null) {
+ for (Map.Entry entry : enchantments1.entrySet()) {
+ if (isSpecialEnchantment(entry.getKey()) && !result.containsEnchantment(entry.getKey())) {
+ result.addEnchantment(entry.getKey(), entry.getValue());
+ } else if (isAllowedEnchantment(entry.getKey())) {
+ int enchantLevel = entry.getValue();
+ // If item0 and item1 both have the same enchantment at the same level, result has level+1.
+ // If item0 and item1 both have the same enchantment at different levels, give the highest level to result.
+ if (enchantments0 != null) {
+ for (Map.Entry rentry : enchantments0.entrySet()) {
+ if (entry.getKey().getName() == rentry.getKey().getName()) {
+ if (entry.getValue() == rentry.getValue() && entry.getValue() < entry.getKey().getMaxLevel()) {
+ enchantLevel = entry.getValue()+1;
+ } else if (entry.getValue() < rentry.getValue()) {
+ enchantLevel = rentry.getValue();
+ }
+ }
+ }
+ }
+ EnchantmentAPI.getEnchantment(entry.getKey().getName()).addToItem(result, enchantLevel);
+ } else {
+ p.sendMessage(ChatColor.RED+"This enchantment is not allowed on this item!");
+ }
+ }
+ }
+
+ return result;
+ }
+
+
+
+ // Copy enchants of 2 items to one item.
+ public ItemStack repairItem(ItemStack one, ItemStack two) {
+ // Create the resulting item.
+ ItemStack result = one.clone();
+
+ int mult = two.getType() == Material.DIAMOND ? 100/DIAMONDS_TO_FULL : 100/LEATHER_TO_FULL;
+ int maxDurability = one.getType().getMaxDurability();
+ int durability = one.getDurability();
+ int newDurability = (durability - (int) (maxDurability*mult));
+ result.setDurability((short) (newDurability >= 0 ? newDurability : 0) );
+
+ return result;
+ }
+
+
// Handle the anvil related parts.
@EventHandler
@@ -65,118 +176,89 @@ public class EventHandlers implements Listener {
// Clean the anvil's inventory after transferring the items.
cleanAnvil(anvilInventory);
}
- }
+ }
new BukkitRunnable() {
@Override
public void run() {
// Check if there are items in both input slots.
- if (anvilInventory.getItem(0) != null && anvilInventory.getItem(1) != null) {
+ if (anvilInventory.getItem(0) != null && anvilInventory.getItem(1) != null) {
// Check if the first input slot contains an elytra.
if (anvilInventory.getItem(0).getType() == Material.ELYTRA) {
+ ItemStack result = null;
// Check if the second input slot contains a diamond chestplate.
- if (anvilInventory.getItem(1).getType() == Material.DIAMOND_CHESTPLATE) {
-
- // Get the enchantments of the first and second item in the anvil.
- Map enchantments0 = anvilInventory.getItem(0).getEnchantments();
- Map enchantments1 = anvilInventory.getItem(1).getEnchantments();
-
- // Create the resulting item and apply the diamond armor tier enchantment to it.
- ItemStack result = new ItemStack(Material.ELYTRA, 1);
- EnchantmentAPI.getEnchantment("Diamond Armor Tier").addToItem(result, 1);
-
- // Copy enchantments from item0 to result.
- if (enchantments0!=null) {
- for (Map.Entry entry : enchantments0.entrySet()) {
- if (entry.getKey().getName().equals("MENDING") || entry.getKey().getName().equals("VANISHING_CURSE") || entry.getKey().getName().equals("VANISHING_CURSE")) {
- result.addEnchantment(entry.getKey(), 1);
- } else {
- EnchantmentAPI.getEnchantment(entry.getKey().getName()).addToItem(result, 1);
- }
- }
- }
- // Copy enchantments from item1 to result.
- if (enchantments1!=null) {
- for (Map.Entry entry : enchantments1.entrySet()) {
- if (entry.getKey().getName().equals("MENDING") || entry.getKey().getName().equals("VANISHING_CURSE") || entry.getKey().getName().equals("VANISHING_CURSE"))
- result.addEnchantment(entry.getKey(), 1);
- else {
- Map resultEnchantments = result.getEnchantments();
- int enchantLevel = entry.getValue();
- // If item0 and item1 both have the same enchantment at the same level, result has level+1.
- // If item0 and item1 both have the same enchantment at different levels, give the highest level to result.
- if (resultEnchantments != null) {
- for (Map.Entry rentry : resultEnchantments.entrySet()) {
- if (entry.getKey().getName() == rentry.getKey().getName()) {
- if (entry.getValue() == rentry.getValue() && entry.getValue()<5) {
- enchantLevel = entry.getValue()+1;
- } else if (entry.getValue() < rentry.getValue()) {
- enchantLevel = rentry.getValue();
- }
- }
- }
- }
- if (!entry.getKey().getName().equals("MENDING") && !entry.getKey().getName().equals("VANISHING_CURSE") && !entry.getKey().getName().equals("VANISHING_CURSE"))
- EnchantmentAPI.getEnchantment(entry.getKey().getName()).addToItem(result, enchantLevel);
- }
- }
- }
- // Resulting item will have full durability.
- result.setDurability((short) 0);
- // Add resulting item in the second slot of the anvil.
- anvilInventory.setItem(2, result);
-
+ if (anvilInventory.getItem(1).getType() == Material.DIAMOND_CHESTPLATE ||
+ (anvilInventory.getItem(1).getType() == Material.ENCHANTED_BOOK && isArmoredElytra(anvilInventory.getItem(0)))) {
+ // Combine the enchantments of the two items in the input slots.
+ result = addEnchants(anvilInventory.getItem(0), anvilInventory.getItem(1), p);
+ if (anvilInventory.getItem(1).getType() == Material.DIAMOND_CHESTPLATE) {
+ result.setDurability((short)0);
+ }
+ }
// If the player tries to repair an armored elytra with diamonds or a regular elytra with leather, repair 52% or 26%.
- } else if ((anvilInventory.getItem(1).getType() == Material.LEATHER && !isArmoredElytra(anvilInventory.getItem(0))) ||
- (anvilInventory.getItem(1).getType() == Material.DIAMOND && isArmoredElytra(anvilInventory.getItem(0)))) {
- int mult = anvilInventory.getItem(1).getType() == Material.DIAMOND ? 2 : 1;
- ItemStack result = anvilInventory.getItem(0).clone();
- int maxDurability = anvilInventory.getItem(0).getType().getMaxDurability();
- int durability = anvilInventory.getItem(0).getDurability();
- int newDurability = (durability - (int) (maxDurability*0.26*mult));
- result.setDurability((short) (newDurability >= 0 ? newDurability : 0) );
- // Add resulting item in the second slot of the anvil.
- anvilInventory.setItem(2, result);
-
+ else if ((anvilInventory.getItem(1).getType() == Material.LEATHER && !isArmoredElytra(anvilInventory.getItem(0))) ||
+ (anvilInventory.getItem(1).getType() == Material.DIAMOND && isArmoredElytra(anvilInventory.getItem(0)))) {
+ // Repair the item in the first input slot with items from the second input slot.
+ result = repairItem(anvilInventory.getItem(0), anvilInventory.getItem(1));
+ }
// Otherwise, remove the item in the result slot (slot2).
- } else {
+ else {
if (anvilInventory.getItem(2)!=null) {
anvilInventory.getItem(2).setAmount(0);
}
}
- // update inventory to show changes made to the anvil's inventory.
- p.updateInventory();
+ // Put the created item in the second slot of the anvil.
+ if (result!=null) {
+ if (anvilInventory.getItem(1).getType() == Material.DIAMOND_CHESTPLATE/* || isArmoredElytra(anvilInventory.getItem(0))*/) {
+ ItemMeta itemmeta = result.getItemMeta();
+ itemmeta.setDisplayName(ChatColor.AQUA+"Armored Elytra");
+ itemmeta.setLore(Arrays.asList("This is an armored Elytra."));
+ result.setItemMeta(itemmeta);
+ net.minecraft.server.v1_11_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(result);
+ NBTTagCompound compound = (nmsStack.hasTag()) ? nmsStack.getTag() : new NBTTagCompound();
+ NBTTagList modifiers = new NBTTagList();
+ NBTTagCompound armor = new NBTTagCompound();
+ armor.set("AttributeName", new NBTTagString("generic.armor"));
+ armor.set("Name", new NBTTagString("generic.armor"));
+ armor.set("Amount", new NBTTagInt(8));
+ armor.set("Operation", new NBTTagInt(0));
+ armor.set("UUIDLeast", new NBTTagInt(894654));
+ armor.set("UUIDMost", new NBTTagInt(2872));
+ armor.set("Slot", new NBTTagString("chest"));
+ modifiers.add(armor);
+ NBTTagCompound armorTough = new NBTTagCompound();
+ armorTough.set("AttributeName", new NBTTagString("generic.armorToughness"));
+ armorTough.set("Name", new NBTTagString("generic.armorToughness"));
+ armorTough.set("Amount", new NBTTagInt(2));
+ armorTough.set("Operation", new NBTTagInt(0));
+ armorTough.set("UUIDLeast", new NBTTagInt(894654));
+ armorTough.set("UUIDMost", new NBTTagInt(2872));
+ armorTough.set("Slot", new NBTTagString("chest"));
+ modifiers.add(armorTough);
+ compound.set("AttributeModifiers", modifiers);
+ result = CraftItemStack.asBukkitCopy(nmsStack);
+ }
+ anvilInventory.setItem(2, result);
+ }
}
- }
+ // Super ugly way of making sure that when applying enchantments from an enchanted book to an elytra, the result has a higher chance of showing up.
+ if (anvilInventory.getItem(1).getType() == Material.ENCHANTED_BOOK) {
+ p.updateInventory();
+ p.updateInventory();
+ p.updateInventory();
+ p.updateInventory();
+ p.updateInventory();
+ p.updateInventory();
+ p.sendMessage(ChatColor.GREEN+"Combining enchanted books with elytras IS possible, but sometimes you have to remove the book and put it back a few times.");
+ }
+ }
+ p.updateInventory();
}
- // Do all this with a slight delay, so the resulting item shows up in the final slot properly.
}.runTaskLater(this.plugin, 1);
}
}
}
- // Calculate the toughness of the player's armor. 2 Points per part of diamond armor (and 2 for armored elytra's... duh...).
- public double getArmorToughness(Player p) {
- double toughness = 0;
- if (p.getInventory().getBoots()!=null)
- if (p.getInventory().getBoots().getType() == Material.DIAMOND_BOOTS) {
- toughness+=2;
- }
- if (p.getInventory().getHelmet()!=null)
- if (p.getInventory().getHelmet().getType() == Material.DIAMOND_HELMET) {
- toughness+=2;
- }
- if (p.getInventory().getLeggings()!=null)
- if (p.getInventory().getLeggings().getType() == Material.DIAMOND_LEGGINGS) {
- toughness+=2;
- }
- if (p.getInventory().getChestplate()!=null)
- if (p.getInventory().getChestplate().getType() == Material.DIAMOND_CHESTPLATE ||
- (p.getInventory().getChestplate().getType() == Material.ELYTRA && isArmoredElytra(p.getInventory().getChestplate()))) {
- toughness+=2;
- }
- return toughness;
- }
// Because the armored elytra doesn't actually give any armor, the damage received by players wearing an armored elytra is calculated here.
@@ -187,26 +269,12 @@ public class EventHandlers implements Listener {
if (p.getInventory().getChestplate()!=null) {
if (p.getInventory().getChestplate().getType() == Material.ELYTRA && isArmoredElytra(p.getInventory().getChestplate())) {
DamageCause cause = e.getCause();
- if (cause!=DamageCause.DROWNING && cause!=DamageCause.LIGHTNING && cause!=DamageCause.STARVATION && cause!=DamageCause.SUFFOCATION && cause!=DamageCause.FALL && cause!=DamageCause.SUICIDE && cause!=DamageCause.FIRE_TICK && cause!=DamageCause.FIRE && cause!=DamageCause.FLY_INTO_WALL && cause!=DamageCause.POISON) {
- double damage = e.getDamage();
- // Get the defense points of the player (armor rating), then add 8 (value of diamond chestplate).
- double defensePoints = p.getAttribute(Attribute.GENERIC_ARMOR).getValue()+8;
- double toughness = getArmorToughness(p);
- // Calculate new damage based on formula found on the wiki.
- double newDamage = e.getDamage() * (1-Math.min(20, Math.max(defensePoints/5, defensePoints-e.getDamage()/(2+toughness/4)))/25);
-
- e.setDamage(EntityDamageEvent.DamageModifier.ABSORPTION, 0);
- e.setDamage(EntityDamageEvent.DamageModifier.ARMOR, 0);
- e.setDamage(EntityDamageEvent.DamageModifier.BLOCKING, 0);
-// e.setDamage(EntityDamageEvent.DamageModifier.HARD_HAT, 0);
- e.setDamage(EntityDamageEvent.DamageModifier.MAGIC, 0);
- e.setDamage(EntityDamageEvent.DamageModifier.RESISTANCE, 0);
- // Base is now the final damage. Why u no have setFinalDamage?
- e.setDamage(EntityDamageEvent.DamageModifier.BASE, newDamage);
+ if (cause!=DamageCause.DROWNING && cause!=DamageCause.STARVATION && cause!=DamageCause.SUFFOCATION &&
+ cause!=DamageCause.SUICIDE && cause!=DamageCause.FLY_INTO_WALL && cause!=DamageCause.POISON) {
- int durability = p.getInventory().getChestplate().getDurability();
+ int durability = p.getInventory().getChestplate().getDurability();
int maxDurability = p.getInventory().getChestplate().getType().getMaxDurability();
- int newDurability = (int) (durability + ((int)(damage/4) > 1 ? (int)(damage/4) : 1));
+ int newDurability = (int) (durability + ((int)(e.getDamage()/4) > 1 ? (int)(e.getDamage()/4) : 1));
// If the elytra has the durability enchantment.
if (p.getInventory().getChestplate().containsEnchantment(Enchantment.DURABILITY)) {
@@ -232,12 +300,16 @@ public class EventHandlers implements Listener {
}
}
+
+
// Remove item from player's chestplate slot and puts it in their normal inventory.
public void enquipChestPlayer(Player p) {
p.getInventory().addItem(p.getInventory().getChestplate());
p.getInventory().getChestplate().setAmount(0);
}
+
+
// Check if the player is trying to equip a broken elytra (and prevent that).
@EventHandler
public void playerEquipsArmor(InventoryClickEvent e){