From bab58fc9a167190c61b166e82f031e6c56025800 Mon Sep 17 00:00:00 2001 From: GrayJou <97294747+Grayjou@users.noreply.github.com> Date: Tue, 3 Mar 2026 07:49:42 -0500 Subject: [PATCH] Optimize item count lookups in crafting GUI Replace nested iterations over storageItems with O(1) dictionary lookups (itemCounts) when computing available ingredient stacks in CraftingGUI.ItemSlotMethods.cs. This reduces severe lag when players have many stacks of common items by summing group totals via itemCounts, using a directItemCount for direct-type checks, and preserving the early-exit logic for recipe groups and existing context decisions (IngredientNotCraftable / IngredientPartiallyInStock). Comments added to explain the optimization. --- UI/GUIs/CraftingGUI.ItemSlotMethods.cs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/UI/GUIs/CraftingGUI.ItemSlotMethods.cs b/UI/GUIs/CraftingGUI.ItemSlotMethods.cs index 050bf440..cec3a82f 100644 --- a/UI/GUIs/CraftingGUI.ItemSlotMethods.cs +++ b/UI/GUIs/CraftingGUI.ItemSlotMethods.cs @@ -41,21 +41,21 @@ internal static Item GetIngredient(int slot, ref int context) if (ProcessGroupsForText(selectedRecipe, item.type, out string nameOverride)) item.SetNameOverride(nameOverride); + // OPTIMIZATION: Use itemCounts dictionary for O(1) lookups instead of O(n*m*k*p) nested loops through storageItems + // This fixes severe lag when player has multiple stacks of certain items (stone, mud, etc.) + + int directItemCount = itemCounts.TryGetValue(item.type, out int count) ? count : 0; + ClampedArithmetic totalGroupStack = 0; - // Local capturing - Item i = item; - Item storageItem = storageItems.FirstOrDefault(stored => stored.type == i.type) ?? new Item(); - + // Calculate recipe group totals by dictionary lookup instead of iterating storageItems foreach (RecipeGroup rec in selectedRecipe.acceptedGroups.Select(index => RecipeGroup.recipeGroups[index])) { if (rec.ContainsItem(item.type)) { foreach (int type in rec.ValidItems) { - foreach (Item storedItem in storageItems) { - if (storedItem.type == type) { - totalGroupStack += storedItem.stack; + if (itemCounts.TryGetValue(type, out int groupItemCount)) { + totalGroupStack += groupItemCount; - if (totalGroupStack >= item.stack) - goto StopCheckingRecipeGroups; - } + if (totalGroupStack >= item.stack) + goto StopCheckingRecipeGroups; } } } @@ -64,9 +64,9 @@ internal static Item GetIngredient(int slot, ref int context) StopCheckingRecipeGroups: if (!item.IsAir) { - if (storageItem.IsAir && (int)totalGroupStack == 0) + if (directItemCount == 0 && (int)totalGroupStack == 0) context = MagicSlotContext.IngredientNotCraftable; - else if (storageItem.stack < item.stack && totalGroupStack < item.stack) + else if (directItemCount < item.stack && totalGroupStack < item.stack) context = MagicSlotContext.IngredientPartiallyInStock; if (context != MagicSlotContext.Normal) {