Apply Improve-performance-of-mass-crafts directly

This commit is contained in:
Jake Potrebic
2024-12-17 11:45:39 +01:00
committed by Nassim Jahnke
parent 05c0d4a6e2
commit ac69f75d23
5 changed files with 42 additions and 98 deletions

View File

@@ -5,11 +5,11 @@
List<ItemStack> getItems();
+ // CraftBukkit start
+ default net.minecraft.world.item.crafting.RecipeHolder<?> getCurrentRecipe() {
+ default net.minecraft.world.item.crafting.RecipeHolder<net.minecraft.world.item.crafting.CraftingRecipe> getCurrentRecipe() {
+ return null;
+ }
+
+ default void setCurrentRecipe(net.minecraft.world.item.crafting.RecipeHolder<?> recipe) {
+ default void setCurrentRecipe(net.minecraft.world.item.crafting.RecipeHolder<net.minecraft.world.item.crafting.CraftingRecipe> recipe) {
+ }
+ // CraftBukkit end
+

View File

@@ -18,9 +18,34 @@
this.access = access;
this.player = playerInventory.player;
this.addResultSlot(this.player, 124, 35);
@@ -56,6 +_,7 @@
@@ -55,7 +_,32 @@
CraftingInput craftInput = craftSlots.asCraftInput();
ServerPlayer serverPlayer = (ServerPlayer)player;
ItemStack itemStack = ItemStack.EMPTY;
+ // Paper start - Perf: Improve mass crafting; check last recipe used first
+ /*
+ 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 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 change, 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.
+
+ See also: ResultSlot class
+ */
+ if (recipe == null) {
+ recipe = craftSlots.getCurrentRecipe();
+ }
+ // Paper end - Perf: Improve mass crafting; check last recipe used first
Optional<RecipeHolder<CraftingRecipe>> recipeFor = level.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftInput, level, recipe);
+ craftSlots.setCurrentRecipe(recipeFor.orElse(null)); // CraftBukkit
if (recipeFor.isPresent()) {

View File

@@ -0,0 +1,11 @@
--- a/net/minecraft/world/inventory/ResultSlot.java
+++ b/net/minecraft/world/inventory/ResultSlot.java
@@ -72,7 +_,7 @@
private NonNullList<ItemStack> getRemainingItems(CraftingInput input, Level level) {
return level 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);

View File

@@ -6,7 +6,7 @@
+ // CraftBukkit start - add fields
+ public List<org.bukkit.entity.HumanEntity> transaction = new java.util.ArrayList<>();
+ private net.minecraft.world.item.crafting.RecipeHolder<?> currentRecipe;
+ private net.minecraft.world.item.crafting.RecipeHolder<net.minecraft.world.item.crafting.CraftingRecipe> currentRecipe;
+ public net.minecraft.world.Container resultInventory;
+ private Player owner;
+ private int maxStack = MAX_STACK;
@@ -51,12 +51,12 @@
+ }
+
+ @Override
+ public net.minecraft.world.item.crafting.RecipeHolder<?> getCurrentRecipe() {
+ public net.minecraft.world.item.crafting.RecipeHolder<net.minecraft.world.item.crafting.CraftingRecipe> getCurrentRecipe() {
+ return this.currentRecipe;
+ }
+
+ @Override
+ public void setCurrentRecipe(net.minecraft.world.item.crafting.RecipeHolder<?> currentRecipe) {
+ public void setCurrentRecipe(net.minecraft.world.item.crafting.RecipeHolder<net.minecraft.world.item.crafting.CraftingRecipe> currentRecipe) {
+ this.currentRecipe = currentRecipe;
+ }
+