diff options
author | booky10 <[email protected]> | 2023-11-04 20:20:01 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2023-11-04 20:20:01 +0100 |
commit | f78d7ce8ffb7e4b6fd5ee256f5e3678ea04fd807 (patch) | |
tree | 8e7abee5129e15a919630824c4f194a2811f7242 /patches/server/1005-Improve-performance-of-mass-crafts.patch | |
parent | 44057da46727138e19d951b56e98ad8c25c1f869 (diff) | |
download | Paper-f78d7ce8ffb7e4b6fd5ee256f5e3678ea04fd807.tar.gz Paper-f78d7ce8ffb7e4b6fd5ee256f5e3678ea04fd807.zip |
Remove "fix-curing-zombie-villager-discount" exploit option (#9895)
Diffstat (limited to 'patches/server/1005-Improve-performance-of-mass-crafts.patch')
-rw-r--r-- | patches/server/1005-Improve-performance-of-mass-crafts.patch | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/patches/server/1005-Improve-performance-of-mass-crafts.patch b/patches/server/1005-Improve-performance-of-mass-crafts.patch new file mode 100644 index 0000000000..183698b5c5 --- /dev/null +++ b/patches/server/1005-Improve-performance-of-mass-crafts.patch @@ -0,0 +1,83 @@ +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/CraftingMenu.java b/src/main/java/net/minecraft/world/inventory/CraftingMenu.java +index a7aa2a4845cbf5a0843dcb93f7bdc5501f62a145..4c8ce073094e55ea0df67fe02c0d1cc8aef76562 100644 +--- a/src/main/java/net/minecraft/world/inventory/CraftingMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/CraftingMenu.java +@@ -76,7 +76,8 @@ public class CraftingMenu extends RecipeBookMenu<CraftingContainer> { + if (!world.isClientSide) { + ServerPlayer entityplayer = (ServerPlayer) player; + ItemStack itemstack = ItemStack.EMPTY; +- Optional<RecipeHolder<CraftingRecipe>> optional = world.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftingInventory, world); ++ final RecipeHolder<?> currentRecipe = craftingInventory.getCurrentRecipe(); // Paper - check last recipe used first ++ Optional<RecipeHolder<CraftingRecipe>> optional = currentRecipe == null ? world.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftingInventory, world) : world.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftingInventory, world, currentRecipe.id()).map(com.mojang.datafixers.util.Pair::getSecond); // Paper - check last recipe used first + + if (optional.isPresent()) { + RecipeHolder<CraftingRecipe> recipeholder = (RecipeHolder) optional.get(); +diff --git a/src/main/java/net/minecraft/world/inventory/ResultSlot.java b/src/main/java/net/minecraft/world/inventory/ResultSlot.java +index 525ba0bdc4c6782480930bea94f73a72efe6fc4c..2554f7b1d687f83f42d69bf8ab54336ba793e301 100644 +--- a/src/main/java/net/minecraft/world/inventory/ResultSlot.java ++++ b/src/main/java/net/minecraft/world/inventory/ResultSlot.java +@@ -59,7 +59,7 @@ public class ResultSlot extends Slot { + @Override + public void onTake(Player player, ItemStack stack) { + this.checkTakeAchievements(stack); +- NonNullList<ItemStack> nonNullList = player.level().getRecipeManager().getRemainingItemsFor(RecipeType.CRAFTING, this.craftSlots, player.level()); ++ NonNullList<ItemStack> nonNullList = player.level().getRecipeManager().getRemainingItemsFor(RecipeType.CRAFTING, this.craftSlots, player.level(), this.craftSlots.getCurrentRecipe() != null ? this.craftSlots.getCurrentRecipe().id() : null); // Paper - check last recipe used first + + for(int i = 0; i < nonNullList.size(); ++i) { + ItemStack itemStack = this.craftSlots.getItem(i); +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 bf16c44e2d61dccb662eceeef89a143a25ba40b0..666fc85bc2079cb367b340f2605f29fe002f4d22 100644 +--- a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java ++++ b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java +@@ -122,13 +122,16 @@ public class RecipeManager extends SimpleJsonResourceReloadListener { + RecipeHolder<T> recipeholder = (RecipeHolder) map.get(id); + + if (recipeholder != null && recipeholder.value().matches(inventory, world)) { ++ inventory.setCurrentRecipe(recipeholder); // Paper + return Optional.of(Pair.of(id, recipeholder)); + } + } + ++ inventory.setCurrentRecipe(null); // Paper - clear before it might be set again + return map.entrySet().stream().filter((entry) -> { + return ((RecipeHolder) entry.getValue()).value().matches(inventory, world); + }).findFirst().map((entry) -> { ++ inventory.setCurrentRecipe(entry.getValue()); // Paper + return Pair.of((ResourceLocation) entry.getKey(), (RecipeHolder) entry.getValue()); + }); + } +@@ -150,7 +153,12 @@ public class RecipeManager extends SimpleJsonResourceReloadListener { + } + + public <C extends Container, T extends Recipe<C>> NonNullList<ItemStack> getRemainingItemsFor(RecipeType<T> type, C inventory, Level world) { +- Optional<RecipeHolder<T>> optional = this.getRecipeFor(type, inventory, world); ++ // Paper start - check last recipe used first ++ return this.getRemainingItemsFor(type, inventory, world, null); ++ } ++ public <C extends Container, T extends Recipe<C>> NonNullList<ItemStack> getRemainingItemsFor(RecipeType<T> type, C inventory, Level world, @Nullable ResourceLocation firstToCheck) { ++ Optional<RecipeHolder<T>> optional = firstToCheck == null ? this.getRecipeFor(type, inventory, world) : this.getRecipeFor(type, inventory, world, firstToCheck).map(Pair::getSecond); ++ // Paper end + + if (optional.isPresent()) { + return ((RecipeHolder) optional.get()).value().getRemainingItems(inventory); |