aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/1061-Improve-performance-of-mass-crafts.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/server/1061-Improve-performance-of-mass-crafts.patch')
-rw-r--r--patches/server/1061-Improve-performance-of-mass-crafts.patch92
1 files changed, 92 insertions, 0 deletions
diff --git a/patches/server/1061-Improve-performance-of-mass-crafts.patch b/patches/server/1061-Improve-performance-of-mass-crafts.patch
new file mode 100644
index 0000000000..57f901bc5f
--- /dev/null
+++ b/patches/server/1061-Improve-performance-of-mass-crafts.patch
@@ -0,0 +1,92 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jake Potrebic <[email protected]>
+Date: Sun, 13 Aug 2023 15:41:52 -0700
+Subject: [PATCH] Improve performance of mass crafts
+
+When the server crafts all available items in CraftingMenu or InventoryMenu the game
+checks either 4 or 9 times for each individual craft for a matching recipe for that container.
+This check can be expensive if 64 total crafts are being performed with the recipe matching logic
+being run 64 * 9 + 64 times. A breakdown of those times is below. This patch caches the last matching
+recipe so that it is checked first and only if it doesn't match does the rest of the matching logic run.
+
+Shift-click crafts are processed one at a time, so shift clicking on an item in the result of a iron block craft
+where all the 9 inputs are full stacks of iron will run 64 iron block crafts. For each of those crafts, the
+'remaining' blocks are calculated. This is due to recipes that have leftover items like buckets. This is done
+for each craft, and done once to get the full 9 leftover items which are usually air. Then 1 item is removed
+from each of the 9 inputs and each time that happens, logic is triggered to update the result itemstack. So
+for each craft, that logic is run 9 times (hence the 64 * 9). The + 64 is from the 64 checks for remaining items.
+
+After this patch, the full iteration over all recipes checking for a match should run once for a full craft to find the
+initial recipe match. Then that recipe will be checked first for all future recipe match checks.
+
+diff --git a/src/main/java/net/minecraft/world/inventory/CraftingContainer.java b/src/main/java/net/minecraft/world/inventory/CraftingContainer.java
+index 779d107a4d07820529273af5931421c09d1dc27f..4f6c8c43f5150e340704682accfbe2a5b1c5db19 100644
+--- a/src/main/java/net/minecraft/world/inventory/CraftingContainer.java
++++ b/src/main/java/net/minecraft/world/inventory/CraftingContainer.java
+@@ -18,11 +18,11 @@ public interface CraftingContainer extends Container, StackedContentsCompatible
+ List<ItemStack> getItems();
+
+ // CraftBukkit start
+- default RecipeHolder<?> getCurrentRecipe() {
++ default RecipeHolder<net.minecraft.world.item.crafting.CraftingRecipe> getCurrentRecipe() { // Paper - use correct generic
+ return null;
+ }
+
+- default void setCurrentRecipe(RecipeHolder<?> recipe) {
++ default void setCurrentRecipe(RecipeHolder<net.minecraft.world.item.crafting.CraftingRecipe> recipe) { // Paper - use correct generic
+ }
+ // CraftBukkit end
+
+diff --git a/src/main/java/net/minecraft/world/inventory/CraftingMenu.java b/src/main/java/net/minecraft/world/inventory/CraftingMenu.java
+index 6b3006a8543265664a2e54898ece92c66afb9c21..2e4043248c3ac7a54d894d76b99adc26518d3866 100644
+--- a/src/main/java/net/minecraft/world/inventory/CraftingMenu.java
++++ b/src/main/java/net/minecraft/world/inventory/CraftingMenu.java
+@@ -56,6 +56,7 @@ public class CraftingMenu extends AbstractCraftingMenu {
+ CraftingInput craftinginput = craftingInventory.asCraftInput();
+ ServerPlayer entityplayer = (ServerPlayer) player;
+ ItemStack itemstack = ItemStack.EMPTY;
++ if (recipe == null) recipe = craftingInventory.getCurrentRecipe(); // Paper - Perf: Improve mass crafting; check last recipe used first
+ Optional<RecipeHolder<CraftingRecipe>> optional = world.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftinginput, world, recipe);
+ craftingInventory.setCurrentRecipe(optional.orElse(null)); // CraftBukkit
+
+diff --git a/src/main/java/net/minecraft/world/inventory/ResultSlot.java b/src/main/java/net/minecraft/world/inventory/ResultSlot.java
+index 1ea4f0800598a75ba74ce033378749d1abe4009b..ff30071f3ef37d1b28cf86e26ce4f7477335a07a 100644
+--- a/src/main/java/net/minecraft/world/inventory/ResultSlot.java
++++ b/src/main/java/net/minecraft/world/inventory/ResultSlot.java
+@@ -72,7 +72,7 @@ public class ResultSlot extends Slot {
+ private NonNullList<ItemStack> getRemainingItems(CraftingInput input, Level world) {
+ return world instanceof ServerLevel serverLevel
+ ? serverLevel.recipeAccess()
+- .getRecipeFor(RecipeType.CRAFTING, input, serverLevel)
++ .getRecipeFor(RecipeType.CRAFTING, input, serverLevel, this.craftSlots.getCurrentRecipe()) // Paper - Perf: Improve mass crafting; check last recipe used first
+ .map(recipe -> recipe.value().getRemainingItems(input))
+ .orElseGet(() -> copyAllInputItems(input))
+ : CraftingRecipe.defaultCraftingReminder(input);
+diff --git a/src/main/java/net/minecraft/world/inventory/TransientCraftingContainer.java b/src/main/java/net/minecraft/world/inventory/TransientCraftingContainer.java
+index 32d49d759f95d27ca04b843bbb2c2fd22ebd7e4a..a458f7b8270dc1d5902e0d131dbf9e66209e26be 100644
+--- a/src/main/java/net/minecraft/world/inventory/TransientCraftingContainer.java
++++ b/src/main/java/net/minecraft/world/inventory/TransientCraftingContainer.java
+@@ -27,7 +27,7 @@ public class TransientCraftingContainer implements CraftingContainer {
+
+ // CraftBukkit start - add fields
+ public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
+- private RecipeHolder<?> currentRecipe;
++ private RecipeHolder<net.minecraft.world.item.crafting.CraftingRecipe> currentRecipe; // Paper - use correct generic
+ public Container resultInventory;
+ private Player owner;
+ private int maxStack = MAX_STACK;
+@@ -72,12 +72,12 @@ public class TransientCraftingContainer implements CraftingContainer {
+ }
+
+ @Override
+- public RecipeHolder<?> getCurrentRecipe() {
++ public RecipeHolder<net.minecraft.world.item.crafting.CraftingRecipe> getCurrentRecipe() { // Paper - use correct generic
+ return this.currentRecipe;
+ }
+
+ @Override
+- public void setCurrentRecipe(RecipeHolder<?> currentRecipe) {
++ public void setCurrentRecipe(RecipeHolder<net.minecraft.world.item.crafting.CraftingRecipe> currentRecipe) { // Paper - use correct generic
+ this.currentRecipe = currentRecipe;
+ }
+