From 73d496ea840c89a16f336cc55c084f154db4374f Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 9 Nov 2024 16:26:05 -0800
Subject: [PATCH] Improve performance of RecipeMap#removeRecipe (#11547)

---
 ...erformance-of-RecipeMap-removeRecipe.patch | 89 +++++++++++++++++++
 1 file changed, 89 insertions(+)
 create mode 100644 patches/server/Improve-performance-of-RecipeMap-removeRecipe.patch

diff --git a/patches/server/Improve-performance-of-RecipeMap-removeRecipe.patch b/patches/server/Improve-performance-of-RecipeMap-removeRecipe.patch
new file mode 100644
index 0000000000..a555d72f27
--- /dev/null
+++ b/patches/server/Improve-performance-of-RecipeMap-removeRecipe.patch
@@ -0,0 +1,89 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jake Potrebic <jake.m.potrebic@gmail.com>
+Date: Thu, 31 Oct 2024 20:36:41 -0700
+Subject: [PATCH] Improve performance of RecipeMap#removeRecipe
+
+
+diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java
++++ b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java
+@@ -0,0 +0,0 @@ public class RecipeManager extends SimplePreparableReloadListener<RecipeMap> imp
+ 
+     // CraftBukkit start
+     public boolean removeRecipe(ResourceKey<Recipe<?>> mcKey) {
+-        boolean removed = this.recipes.removeRecipe(mcKey);
++        boolean removed = this.recipes.removeRecipe((ResourceKey<Recipe<RecipeInput>>) (ResourceKey) mcKey); // Paper - generic fix
+         if (removed) {
+             this.finalizeRecipeLoading();
+         }
+diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeMap.java b/src/main/java/net/minecraft/world/item/crafting/RecipeMap.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/world/item/crafting/RecipeMap.java
++++ b/src/main/java/net/minecraft/world/item/crafting/RecipeMap.java
+@@ -0,0 +0,0 @@ public class RecipeMap {
+         }
+     }
+ 
+-    public boolean removeRecipe(ResourceKey<Recipe<?>> mcKey) {
+-        boolean removed = false;
+-        Iterator<RecipeHolder<?>> iter = this.byType.values().iterator();
+-        while (iter.hasNext()) {
+-            RecipeHolder<?> recipe = iter.next();
+-            if (recipe.id().equals(mcKey)) {
+-                iter.remove();
+-                removed = true;
+-            }
+-        }
+-        removed |= this.byKey.remove(mcKey) != null;
++    // public boolean removeRecipe(ResourceKey<Recipe<?>> mcKey) {
++    //     boolean removed = false;
++    //     Iterator<RecipeHolder<?>> iter = this.byType.values().iterator();
++    //     while (iter.hasNext()) {
++    //         RecipeHolder<?> recipe = iter.next();
++    //         if (recipe.id().equals(mcKey)) {
++    //             iter.remove();
++    //             removed = true;
++    //         }
++    //     }
++    //     removed |= this.byKey.remove(mcKey) != null;
++    //
++    //     return removed;
++    // }
++    // CraftBukkit end
++
+ 
+-        return removed;
++    // Paper start - replace removeRecipe implementation
++    public <T extends RecipeInput> boolean removeRecipe(ResourceKey<Recipe<T>> mcKey) {
++        //noinspection unchecked
++        final RecipeHolder<Recipe<T>> remove = (RecipeHolder<Recipe<T>>) this.byKey.remove(mcKey);
++        if (remove == null) {
++            return false;
++        }
++        final Collection<? extends RecipeHolder<? extends Recipe<T>>> recipes = this.byType(remove.value().getType());
++        if (recipes.remove(remove)) {
++            return true;
++        }
++        return false;
++        // Paper end - why are you using a loop???
+     }
+-    // CraftBukkit end
++    // Paper end - replace removeRecipe implementation
+ 
+     public <I extends RecipeInput, T extends Recipe<I>> Collection<RecipeHolder<T>> byType(RecipeType<T> type) {
+         return (Collection) this.byType.get(type); // CraftBukkit - decompile error
+diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java b/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java
++++ b/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java
+@@ -0,0 +0,0 @@ public class RecipeIterator implements Iterator<Recipe> {
+     public void remove() {
+         MinecraftServer.getServer().getRecipeManager().recipes.byKey.remove(this.currentRecipe.id()); // Paper - fix removing recipes from RecipeIterator
+         this.recipes.remove();
++        // Paper start - correctly reload recipes
++        MinecraftServer.getServer().getRecipeManager().finalizeRecipeLoading();
++        MinecraftServer.getServer().getPlayerList().reloadRecipes();
++        // Paper end - correctly reload recipes
+     }
+ }