e035fd7034
Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: cc9aa21a SPIGOT-6399, SPIGOT-7344: Clarify collidable behavior for player entities f23325b6 Add API for per-world simulation distances 26e1774e Add API for per-world view distances 0b541e60 Add PlayerLoginEvent#getRealAddress 5f027d2d PR-949: Add Vector#fromJOML() overloads for read-only vector types CraftBukkit Changes: bcf56171a PR-1321: Clean up some stuff which got missed during previous PRs 7f833a2d1 SPIGOT-7462: Players no longer drop XP after dying near a Sculk Catalyst 752aac669 Implement APIs for per world view and simulation distances 57d7ef433 Preserve empty enchantment tags for glow effect 465ec3fb4 Remove connected check on setScoreboard f90ce621e Use one PermissibleBase for all command blocks 5876cca44 SPIGOT-7550: Fix creation of Arrow instances f03fc3aa3 SPIGOT-7549: ServerTickManager#setTickRate incorrect Precondition 9d7f49b01 SPIGOT-7548: Fix wrong spawn location for experience orb and dropped item Spigot Changes: ed9ba9a4 Drop no longer required patch ignoring -o option 86b5dd6a SPIGOT-7546: Fix hardcoded check for outdated client message aa7cde7a Remove obsolete APIs for per world view and simulation distances 6dff577e Remove obsolete patch preserving empty `ench` tags a3bf95b8 Remove obsolete PlayerLoginEvent#getRealAddress 1b02f5d6 Remove obsolete connected check on setScoreboard patch acf717eb Remove obsolete command block PermissibleBase patch 053fa2a9 Remove redundant patch dealing with null tile entities
84 Zeilen
6.2 KiB
Diff
84 Zeilen
6.2 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
|
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 7b2ac37e8bd305919f04ded043e50f13b3fe4253..8c97a7269040436cacc65fd182fa8e5f931b6c16 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 93e7d350a4176250d9ae3f0e1e7e6a4197d613b0..b81e1802c8dcc8ebdef96d70088c18379598a66b 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);
|