diff options
author | HoleFish <48403212+HoleFish@users.noreply.github.com> | 2023-11-12 11:03:17 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-12 12:03:17 +0900 |
commit | c7c4ca2a716df221351998c275599707972df229 (patch) | |
tree | f633eaff69c7df3ba2da3f423451580c6d5d1e6a /src/main | |
parent | 581d16e61ddd8ed195fa5e6618fe0cea6fdde167 (diff) | |
download | GT5-Unofficial-c7c4ca2a716df221351998c275599707972df229.tar.gz GT5-Unofficial-c7c4ca2a716df221351998c275599707972df229.tar.bz2 GT5-Unofficial-c7c4ca2a716df221351998c275599707972df229.zip |
fix lag caused by too much parallel (#2358)
* Update GT_Recipe.java
add a method to calculate max parallel by inputs
* remove incredible loop in parallel calculation
* Update GT_Recipe.java
overwrite maxParallelCalculatedByInput
split isRecipeInputEqual into maxParallelCalculatedByInput and consumeInput
* Fix
* spotless and fix
* spotless
* optimize
* batch mode optimize
* Update notes
Diffstat (limited to 'src/main')
-rw-r--r-- | src/main/java/gregtech/api/util/GT_ParallelHelper.java | 28 | ||||
-rw-r--r-- | src/main/java/gregtech/api/util/GT_Recipe.java | 147 |
2 files changed, 95 insertions, 80 deletions
diff --git a/src/main/java/gregtech/api/util/GT_ParallelHelper.java b/src/main/java/gregtech/api/util/GT_ParallelHelper.java index 8430f28fa0..e848d87092 100644 --- a/src/main/java/gregtech/api/util/GT_ParallelHelper.java +++ b/src/main/java/gregtech/api/util/GT_ParallelHelper.java @@ -456,26 +456,23 @@ public class GT_ParallelHelper { maxParallelBeforeBatchMode = Math.min(maxParallel, maxParallelBeforeBatchMode); - // Consume inputs to determine normal parallel + // determine normal parallel + int actualMaxParallel = (int) Math.min(maxParallelBeforeBatchMode, availableEUt / tRecipeEUt); if (recipeCheck != null) { - int actualMaxParallel = (int) Math.min(maxParallelBeforeBatchMode, availableEUt / tRecipeEUt); currentParallel = recipeCheck.checkRecipeInputs(true, actualMaxParallel, itemInputs, fluidInputs); } else { - long tCurrentUsage = 0; - boolean builtRecipeCheck = false; - for (; currentParallel < maxParallelBeforeBatchMode - && tCurrentUsage < (availableEUt - tRecipeEUt); currentParallel++) { - if (!tryConsumeRecipeInputs(recipe, fluidInputs, itemInputs)) { - break; - } - tCurrentUsage += tRecipeEUt; - if (tSingleRecipeCheckBuilder != null && !builtRecipeCheck) { + currentParallel = (int) recipe.maxParallelCalculatedByInputs(actualMaxParallel, fluidInputs, itemInputs); + if (currentParallel > 0) { + if (tSingleRecipeCheckBuilder != null) { // If recipe checker is not built yet, build and set it + recipe.consumeInput(1, fluidInputs, itemInputs); SingleRecipeCheck builtCheck = tSingleRecipeCheckBuilder.setAfter(itemInputs, fluidInputs) .setRecipe(recipe) .build(); singleRecipeMachine.setSingleRecipeCheck(builtCheck); - builtRecipeCheck = true; + recipe.consumeInput(currentParallel - 1, fluidInputs, itemInputs); + } else { + recipe.consumeInput(currentParallel, fluidInputs, itemInputs); } } } @@ -502,10 +499,9 @@ public class GT_ParallelHelper { if (recipeCheck != null) { tExtraParallels = recipeCheck.checkRecipeInputs(true, maxExtraParallels, itemInputs, fluidInputs); } else { - while (tExtraParallels < maxExtraParallels - && tryConsumeRecipeInputs(recipe, fluidInputs, itemInputs, currentParallel)) { - tExtraParallels += currentParallel; - } + tExtraParallels = (int) recipe + .maxParallelCalculatedByInputs(maxExtraParallels, fluidInputs, itemInputs); + recipe.consumeInput(tExtraParallels, fluidInputs, itemInputs); } durationMultiplier = 1.0f + (float) tExtraParallels / currentParallel; currentParallel += tExtraParallels; diff --git a/src/main/java/gregtech/api/util/GT_Recipe.java b/src/main/java/gregtech/api/util/GT_Recipe.java index e25316c6dd..5cbd54b2f3 100644 --- a/src/main/java/gregtech/api/util/GT_Recipe.java +++ b/src/main/java/gregtech/api/util/GT_Recipe.java @@ -657,65 +657,53 @@ public class GT_Recipe implements Comparable<GT_Recipe> { */ public boolean isRecipeInputEqual(boolean aDecreaseStacksizeBySuccess, boolean aDontCheckStackSizes, int amountMultiplier, FluidStack[] aFluidInputs, ItemStack... aInputs) { - if (mInputs.length > 0 && aInputs == null) return false; - if (mFluidInputs.length > 0 && aFluidInputs == null) return false; + double maxParallel = maxParallelCalculatedByInputs(amountMultiplier, aFluidInputs, aInputs); + if (aDontCheckStackSizes) { + return maxParallel > 0; + } else if (maxParallel >= amountMultiplier) { + if (aDecreaseStacksizeBySuccess) { + consumeInput(amountMultiplier, aFluidInputs, aInputs); + } + return true; + } + return false; + } + + /** + * WARNING: ensure that the inputs and fluid inputs are enough to be consumed! + */ + public void consumeInput(int amountMultiplier, FluidStack[] aFluidInputs, ItemStack... aInputs) { + if (amountMultiplier <= 0) return; - // We need to handle 0-size recipe inputs. These are for inputs that don't get consumed. - boolean inputFound; int remainingCost; - // Array tracking modified fluid amounts. For efficiency, we will lazily initialize this array. - // We use Integer so that we can have null as the default value, meaning unchanged. - Integer[] newFluidAmounts = null; if (aFluidInputs != null) { - newFluidAmounts = new Integer[aFluidInputs.length]; - for (FluidStack recipeFluidCost : mFluidInputs) { if (recipeFluidCost != null) { - inputFound = false; remainingCost = recipeFluidCost.amount * amountMultiplier; - for (int i = 0; i < aFluidInputs.length; i++) { - FluidStack providedFluid = aFluidInputs[i]; + for (FluidStack providedFluid : aFluidInputs) { if (providedFluid != null && providedFluid.isFluidEqual(recipeFluidCost)) { - inputFound = true; - if (newFluidAmounts[i] == null) { - newFluidAmounts[i] = providedFluid.amount; - } - - if (aDontCheckStackSizes || newFluidAmounts[i] >= remainingCost) { - newFluidAmounts[i] -= remainingCost; - remainingCost = 0; + if (providedFluid.amount >= remainingCost) { + providedFluid.amount -= remainingCost; break; } else { - remainingCost -= newFluidAmounts[i]; - newFluidAmounts[i] = 0; + remainingCost -= providedFluid.amount; + providedFluid.amount = 0; } } } - - if (remainingCost > 0 || !inputFound) { - // Cost not satisfied, or for non-consumed inputs, input not found. - return false; - } } } } - // Array tracking modified item stack sizes. For efficiency, we will lazily initialize this array. - // We use Integer so that we can have null as the default value, meaning unchanged. - Integer[] newItemAmounts = null; if (aInputs != null) { - newItemAmounts = new Integer[aInputs.length]; - for (ItemStack recipeItemCost : mInputs) { ItemStack unifiedItemCost = GT_OreDictUnificator.get_nocopy(true, recipeItemCost); if (unifiedItemCost != null) { - inputFound = false; remainingCost = recipeItemCost.stackSize * amountMultiplier; - for (int i = 0; i < aInputs.length; i++) { - ItemStack providedItem = aInputs[i]; + for (ItemStack providedItem : aInputs) { if (isNBTSensitive && !GT_Utility.areStacksEqual(providedItem, unifiedItemCost, false)) { continue; } else if (!isNBTSensitive @@ -731,49 +719,80 @@ public class GT_Recipe implements Comparable<GT_Recipe> { } } - inputFound = true; - if (newItemAmounts[i] == null) { - newItemAmounts[i] = providedItem.stackSize; - } - - if (aDontCheckStackSizes || newItemAmounts[i] >= remainingCost) { - newItemAmounts[i] -= remainingCost; - remainingCost = 0; + if (providedItem.stackSize >= remainingCost) { + providedItem.stackSize -= remainingCost; break; } else { - remainingCost -= newItemAmounts[i]; - newItemAmounts[i] = 0; + remainingCost -= providedItem.stackSize; + providedItem.stackSize = 0; } } - - if (remainingCost > 0 || !inputFound) { - // Cost not satisfied, or for non-consumed inputs, input not found. - return false; - } } } } + } - if (aDecreaseStacksizeBySuccess) { - // Copy modified amounts into the input stacks. - if (aFluidInputs != null) { - for (int i = 0; i < aFluidInputs.length; i++) { - if (newFluidAmounts[i] != null) { - aFluidInputs[i].amount = newFluidAmounts[i]; - } - } + /** + * Returns the number of parallel recipes, or 0 if recipe is not satisfied at all. 0 < number < 1 means that inputs + * are found but not enough. Refer to SingleRecipeCheck#checkRecipeInputs. + */ + public double maxParallelCalculatedByInputs(int maxParallel, FluidStack[] aFluidInputs, ItemStack... aInputs) { + if (mInputs.length > 0 && aInputs == null) return 0; + if (mFluidInputs.length > 0 && aFluidInputs == null) return 0; + + double currentParallel = maxParallel; + + if (aFluidInputs != null) { + // Create map for fluid -> stored amount + Map<Fluid, Integer> fluidMap = new HashMap<>(); + Map<Fluid, Integer> fluidCost = new HashMap<>(); + for (FluidStack fluidStack : aFluidInputs) { + if (fluidStack == null) continue; + fluidMap.merge(fluidStack.getFluid(), fluidStack.amount, Integer::sum); + } + for (FluidStack fluidStack : mFluidInputs) { + if (fluidStack == null) continue; + fluidCost.merge(fluidStack.getFluid(), fluidStack.amount, Integer::sum); } - if (aInputs != null) { - for (int i = 0; i < aInputs.length; i++) { - if (newItemAmounts[i] != null) { - aInputs[i].stackSize = newItemAmounts[i]; - } + // Check how many parallels can it perform for each fluid + for (Map.Entry<Fluid, Integer> costEntry : fluidCost.entrySet()) { + if (costEntry.getValue() > 0) { + currentParallel = Math.min( + currentParallel, + (double) fluidMap.getOrDefault(costEntry.getKey(), 0) / costEntry.getValue()); + } + if (currentParallel <= 0) { + return 0; } } } - return true; + if (aInputs != null) { + // Create map for item -> stored amount + Map<GT_Utility.ItemId, Integer> itemMap = new HashMap<>(); + Map<GT_Utility.ItemId, Integer> itemCost = new HashMap<>(); + for (ItemStack itemStack : aInputs) { + if (itemStack == null) continue; + itemMap.merge(GT_Utility.ItemId.createNoCopy(itemStack), itemStack.stackSize, Integer::sum); + } + for (ItemStack itemStack : mInputs) { + if (itemStack == null) continue; + itemCost.merge(GT_Utility.ItemId.createNoCopy(itemStack), itemStack.stackSize, Integer::sum); + } + // Check how many parallels can it perform for each item + for (Map.Entry<GT_Utility.ItemId, Integer> costEntry : itemCost.entrySet()) { + if (costEntry.getValue() > 0) { + currentParallel = Math.min( + currentParallel, + (double) itemMap.getOrDefault(costEntry.getKey(), 0) / costEntry.getValue()); + } + if (currentParallel <= 0) { + return 0; + } + } + } + return currentParallel; } @Override |