From b060c6104be5aad756e46ee6901041c60ed425dd Mon Sep 17 00:00:00 2001 From: D-Cysteine <54219287+D-Cysteine@users.noreply.github.com> Date: Sat, 20 Nov 2021 12:45:46 -0700 Subject: Fix recipe input check --- src/main/java/gregtech/api/util/GT_Recipe.java | 169 ++++++++++++------------- 1 file changed, 83 insertions(+), 86 deletions(-) (limited to 'src/main/java/gregtech/api/util') diff --git a/src/main/java/gregtech/api/util/GT_Recipe.java b/src/main/java/gregtech/api/util/GT_Recipe.java index 7b74f95a6b..27e3e29068 100644 --- a/src/main/java/gregtech/api/util/GT_Recipe.java +++ b/src/main/java/gregtech/api/util/GT_Recipe.java @@ -379,112 +379,109 @@ public class GT_Recipe implements Comparable { public static boolean GTppRecipeHelper; public boolean isRecipeInputEqual(boolean aDecreaseStacksizeBySuccess, boolean aDontCheckStackSizes, FluidStack[] aFluidInputs, ItemStack... aInputs) { - if (mInputs.length > 0 && aInputs == null) return false; if (mFluidInputs.length > 0 && aFluidInputs == null) return false; + + // We need to handle 0-size recipe ingredients. These are for ingredients that don't get consumed. + boolean found; int amt; - for (FluidStack tFluid : mFluidInputs) - if (tFluid != null) { - boolean temp = true; - amt = tFluid.amount; - for (FluidStack aFluid : aFluidInputs) - if (aFluid != null && aFluid.isFluidEqual(tFluid)) { - if (aDontCheckStackSizes) { - temp = false; - break; - } - amt -= aFluid.amount; - if (amt < 1) { - temp = false; - break; + + // 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 uninitialized. + Integer[] fluidAmounts = null; + if (aFluidInputs != null) { + fluidAmounts = new Integer[aFluidInputs.length]; + + for (FluidStack tFluid : mFluidInputs) { + if (tFluid != null) { + found = false; + amt = tFluid.amount; + + for (int i = 0; i < aFluidInputs.length; i++) { + FluidStack aFluid = aFluidInputs[i]; + if (aFluid != null && aFluid.isFluidEqual(tFluid)) { + found = true; + if (fluidAmounts[i] == null) { + fluidAmounts[i] = aFluid.amount; + } + + if (aDontCheckStackSizes || fluidAmounts[i] >= amt) { + fluidAmounts[i] -= amt; + amt = 0; + break; + } else { + amt -= fluidAmounts[i]; + fluidAmounts[i] = 0; + } } } - if (temp) return false; + + if (amt > 0 || !found) { + return false; + } + } } + } - HashSet isVisited = new HashSet<>(); - - for (ItemStack tStack : mInputs) { - ItemStack unified_tStack = GT_OreDictUnificator.get_nocopy(true, tStack); - if (unified_tStack != null) { - amt = tStack.stackSize; - boolean temp = true; - int it = 0; - for (ItemStack aStack : aInputs) { - it ++; - if (GT_OreDictUnificator.isInputStackEqual(aStack, unified_tStack) && !isVisited.contains(it)) { - isVisited.add(it); - if (GTppRecipeHelper) {//remove once the fix is out - if (GT_Utility.areStacksEqual(aStack, Ic2Items.FluidCell.copy(), true) || GT_Utility.areStacksEqual(aStack, ItemList.Tool_DataStick.get(1L), true) || GT_Utility.areStacksEqual(aStack, ItemList.Tool_DataOrb.get(1L), true)) { - if (!GT_Utility.areStacksEqual(aStack, tStack, false)) - continue; + // 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 uninitialized. + Integer[] stackSizes = null; + if (aInputs != null) { + stackSizes = new Integer[aInputs.length]; + + for (ItemStack tStack : mInputs) { + ItemStack unified_tStack = GT_OreDictUnificator.get_nocopy(true, tStack); + if (unified_tStack != null) { + found = false; + amt = tStack.stackSize; + + for (int i = 0; i < aInputs.length; i++) { + ItemStack aStack = aInputs[i]; + if (GT_OreDictUnificator.isInputStackEqual(aStack, unified_tStack)) { + if (GTppRecipeHelper) { // remove once the fix is out + if (GT_Utility.areStacksEqual(aStack, Ic2Items.FluidCell.copy(), true) || GT_Utility.areStacksEqual(aStack, ItemList.Tool_DataStick.get(1L), true) || GT_Utility.areStacksEqual(aStack, ItemList.Tool_DataOrb.get(1L), true)) { + if (!GT_Utility.areStacksEqual(aStack, tStack, false)) + continue; + } + } + + found = true; + if (stackSizes[i] == null) { + stackSizes[i] = aStack.stackSize; + } + + if (aDontCheckStackSizes || stackSizes[i] >= amt) { + stackSizes[i] -= amt; + amt = 0; + break; + } else { + amt -= stackSizes[i]; + stackSizes[i] = 0; } } - if (aDontCheckStackSizes) { - temp = false; - break; - } - amt -= aStack.stackSize; - if (amt < 1) { - temp = false; - break; - } + } + + if (amt > 0 || !found) { + return false; } } - if (temp) return false; } } + if (aDecreaseStacksizeBySuccess) { + // Copy modified amounts into the input stacks. if (aFluidInputs != null) { - for (FluidStack tFluid : mFluidInputs) { - if (tFluid != null) { - amt = tFluid.amount; - for (FluidStack aFluid : aFluidInputs) { - if (aFluid != null && aFluid.isFluidEqual(tFluid)) { - if (aDontCheckStackSizes) { - aFluid.amount -= amt; - break; - } - if (aFluid.amount < amt) { - amt -= aFluid.amount; - aFluid.amount = 0; - } else { - aFluid.amount -= amt; - amt = 0; - break; - } - } - } + for (int i = 0; i < aFluidInputs.length; i++) { + if (fluidAmounts[i] != null) { + aFluidInputs[i].amount = fluidAmounts[i]; } } } if (aInputs != null) { - for (ItemStack tStack : mInputs) { - if (tStack != null) { - amt = tStack.stackSize; - for (ItemStack aStack : aInputs) { - if ((GT_Utility.areUnificationsEqual(aStack, tStack, true) || GT_Utility.areUnificationsEqual(GT_OreDictUnificator.get(false, aStack), tStack, true))) { - if (GTppRecipeHelper) { - if (GT_Utility.areStacksEqual(aStack, Ic2Items.FluidCell.copy(), true) || GT_Utility.areStacksEqual(aStack, ItemList.Tool_DataStick.get(1L), true) || GT_Utility.areStacksEqual(aStack, ItemList.Tool_DataOrb.get(1L), true)) { - if (!GT_Utility.areStacksEqual(aStack, tStack, false)) - continue; - } - } - if (aDontCheckStackSizes){ - aStack.stackSize -= amt; - break; - } - if (aStack.stackSize < amt){ - amt -= aStack.stackSize; - aStack.stackSize = 0; - }else{ - aStack.stackSize -= amt; - amt = 0; - break; - } - } - } + for (int i = 0; i < aInputs.length; i++) { + if (stackSizes[i] != null) { + aInputs[i].stackSize = stackSizes[i]; } } } -- cgit From 8231f6ccbb9e9b6d2d61e11e4fab7f0ee1a7a46c Mon Sep 17 00:00:00 2001 From: D-Cysteine <54219287+D-Cysteine@users.noreply.github.com> Date: Sat, 20 Nov 2021 22:43:07 -0700 Subject: Rename variables and add some comments --- src/main/java/gregtech/api/util/GT_Recipe.java | 98 ++++++++++++++------------ 1 file changed, 52 insertions(+), 46 deletions(-) (limited to 'src/main/java/gregtech/api/util') diff --git a/src/main/java/gregtech/api/util/GT_Recipe.java b/src/main/java/gregtech/api/util/GT_Recipe.java index 27e3e29068..d94d161f14 100644 --- a/src/main/java/gregtech/api/util/GT_Recipe.java +++ b/src/main/java/gregtech/api/util/GT_Recipe.java @@ -378,45 +378,50 @@ public class GT_Recipe implements Comparable { public static boolean GTppRecipeHelper; + /** + * WARNING: Do not call this method with both {@code aDecreaseStacksizeBySuccess} and {@code aDontCheckStackSizes} set to {@code true}! + * You'll get weird behavior. + */ public boolean isRecipeInputEqual(boolean aDecreaseStacksizeBySuccess, boolean aDontCheckStackSizes, FluidStack[] aFluidInputs, ItemStack... aInputs) { if (mInputs.length > 0 && aInputs == null) return false; if (mFluidInputs.length > 0 && aFluidInputs == null) return false; - // We need to handle 0-size recipe ingredients. These are for ingredients that don't get consumed. - boolean found; - int amt; + // 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 uninitialized. - Integer[] fluidAmounts = null; + // We use Integer so that we can have null as the default value, meaning unchanged. + Integer[] newFluidAmounts = null; if (aFluidInputs != null) { - fluidAmounts = new Integer[aFluidInputs.length]; + newFluidAmounts = new Integer[aFluidInputs.length]; - for (FluidStack tFluid : mFluidInputs) { - if (tFluid != null) { - found = false; - amt = tFluid.amount; + for (FluidStack recipeFluidCost : mFluidInputs) { + if (recipeFluidCost != null) { + inputFound = false; + remainingCost = recipeFluidCost.amount; for (int i = 0; i < aFluidInputs.length; i++) { - FluidStack aFluid = aFluidInputs[i]; - if (aFluid != null && aFluid.isFluidEqual(tFluid)) { - found = true; - if (fluidAmounts[i] == null) { - fluidAmounts[i] = aFluid.amount; + FluidStack providedFluid = aFluidInputs[i]; + if (providedFluid != null && providedFluid.isFluidEqual(recipeFluidCost)) { + inputFound = true; + if (newFluidAmounts[i] == null) { + newFluidAmounts[i] = providedFluid.amount; } - if (aDontCheckStackSizes || fluidAmounts[i] >= amt) { - fluidAmounts[i] -= amt; - amt = 0; + if (aDontCheckStackSizes || newFluidAmounts[i] >= remainingCost) { + newFluidAmounts[i] -= remainingCost; + remainingCost = 0; break; } else { - amt -= fluidAmounts[i]; - fluidAmounts[i] = 0; + remainingCost -= newFluidAmounts[i]; + newFluidAmounts[i] = 0; } } } - if (amt > 0 || !found) { + if (remainingCost > 0 || !inputFound) { + // Cost not satisfied, or for non-consumed inputs, input not found. return false; } } @@ -424,44 +429,45 @@ public class GT_Recipe implements Comparable { } // 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 uninitialized. - Integer[] stackSizes = null; + // We use Integer so that we can have null as the default value, meaning unchanged. + Integer[] newItemAmounts = null; if (aInputs != null) { - stackSizes = new Integer[aInputs.length]; + newItemAmounts = new Integer[aInputs.length]; - for (ItemStack tStack : mInputs) { - ItemStack unified_tStack = GT_OreDictUnificator.get_nocopy(true, tStack); - if (unified_tStack != null) { - found = false; - amt = tStack.stackSize; + for (ItemStack recipeItemCost : mInputs) { + ItemStack unifiedItemCost = GT_OreDictUnificator.get_nocopy(true, recipeItemCost); + if (unifiedItemCost != null) { + inputFound = false; + remainingCost = recipeItemCost.stackSize; for (int i = 0; i < aInputs.length; i++) { - ItemStack aStack = aInputs[i]; - if (GT_OreDictUnificator.isInputStackEqual(aStack, unified_tStack)) { + ItemStack providedItem = aInputs[i]; + if (GT_OreDictUnificator.isInputStackEqual(providedItem, unifiedItemCost)) { if (GTppRecipeHelper) { // remove once the fix is out - if (GT_Utility.areStacksEqual(aStack, Ic2Items.FluidCell.copy(), true) || GT_Utility.areStacksEqual(aStack, ItemList.Tool_DataStick.get(1L), true) || GT_Utility.areStacksEqual(aStack, ItemList.Tool_DataOrb.get(1L), true)) { - if (!GT_Utility.areStacksEqual(aStack, tStack, false)) + if (GT_Utility.areStacksEqual(providedItem, Ic2Items.FluidCell.copy(), true) || GT_Utility.areStacksEqual(providedItem, ItemList.Tool_DataStick.get(1L), true) || GT_Utility.areStacksEqual(providedItem, ItemList.Tool_DataOrb.get(1L), true)) { + if (!GT_Utility.areStacksEqual(providedItem, recipeItemCost, false)) continue; } } - found = true; - if (stackSizes[i] == null) { - stackSizes[i] = aStack.stackSize; + inputFound = true; + if (newItemAmounts[i] == null) { + newItemAmounts[i] = providedItem.stackSize; } - if (aDontCheckStackSizes || stackSizes[i] >= amt) { - stackSizes[i] -= amt; - amt = 0; + if (aDontCheckStackSizes || newItemAmounts[i] >= remainingCost) { + newItemAmounts[i] -= remainingCost; + remainingCost = 0; break; } else { - amt -= stackSizes[i]; - stackSizes[i] = 0; + remainingCost -= newItemAmounts[i]; + newItemAmounts[i] = 0; } } } - if (amt > 0 || !found) { + if (remainingCost > 0 || !inputFound) { + // Cost not satisfied, or for non-consumed inputs, input not found. return false; } } @@ -472,16 +478,16 @@ public class GT_Recipe implements Comparable { // Copy modified amounts into the input stacks. if (aFluidInputs != null) { for (int i = 0; i < aFluidInputs.length; i++) { - if (fluidAmounts[i] != null) { - aFluidInputs[i].amount = fluidAmounts[i]; + if (newFluidAmounts[i] != null) { + aFluidInputs[i].amount = newFluidAmounts[i]; } } } if (aInputs != null) { for (int i = 0; i < aInputs.length; i++) { - if (stackSizes[i] != null) { - aInputs[i].stackSize = stackSizes[i]; + if (newItemAmounts[i] != null) { + aInputs[i].stackSize = newItemAmounts[i]; } } } -- cgit From a4d6e33b06059629b3fb86465c9c8c146407fb82 Mon Sep 17 00:00:00 2001 From: D-Cysteine <54219287+D-Cysteine@users.noreply.github.com> Date: Sun, 21 Nov 2021 06:51:34 -0700 Subject: Add comment about GTppRecipeHelper --- src/main/java/gregtech/api/util/GT_Recipe.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src/main/java/gregtech/api/util') diff --git a/src/main/java/gregtech/api/util/GT_Recipe.java b/src/main/java/gregtech/api/util/GT_Recipe.java index d94d161f14..c0ea06af07 100644 --- a/src/main/java/gregtech/api/util/GT_Recipe.java +++ b/src/main/java/gregtech/api/util/GT_Recipe.java @@ -376,6 +376,19 @@ public class GT_Recipe implements Comparable { return isRecipeInputEqual(aDecreaseStacksizeBySuccess, false, aFluidInputs, aInputs); } + /** + * Okay, did some code archeology to figure out what's going on here. + * + *

This variable was added in + * this commit, + * in order to fix the issues mentioned in + * the PR. + * + *

It looks like it controls checking NBT. At this point, since we are still using universal + * fluid cells which store their fluids in NBT, it probably will not be safe to disable the NBT + * checks in the near future. Data sticks may be another case. Anyway, we probably can't get rid + * of this without some significant changes to clean up recipe inputs. + */ public static boolean GTppRecipeHelper; /** @@ -443,7 +456,7 @@ public class GT_Recipe implements Comparable { for (int i = 0; i < aInputs.length; i++) { ItemStack providedItem = aInputs[i]; if (GT_OreDictUnificator.isInputStackEqual(providedItem, unifiedItemCost)) { - if (GTppRecipeHelper) { // remove once the fix is out + if (GTppRecipeHelper) { // Please see JavaDoc on GTppRecipeHelper for why this is here. if (GT_Utility.areStacksEqual(providedItem, Ic2Items.FluidCell.copy(), true) || GT_Utility.areStacksEqual(providedItem, ItemList.Tool_DataStick.get(1L), true) || GT_Utility.areStacksEqual(providedItem, ItemList.Tool_DataOrb.get(1L), true)) { if (!GT_Utility.areStacksEqual(providedItem, recipeItemCost, false)) continue; -- cgit