From b1ef472ca7dc7ff0b3093e25c2897f0e0d2650f8 Mon Sep 17 00:00:00 2001 From: mibac138 <5672750+mibac138@users.noreply.github.com> Date: Thu, 8 Aug 2024 20:59:05 +0200 Subject: [PATCH 1/2] Optimize crafter performance Caching used recipes when updating the client-side inventory reduces client freezes when there are a lot of recipes registered. --- .../modules/crafter/blocks/CrafterBaseTE.java | 16 +++++++++++++--- .../modules/crafter/data/CraftingRecipe.java | 9 +-------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/main/java/mcjty/rftoolsutility/modules/crafter/blocks/CrafterBaseTE.java b/src/main/java/mcjty/rftoolsutility/modules/crafter/blocks/CrafterBaseTE.java index 9e397b09..0f9f910e 100644 --- a/src/main/java/mcjty/rftoolsutility/modules/crafter/blocks/CrafterBaseTE.java +++ b/src/main/java/mcjty/rftoolsutility/modules/crafter/blocks/CrafterBaseTE.java @@ -120,9 +120,19 @@ private void clearCacheOrUpdateRecipe(Integer slot) { for (int i = 0; i < 9; i++) { workInventory.setItem(i, items.getStackInSlot(i + SLOT_CRAFTINPUT).copy()); } - Recipe recipe = CraftingRecipe.findRecipe(level, workInventory); - if (recipe != null) { - ItemStack result = BaseRecipe.assemble(recipe, workInventory, level); + Recipe matchingRecipe = null; + for (CraftingRecipe recipe : recipes) { + Recipe cachedRecipe = recipe.getCachedRecipe(level); + if (cachedRecipe != null && cachedRecipe.matches(workInventory, level)) { + matchingRecipe = cachedRecipe; + break; + } + } + if (matchingRecipe == null) { + matchingRecipe = CraftingRecipe.findRecipe(level, workInventory); + } + if (matchingRecipe != null) { + ItemStack result = BaseRecipe.assemble(matchingRecipe, workInventory, level); items.setStackInSlot(SLOT_CRAFTOUTPUT, result); } else { items.setStackInSlot(SLOT_CRAFTOUTPUT, ItemStack.EMPTY); diff --git a/src/main/java/mcjty/rftoolsutility/modules/crafter/data/CraftingRecipe.java b/src/main/java/mcjty/rftoolsutility/modules/crafter/data/CraftingRecipe.java index 15daddaa..98101a6d 100644 --- a/src/main/java/mcjty/rftoolsutility/modules/crafter/data/CraftingRecipe.java +++ b/src/main/java/mcjty/rftoolsutility/modules/crafter/data/CraftingRecipe.java @@ -10,7 +10,6 @@ import net.minecraft.world.inventory.TransientCraftingContainer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.item.crafting.RecipeManager; import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.Level; @@ -91,13 +90,7 @@ public List getCompressedIngredients() { } public static Recipe findRecipe(Level world, CraftingContainer inv) { - RecipeManager recipeManager = world.getRecipeManager(); - for (Recipe r : recipeManager.getRecipes()) { - if (r != null && RecipeType.CRAFTING.equals(r.getType()) && r.matches(inv, world)) { - return r; - } - } - return null; + return world.getRecipeManager().getRecipeFor(RecipeType.CRAFTING, inv, world).orElse(null); } public void readFromNBT(CompoundTag tagCompound) { From 49e53f247e566942f8b3bd65f24920039dc5bbcb Mon Sep 17 00:00:00 2001 From: mibac138 <5672750+mibac138@users.noreply.github.com> Date: Fri, 9 Aug 2024 01:44:44 +0200 Subject: [PATCH 2/2] Avoid needlessly searching through all recipes if the recipe id is known Reduces freezing upon opening a crafter when there is a large number of recipes registered. --- .../modules/crafter/blocks/CrafterBaseTE.java | 5 ++++- .../modules/crafter/data/CraftingRecipe.java | 14 +++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/main/java/mcjty/rftoolsutility/modules/crafter/blocks/CrafterBaseTE.java b/src/main/java/mcjty/rftoolsutility/modules/crafter/blocks/CrafterBaseTE.java index 0f9f910e..1af06d03 100644 --- a/src/main/java/mcjty/rftoolsutility/modules/crafter/blocks/CrafterBaseTE.java +++ b/src/main/java/mcjty/rftoolsutility/modules/crafter/blocks/CrafterBaseTE.java @@ -39,6 +39,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.item.crafting.ShapedRecipe; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; @@ -129,7 +130,9 @@ private void clearCacheOrUpdateRecipe(Integer slot) { } } if (matchingRecipe == null) { - matchingRecipe = CraftingRecipe.findRecipe(level, workInventory); + matchingRecipe = level.getRecipeManager() + .getRecipeFor(RecipeType.CRAFTING, workInventory, level) + .orElse(null); } if (matchingRecipe != null) { ItemStack result = BaseRecipe.assemble(matchingRecipe, workInventory, level); diff --git a/src/main/java/mcjty/rftoolsutility/modules/crafter/data/CraftingRecipe.java b/src/main/java/mcjty/rftoolsutility/modules/crafter/data/CraftingRecipe.java index 98101a6d..9e780abc 100644 --- a/src/main/java/mcjty/rftoolsutility/modules/crafter/data/CraftingRecipe.java +++ b/src/main/java/mcjty/rftoolsutility/modules/crafter/data/CraftingRecipe.java @@ -1,9 +1,11 @@ package mcjty.rftoolsutility.modules.crafter.data; +import com.mojang.datafixers.util.Pair; import mcjty.lib.varia.InventoryTools; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.CraftingContainer; @@ -32,6 +34,7 @@ public ItemStack quickMoveStack(Player player, int slot) { }, 3, 3); private ItemStack result = ItemStack.EMPTY; + private ResourceLocation recipeId; private boolean recipePresent = false; private Recipe recipe = null; @@ -89,10 +92,6 @@ public List getCompressedIngredients() { return compressedIngredients; } - public static Recipe findRecipe(Level world, CraftingContainer inv) { - return world.getRecipeManager().getRecipeFor(RecipeType.CRAFTING, inv, world).orElse(null); - } - public void readFromNBT(CompoundTag tagCompound) { ListTag nbtTagList = tagCompound.getList("Items", Tag.TAG_COMPOUND); for (int i = 0; i < nbtTagList.size(); i++) { @@ -102,6 +101,7 @@ public void readFromNBT(CompoundTag tagCompound) { result = ItemStack.of(resultCompound); keepOne = tagCompound.getBoolean("Keep") ? KeepMode.KEEP : KeepMode.ALL; craftMode = CraftMode.values()[tagCompound.getByte("Int")]; + recipeId = ResourceLocation.tryParse(tagCompound.getString("RecipeId")); recipePresent = false; } @@ -123,6 +123,9 @@ public void writeToNBT(CompoundTag tagCompound) { tagCompound.put("Items", nbtTagList); tagCompound.putBoolean("Keep", keepOne == KeepMode.KEEP); tagCompound.putByte("Int", (byte) craftMode.ordinal()); + if (recipe != null) { + tagCompound.putString("RecipeId", recipe.getId().toString()); + } } public void setRecipe(ItemStack[] items, ItemStack result) { @@ -148,7 +151,8 @@ public ItemStack getResult() { public Recipe getCachedRecipe(Level world) { if (!recipePresent) { recipePresent = true; - recipe = findRecipe(world, inv); + recipe = world.getRecipeManager().getRecipeFor(RecipeType.CRAFTING, inv, world, recipeId).map(Pair::getSecond).orElse(null); + recipeId = recipe != null ? recipe.getId() : null; compressedIngredients = null; } return recipe;