From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Sun, 19 Apr 2020 00:17:56 -0500
Subject: [PATCH] Anvil API


diff --git a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java
index 3070ad3a4bbe83485c6b4a68aa634045c70cafdd..ddfb89d62d2ec316683e9f0f5550e298ab26d137 100644
--- a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java
@@ -2,8 +2,12 @@ package net.minecraft.world.inventory;
 
 import java.util.Iterator;
 import java.util.Map;
+import net.minecraft.nbt.IntTag;
 import net.minecraft.network.chat.Component;
 import net.minecraft.network.chat.TextComponent;
+import net.minecraft.network.protocol.game.ClientboundContainerSetDataPacket;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
+import net.minecraft.server.level.ServerPlayer;
 import net.minecraft.tags.BlockTags;
 import net.minecraft.tags.Tag;
 import net.minecraft.world.entity.player.Inventory;
@@ -42,6 +46,8 @@ public class AnvilMenu extends ItemCombinerMenu {
     public int maximumRepairCost = 40;
     private CraftInventoryView bukkitEntity;
     // CraftBukkit end
+    public boolean bypassCost = false; // Purpur
+    public boolean canDoUnsafeEnchants = false; // Purpur
 
     public AnvilMenu(int syncId, Inventory inventory) {
         this(syncId, inventory, ContainerLevelAccess.NULL);
@@ -60,12 +66,14 @@ public class AnvilMenu extends ItemCombinerMenu {
 
     @Override
     protected boolean mayPickup(Player player, boolean present) {
-        return (player.getAbilities().instabuild || player.experienceLevel >= this.cost.get()) && this.cost.get() > 0;
+        return (player.getAbilities().instabuild || player.experienceLevel >= this.cost.get()) && (bypassCost || this.cost.get() > 0); // Purpur
     }
 
     @Override
     protected void onTake(Player player, ItemStack stack) {
+        if (net.pl3x.purpur.event.inventory.AnvilTakeResultEvent.getHandlerList().getRegisteredListeners().length > 0) new net.pl3x.purpur.event.inventory.AnvilTakeResultEvent(player.getBukkitEntity(), getBukkitView(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack)).callEvent(); // Purpur
         if (!player.getAbilities().instabuild) {
+            if (bypassCost) ((ServerPlayer) player).lastSentExp = -1; else // Purpur
             player.giveExperienceLevels(-this.cost.get());
         }
 
@@ -116,6 +124,12 @@ public class AnvilMenu extends ItemCombinerMenu {
 
     @Override
     public void createResult() {
+        // Purpur start
+        bypassCost = false;
+        canDoUnsafeEnchants = false;
+        if (net.pl3x.purpur.event.inventory.AnvilUpdateResultEvent.getHandlerList().getRegisteredListeners().length > 0) new net.pl3x.purpur.event.inventory.AnvilUpdateResultEvent(getBukkitView()).callEvent();
+        // Purpur end
+
         ItemStack itemstack = this.inputSlots.getItem(0);
 
         this.cost.set(1);
@@ -192,7 +206,7 @@ public class AnvilMenu extends ItemCombinerMenu {
                             int i2 = (Integer) map1.get(enchantment);
 
                             i2 = l1 == i2 ? i2 + 1 : Math.max(i2, l1);
-                            boolean flag3 = enchantment.canEnchant(itemstack);
+                            boolean flag3 = canDoUnsafeEnchants || enchantment.canEnchant(itemstack); // Purpur
 
                             if (this.player.getAbilities().instabuild || itemstack.is(Items.ENCHANTED_BOOK)) {
                                 flag3 = true;
@@ -204,7 +218,7 @@ public class AnvilMenu extends ItemCombinerMenu {
                                 Enchantment enchantment1 = (Enchantment) iterator1.next();
 
                                 if (enchantment1 != enchantment && !enchantment.isCompatibleWith(enchantment1)) {
-                                    flag3 = false;
+                                    flag3 = canDoUnsafeEnchants; // Purpur
                                     ++i;
                                 }
                             }
@@ -275,6 +289,13 @@ public class AnvilMenu extends ItemCombinerMenu {
                 this.cost.set(this.maximumRepairCost - 1); // CraftBukkit
             }
 
+            // Purpur start
+            if (bypassCost && cost.get() >= maximumRepairCost) {
+                itemstack.addTagElement("Purpur.realCost", IntTag.valueOf(cost.get()));
+                cost.set(maximumRepairCost - 1);
+            }
+            // Purpur end
+
             if (this.cost.get() >= this.maximumRepairCost && !this.player.getAbilities().instabuild) { // CraftBukkit
                 itemstack1 = ItemStack.EMPTY;
             }
@@ -296,6 +317,12 @@ public class AnvilMenu extends ItemCombinerMenu {
 
             org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(this.getBukkitView(), itemstack1); // CraftBukkit
             this.broadcastChanges();
+            // Purpur start
+            if (canDoUnsafeEnchants && itemstack1 != ItemStack.EMPTY) {
+                ((ServerPlayer) player).connection.send(new ClientboundContainerSetSlotPacket(containerId, incrementStateId(), 2, itemstack1));
+                ((ServerPlayer) player).connection.send(new ClientboundContainerSetDataPacket(containerId, 0, cost.get()));
+            }
+            // Purpur end
         }
     }
 
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java
index 3ff03e3e8c723d0f2a7c115d4dba01f1b3c2c46e..4dc71c761371400fb92e6943ba44bf40968dae97 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java
@@ -9,7 +9,7 @@ import org.bukkit.inventory.AnvilInventory;
 public class CraftInventoryAnvil extends CraftResultInventory implements AnvilInventory {
 
     private final Location location;
-    private final AnvilMenu container;
+    public final AnvilMenu container; // Purpur - private -> public
 
     public CraftInventoryAnvil(Location location, Container inventory, Container resultInventory, AnvilMenu container) {
         super(inventory, resultInventory);
@@ -47,4 +47,26 @@ public class CraftInventoryAnvil extends CraftResultInventory implements AnvilIn
         Preconditions.checkArgument(levels >= 0, "Maximum repair cost must be positive (or 0)");
         container.maximumRepairCost = levels;
     }
+
+    // Purpur start
+    @Override
+    public boolean canBypassCost() {
+        return container.bypassCost;
+    }
+
+    @Override
+    public void setBypassCost(boolean bypassCost) {
+        container.bypassCost = bypassCost;
+    }
+
+    @Override
+    public boolean canDoUnsafeEnchants() {
+        return container.canDoUnsafeEnchants;
+    }
+
+    @Override
+    public void setDoUnsafeEnchants(boolean canDoUnsafeEnchants) {
+        container.canDoUnsafeEnchants = canDoUnsafeEnchants;
+    }
+    // Purpur end
 }
