From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Wed, 20 Dec 2017 17:36:49 -0500
Subject: [PATCH] Ability to apply mending to XP API

This allows plugins that give players the ability to apply the experience
points to the Item Mending formula, which will repair an item instead
of giving the player experience points.

Both an API To standalone mend, and apply mending logic to .giveExp has been added.

diff --git a/src/main/java/net/minecraft/server/EnchantmentManager.java b/src/main/java/net/minecraft/server/EnchantmentManager.java
index 1822178e8dd67bb063f5eab60335de9852b9a71c..d96c03a1a164799f49fdb3309594e7592a8d2206 100644
--- a/src/main/java/net/minecraft/server/EnchantmentManager.java
+++ b/src/main/java/net/minecraft/server/EnchantmentManager.java
@@ -246,6 +246,11 @@ public class EnchantmentManager {
         return getEnchantmentLevel(Enchantments.CHANNELING, itemstack) > 0;
     }
 
+    // Paper - OBFHELPER
+    public static @javax.annotation.Nonnull ItemStack getRandomEquippedItemWithEnchant(Enchantment enchantment, EntityLiving entityliving) {
+        Entry<EnumItemSlot, ItemStack> entry = b(enchantment, entityliving);
+        return entry != null ? entry.getValue() : ItemStack.NULL_ITEM;
+    }
     @Nullable
     public static Entry<EnumItemSlot, ItemStack> b(Enchantment enchantment, EntityLiving entityliving) {
         Map<EnumItemSlot, ItemStack> map = enchantment.a(entityliving);
diff --git a/src/main/java/net/minecraft/server/EntityExperienceOrb.java b/src/main/java/net/minecraft/server/EntityExperienceOrb.java
index b3edb69a967058392f5027fbdc7fadff7e1dc6e2..87c6b77ce3b1446893a0d617b63f925a403e09cc 100644
--- a/src/main/java/net/minecraft/server/EntityExperienceOrb.java
+++ b/src/main/java/net/minecraft/server/EntityExperienceOrb.java
@@ -254,10 +254,12 @@ public class EntityExperienceOrb extends Entity {
         }
     }
 
+    public int durToXp(int i) { return b(i); } // Paper OBFHELPER
     private int b(int i) {
         return i / 2;
     }
 
+    public int xpToDur(int i) { return c(i); } // Paper OBFHELPER
     private int c(int i) {
         return i * 2;
     }
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index b999821bbe5cbc5645c9b55eead88c3c65a4c62d..4375eb013953e8fdfdf85aed238f84ba81a75413 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -1018,8 +1018,37 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
         return GameMode.getByValue(getHandle().playerInteractManager.getGameMode().getId());
     }
 
+    // Paper start
     @Override
-    public void giveExp(int exp) {
+    public int applyMending(int amount) {
+        EntityPlayer handle = getHandle();
+        // Logic copied from EntityExperienceOrb and remapped to unobfuscated methods/properties
+        net.minecraft.server.ItemStack itemstack = net.minecraft.server.EnchantmentManager.getRandomEquippedItemWithEnchant(net.minecraft.server.Enchantments.MENDING, handle);
+        if (!itemstack.isEmpty() && itemstack.getItem().usesDurability()) {
+
+            net.minecraft.server.EntityExperienceOrb orb = net.minecraft.server.EntityTypes.EXPERIENCE_ORB.create(handle.world);
+            orb.value = amount;
+            orb.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM;
+            orb.setPositionRaw(handle.locX(), handle.locY(), handle.locZ());
+
+            int i = Math.min(orb.xpToDur(amount), itemstack.getDamage());
+            org.bukkit.event.player.PlayerItemMendEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent(handle, orb, itemstack, i);
+            i = event.getRepairAmount();
+            orb.dead = true;
+            if (!event.isCancelled()) {
+                amount -= orb.durToXp(i);
+                itemstack.setDamage(itemstack.getDamage() - i);
+            }
+        }
+        return amount;
+    }
+
+    @Override
+    public void giveExp(int exp, boolean applyMending) {
+        if (applyMending) {
+            exp = this.applyMending(exp);
+        }
+        // Paper end
         getHandle().giveExp(exp);
     }
 
