diff options
Diffstat (limited to 'src')
5 files changed, 296 insertions, 126 deletions
diff --git a/src/main/java/gregtech/api/util/GT_AssemblyLineUtils.java b/src/main/java/gregtech/api/util/GT_AssemblyLineUtils.java index 62238a8112..25f4b35ab3 100644 --- a/src/main/java/gregtech/api/util/GT_AssemblyLineUtils.java +++ b/src/main/java/gregtech/api/util/GT_AssemblyLineUtils.java @@ -2,8 +2,11 @@ package gregtech.api.util; import static gregtech.GT_Mod.GT_FML_LOGGER; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.List; +import java.util.Objects; import cpw.mods.fml.common.FMLCommonHandler; import gregtech.api.enums.GT_Values; @@ -16,6 +19,8 @@ import net.minecraft.nbt.NBTTagList; import net.minecraft.nbt.NBTTagString; import net.minecraftforge.fluids.FluidStack; +import javax.annotation.Nonnull; + public class GT_AssemblyLineUtils { /** @@ -34,21 +39,19 @@ public class GT_AssemblyLineUtils { * @param aDataStick - The DataStick to process * @return Is this DataStick now valid with a current recipe? */ - public static boolean processDataStick(ItemStack aDataStick) { + public static GT_Recipe_AssemblyLine processDataStick(ItemStack aDataStick) { if (!isItemDataStick(aDataStick)) { - return false; + return null; } if (doesDataStickNeedUpdate(aDataStick)) { ItemStack aStickOutput = getDataStickOutput(aDataStick); if (aStickOutput != null) { GT_Recipe_AssemblyLine aIntendedRecipe = findAssemblyLineRecipeByOutput(aStickOutput); - if (aIntendedRecipe != null) { - return setAssemblyLineRecipeOnDataStick(aDataStick, aIntendedRecipe); - } + if (aIntendedRecipe != null && setAssemblyLineRecipeOnDataStick(aDataStick, aIntendedRecipe)) + return aIntendedRecipe; } - return false; } - return true; + return null; } @@ -58,7 +61,7 @@ public class GT_AssemblyLineUtils { * @return The GT_Recipe_AssemblyLine recipe contained on the DataStick, if any. */ public static GT_Recipe_AssemblyLine findAssemblyLineRecipeFromDataStick(ItemStack aDataStick) { - return findAssemblyLineRecipeFromDataStick(aDataStick, false); + return findAssemblyLineRecipeFromDataStick(aDataStick, false).getRecipe(); } /** @@ -67,24 +70,26 @@ public class GT_AssemblyLineUtils { * @param aReturnBuiltRecipe - Do we return a GT_Recipe_AssemblyLine built from the data on the Data Stick instead of searching the Recipe Map? * @return The GT_Recipe_AssemblyLine recipe contained on the DataStick, if any. */ - public static GT_Recipe_AssemblyLine findAssemblyLineRecipeFromDataStick(ItemStack aDataStick, boolean aReturnBuiltRecipe) { + @Nonnull + public static LookupResult findAssemblyLineRecipeFromDataStick(ItemStack aDataStick, boolean aReturnBuiltRecipe) { if (!isItemDataStick(aDataStick)) { - return null; + return LookupResultType.INVALID_STICK.getResult(); } - ItemStack[] aInputs = new ItemStack[15]; - ItemStack[] aOutputs = new ItemStack[1]; - FluidStack[] aFluidInputs = new FluidStack[4]; + List<ItemStack> aInputs = new ArrayList<>(15); + ItemStack aOutput = null; + List<List<ItemStack>> mOreDictAlt = new ArrayList<>(15); + List<FluidStack> aFluidInputs = new ArrayList<>(4); NBTTagCompound aTag = aDataStick.getTagCompound(); if (aTag == null) { - return null; + return LookupResultType.INVALID_STICK.getResult(); } //Get From Cache if (doesDataStickHaveRecipeHash(aDataStick)) { GT_Recipe_AssemblyLine aRecipeFromCache = sRecipeCacheByRecipeHash.get(getHashFromDataStack(aDataStick)); if (aRecipeFromCache != null) { - return aRecipeFromCache; + return LookupResultType.VALID_STACK_AND_VALID_HASH.getResult(aRecipeFromCache); } } @@ -94,33 +99,25 @@ public class GT_AssemblyLineUtils { continue; } - boolean flag = true; - if (count > 0) { - for (int j = 0; j < count; j++) { - aInputs[i] = GT_Utility.loadItem(aTag, "a" + i + ":" + j); - if (aInputs[i] == null) { - continue; - } - if (GT_Values.D1) { - GT_FML_LOGGER.info("Item " + i + " : " + aInputs[i].getUnlocalizedName()); - } - flag = false; - break; - } - } - if (flag) { - aInputs[i] = GT_Utility.loadItem(aTag, "" + i); - if (aInputs[i] == null) { - flag = false; + List<ItemStack> tAltCurrent = new ArrayList<>(); + for (int j = 0; j < count; j++) { + ItemStack tLoaded = GT_Utility.loadItem(aTag, "a" + i + ":" + j); + if (tLoaded == null) { continue; } + tAltCurrent.add(tLoaded); if (GT_Values.D1) { - GT_FML_LOGGER.info("Item " + i + " : " + aInputs[i].getUnlocalizedName()); + GT_FML_LOGGER.info("Item Alt " + i + " : " + tLoaded.getUnlocalizedName()); } - flag = false; } + mOreDictAlt.add(tAltCurrent); + ItemStack tLoaded = GT_Utility.loadItem(aTag, "" + i); + if (tLoaded == null) { + continue; + } + aInputs.add(tLoaded); if (GT_Values.D1) { - GT_FML_LOGGER.info(i + (flag ? " not accepted" : " accepted")); + GT_FML_LOGGER.info("Item " + i + " : " + tLoaded.getUnlocalizedName()); } } @@ -129,18 +126,16 @@ public class GT_AssemblyLineUtils { } for (int i = 0; i < 4; i++) { if (!aTag.hasKey("f" + i)) continue; - aFluidInputs[i] = GT_Utility.loadFluid(aTag, "f" + i); - if (aFluidInputs[i] == null) continue; + FluidStack tLoaded = GT_Utility.loadFluid(aTag, "f" + i); + if (tLoaded == null) continue; + aFluidInputs.add(tLoaded); if (GT_Values.D1) { - GT_FML_LOGGER.info("Fluid " + i + " " + aFluidInputs[i].getUnlocalizedName()); - } - if (GT_Values.D1) { - GT_FML_LOGGER.info(i + " accepted"); + GT_FML_LOGGER.info("Fluid " + i + " " + tLoaded.getUnlocalizedName()); } } - aOutputs = new ItemStack[]{GT_Utility.loadItem(aTag, "output")}; - if (!aTag.hasKey("output") || !aTag.hasKey("time") || aTag.getInteger("time") <= 0 || !aTag.hasKey("eu") || aOutputs[0] == null || !GT_Utility.isStackValid(aOutputs[0])) { - return null; + aOutput = GT_Utility.loadItem(aTag, "output"); + if (!aTag.hasKey("output") || !aTag.hasKey("time") || aTag.getInteger("time") <= 0 || !aTag.hasKey("eu") || !GT_Utility.isStackValid(aOutput)) { + return LookupResultType.INVALID_STICK.getResult(); } if (GT_Values.D1) { GT_FML_LOGGER.info("Found Data Stick recipe"); @@ -151,25 +146,41 @@ public class GT_AssemblyLineUtils { // Try build a recipe instance if (aReturnBuiltRecipe) { - GT_Recipe_AssemblyLine aBuiltRecipe = new GT_Recipe_AssemblyLine(null, 0, aInputs, aFluidInputs, aOutputs[0], aTime, aEU); - return aBuiltRecipe; + return LookupResultType.VALID_STACK_AND_VALID_HASH.getResult(new GT_Recipe_AssemblyLine(null, 0, aInputs.toArray(new ItemStack[0]), aFluidInputs.toArray(new FluidStack[0]), aOutput, aTime, aEU)); } for (GT_Recipe_AssemblyLine aRecipe : GT_Recipe.GT_Recipe_AssemblyLine.sAssemblylineRecipes) { - if (aRecipe.mEUt == aEU && aRecipe.mDuration == aTime) { - if (GT_Utility.areStacksEqual(aOutputs[0], aRecipe.mOutput, true)) { - if (Arrays.equals(aRecipe.mInputs, aInputs) && Arrays.equals(aRecipe.mFluidInputs, aFluidInputs)) { - // Cache it - String aRecipeHash = generateRecipeHash(aRecipe); - sRecipeCacheByRecipeHash.put(aRecipeHash, aRecipe); - sRecipeCacheByOutput.put(new GT_ItemStack(aRecipe.mOutput), aRecipe); - return aRecipe; - } - } + if (aRecipe.mEUt != aEU || aRecipe.mDuration != aTime) continue; + if (!GT_Utility.areStacksEqual(aOutput, aRecipe.mOutput, true)) continue; + if (!GT_Utility.areStackListsEqual(Arrays.asList(aRecipe.mInputs), aInputs, false, true)) continue; + if (!Objects.equals(Arrays.asList(aRecipe.mFluidInputs), aFluidInputs)) continue; + if (!areStacksEqual(aRecipe.mOreDictAlt, mOreDictAlt)) continue; + + // Cache it + String aRecipeHash = generateRecipeHash(aRecipe); + sRecipeCacheByRecipeHash.put(aRecipeHash, aRecipe); + sRecipeCacheByOutput.put(new GT_ItemStack(aRecipe.mOutput), aRecipe); + if (doesDataStickHaveRecipeHash(aDataStick)) { + String aStickHash = getHashFromDataStack(aDataStick); + if (aRecipeHash.equals(aStickHash)) + return LookupResultType.VALID_STACK_AND_VALID_HASH.getResult(aRecipe); } + return LookupResultType.VALID_STACK_AND_VALID_RECIPE.getResult(aRecipe); } - return null; + return LookupResultType.VALID_STACK_BUT_INVALID_RECIPE.getResult(); + } + + private static boolean areStacksEqual(ItemStack[][] lhs, List<List<ItemStack>> rhs) { + for (int i = 0; i < lhs.length; i++) { + if (!areStacksEqual(lhs[i], rhs.get(i))) + return false; + } + return true; + } + + private static boolean areStacksEqual(ItemStack[] lhs, List<ItemStack> rhs) { + return lhs == null ? rhs.isEmpty() : !rhs.isEmpty() && GT_Utility.areStackListsEqual(Arrays.asList(lhs), rhs, false, true); } @@ -210,7 +221,7 @@ public class GT_AssemblyLineUtils { public static String generateRecipeHash(GT_Recipe_AssemblyLine aRecipe) { String aHash = "Invalid.Recipe.Hash"; if (aRecipe != null) { - aHash = "Hash."+aRecipe.hashCode(); + aHash = "Hash."+aRecipe.getPersistentHash(); } return aHash; } @@ -343,7 +354,7 @@ public class GT_AssemblyLineUtils { String aHash = generateRecipeHash(aNewRecipe); if (GT_Values.D1) { - GT_Recipe_AssemblyLine aOldRecipe = findAssemblyLineRecipeFromDataStick(aDataStick, true); + GT_Recipe_AssemblyLine aOldRecipe = findAssemblyLineRecipeFromDataStick(aDataStick, true).recipe; GT_FML_LOGGER.info("Updating data stick: "+aDataStick.getDisplayName()+" | Old Recipe Hash: "+generateRecipeHash(aOldRecipe)+", New Recipe Hash: "+aHash); } @@ -437,4 +448,49 @@ public class GT_AssemblyLineUtils { return false; } + public enum LookupResultType { + INVALID_STICK(true), + VALID_STACK_BUT_INVALID_RECIPE(true), + VALID_STACK_AND_VALID_RECIPE(false), + VALID_STACK_AND_VALID_HASH(false); + + private final boolean recipeNull; + private LookupResult singletonResult; + + LookupResultType(boolean recipeNull) { + this.recipeNull = recipeNull; + } + + public LookupResult getResult() { + if (!recipeNull) + throw new IllegalArgumentException("This result type require a nonnull recipe"); + if (singletonResult == null) + singletonResult = new LookupResult(null, this); + return singletonResult; + } + + public LookupResult getResult(GT_Recipe_AssemblyLine recipe) { + if ((recipe == null) != recipeNull) + throw new IllegalArgumentException("This result type does not allow given input"); + return new LookupResult(recipe, this); + } + } + + public static class LookupResult { + private final GT_Recipe_AssemblyLine recipe; + private final LookupResultType type; + + LookupResult(GT_Recipe_AssemblyLine recipe, LookupResultType type) { + this.recipe = recipe; + this.type = type; + } + + public GT_Recipe_AssemblyLine getRecipe() { + return recipe; + } + + public LookupResultType getType() { + return type; + } + } } diff --git a/src/main/java/gregtech/api/util/GT_Recipe.java b/src/main/java/gregtech/api/util/GT_Recipe.java index 7d475b4dfd..1b54e10795 100644 --- a/src/main/java/gregtech/api/util/GT_Recipe.java +++ b/src/main/java/gregtech/api/util/GT_Recipe.java @@ -565,6 +565,7 @@ public class GT_Recipe implements Comparable<GT_Recipe> { public int mDuration; public int mEUt; public ItemStack[][] mOreDictAlt; + private int mPersistentHash; public GT_Recipe_AssemblyLine(ItemStack aResearchItem, int aResearchTime, ItemStack[] aInputs, FluidStack[] aFluidInputs, ItemStack aOutput, int aDuration, int aEUt) { this(aResearchItem, aResearchTime, aInputs, aFluidInputs, aOutput, aDuration, aEUt, new ItemStack[aInputs.length][]); @@ -658,7 +659,19 @@ public class GT_Recipe implements Comparable<GT_Recipe> { && this.mEUt == other.mEUt && this.mResearchTime == other.mResearchTime; } - + + public int getPersistentHash() { + return mPersistentHash; + } + + public void setPersistentHash(int aPersistentHash) { + if (this.mPersistentHash != 0) + throw new IllegalStateException("Cannot set persistent hash twice!"); + if (aPersistentHash == 0) + this.mPersistentHash = 1; + else + this.mPersistentHash = aPersistentHash; + } } public static class GT_Recipe_Map { diff --git a/src/main/java/gregtech/api/util/GT_Utility.java b/src/main/java/gregtech/api/util/GT_Utility.java index 3b0ec94a92..07e5fcec73 100644 --- a/src/main/java/gregtech/api/util/GT_Utility.java +++ b/src/main/java/gregtech/api/util/GT_Utility.java @@ -9,6 +9,7 @@ import com.gtnewhorizon.structurelib.alignment.IAlignment; import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider; import com.mojang.authlib.GameProfile; import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.registry.GameRegistry; import gregtech.api.GregTech_API; import gregtech.api.damagesources.GT_DamageSources; import gregtech.api.damagesources.GT_DamageSources.DamageSourceHotItem; @@ -965,6 +966,30 @@ public class GT_Utility { && (Items.feather.getDamage(aStack1) == Items.feather.getDamage(aStack2) || Items.feather.getDamage(aStack1) == W || Items.feather.getDamage(aStack2) == W); } + /** + * Treat both null list, or both null item stack at same list position as equal. + * + * Since ItemStack doesn't override equals and hashCode, you cannot just use Objects.equals + */ + public static boolean areStackListsEqual(List<ItemStack> lhs, List<ItemStack> rhs, boolean ignoreStackSize, boolean ignoreNBT) { + if (lhs == null) return rhs == null; + if (rhs == null) return false; + if (lhs.size() != rhs.size()) return false; + for (Iterator<ItemStack> it1 = lhs.iterator(), it2 = rhs.iterator(); it1.hasNext() && it2.hasNext(); ) { + if (!areStacksEqualExtended(it1.next(), it2.next(), ignoreStackSize, ignoreNBT)) + return false; + } + return true; + } + + private static boolean areStacksEqualExtended(ItemStack lhs, ItemStack rhs, boolean ignoreStackSize, boolean ignoreNBT) { + if (lhs == null) return rhs == null; + if (rhs == null) return false; + return lhs.getItem() == rhs.getItem() && + (ignoreNBT || Objects.equals(lhs.stackTagCompound, rhs.stackTagCompound)) && + (ignoreStackSize || lhs.stackSize == rhs.stackSize); + } + public static boolean areUnificationsEqual(ItemStack aStack1, ItemStack aStack2) { return areUnificationsEqual(aStack1, aStack2, false); } @@ -3014,4 +3039,31 @@ public class GT_Utility { public static int clamp(int val, int lo, int hi) { return val > hi ? hi : val < lo ? lo : val; } + + /** + * Hash an item stack for the purpose of storing hash across launches + */ + public static int persistentHash(ItemStack aStack, boolean aUseStackSize, boolean aUseNBT) { + if (aStack == null) + return 0; + int result = Objects.hashCode(GameRegistry.findUniqueIdentifierFor(aStack.getItem())); + result = result * 31 + Items.feather.getDamage(aStack); + + if (aUseStackSize) result = result * 31 + aStack.stackSize; + if (aUseNBT) result = result * 31 + Objects.hashCode(aStack.stackTagCompound); + return result; + } + + /** + * Hash an item stack for the purpose of storing hash across launches + */ + public static int persistentHash(FluidStack aStack, boolean aUseStackSize, boolean aUseNBT) { + if (aStack == null) + return 0; + int base = Objects.hashCode(aStack.getFluid().getName()); + + if (aUseStackSize) base = base * 31 + aStack.amount; + if (aUseNBT) base = base * 31 + Objects.hashCode(aStack.tag); + return base; + } } diff --git a/src/main/java/gregtech/common/GT_RecipeAdder.java b/src/main/java/gregtech/common/GT_RecipeAdder.java index 69a5254c44..f130c65adf 100644 --- a/src/main/java/gregtech/common/GT_RecipeAdder.java +++ b/src/main/java/gregtech/common/GT_RecipeAdder.java @@ -1,6 +1,7 @@ package gregtech.common; import cpw.mods.fml.common.Loader; +import cpw.mods.fml.common.registry.GameRegistry; import gregtech.GT_Mod; import gregtech.api.GregTech_API; import gregtech.api.enums.GT_Values; @@ -16,6 +17,7 @@ import gregtech.common.items.GT_IntegratedCircuit_Item; import mods.railcraft.common.blocks.aesthetics.cube.EnumCube; import mods.railcraft.common.items.RailcraftToolItems; import net.minecraft.init.Blocks; +import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; @@ -23,6 +25,7 @@ import net.minecraftforge.oredict.OreDictionary; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; import java.util.List; import static gregtech.GT_Mod.GT_FML_LOGGER; @@ -1418,7 +1421,19 @@ public class GT_RecipeAdder implements IGT_RecipeAdder { } GT_Recipe.GT_Recipe_Map.sScannerFakeRecipes.addFakeRecipe(false, new ItemStack[]{aResearchItem}, new ItemStack[]{aOutput}, new ItemStack[]{ItemList.Tool_DataStick.getWithName(1L, "Writes Research result", new Object[0])}, null, null, aResearchTime, 30, -201); GT_Recipe.GT_Recipe_Map.sAssemblylineVisualRecipes.addFakeRecipe(false, aInputs, new ItemStack[]{aOutput}, new ItemStack[]{ItemList.Tool_DataStick.getWithName(1L, "Reads Research result", new Object[0])}, aFluidInputs, null, aDuration, aEUt, 0,true); - GT_Recipe.GT_Recipe_AssemblyLine.sAssemblylineRecipes.add(new GT_Recipe_AssemblyLine( aResearchItem, aResearchTime, aInputs, aFluidInputs, aOutput, aDuration, aEUt)); + GT_Recipe_AssemblyLine tRecipe = new GT_Recipe_AssemblyLine(aResearchItem, aResearchTime, aInputs, aFluidInputs, aOutput, aDuration, aEUt); + int tPersistentHash = 1; + for (ItemStack tInput : aInputs) + tPersistentHash = tPersistentHash * 31 + GT_Utility.persistentHash(tInput, true, false); + tPersistentHash = tPersistentHash * 31 + GT_Utility.persistentHash(aResearchItem, true, false); + tPersistentHash = tPersistentHash * 31 + GT_Utility.persistentHash(aOutput, true, false); + for (FluidStack tFluidInput : aFluidInputs) + tPersistentHash = tPersistentHash * 31 + GT_Utility.persistentHash(tFluidInput, true, false); + tPersistentHash = tPersistentHash * 31 + aResearchTime; + tPersistentHash = tPersistentHash * 31 + aDuration; + tPersistentHash = tPersistentHash * 31 + aEUt; + tRecipe.setPersistentHash(tPersistentHash == 0 ? 1 : tPersistentHash); + GT_Recipe.GT_Recipe_AssemblyLine.sAssemblylineRecipes.add(tRecipe); return true; } @@ -1432,17 +1447,23 @@ public class GT_RecipeAdder implements IGT_RecipeAdder { } ItemStack[] tInputs = new ItemStack[aInputs.length]; ItemStack[][] tAlts = new ItemStack[aInputs.length][]; + int tPersistentHash = 1; for(int i = 0; i < aInputs.length; i++){ Object obj = aInputs[i]; if (obj instanceof ItemStack) { tInputs[i] = (ItemStack) obj; tAlts[i] = null; + tPersistentHash = tPersistentHash * 31 + GT_Utility.persistentHash(tInputs[i], true, false); continue; } else if (obj instanceof ItemStack[]) { ItemStack[] aStacks = (ItemStack[]) obj; if (aStacks.length > 0) { tInputs[i] = aStacks[0]; tAlts[i] = (ItemStack[]) Arrays.copyOf(aStacks, aStacks.length); + for (ItemStack tAlt : tAlts[i]) { + tPersistentHash = tPersistentHash * 31 + GT_Utility.persistentHash(tAlt, true, false); + } + tPersistentHash *= 31; continue; } } else if (obj instanceof Object[]) { @@ -1450,6 +1471,11 @@ public class GT_RecipeAdder implements IGT_RecipeAdder { List<ItemStack> tList; if (objs.length >= 2 && !(tList = GT_OreDictUnificator.getOres(objs[0])).isEmpty()) { try { + // sort the output, so the hash code is stable across launches + tList.sort(Comparator.<ItemStack, String>comparing(s -> GameRegistry.findUniqueIdentifierFor(s.getItem()).modId) + .thenComparing(s -> GameRegistry.findUniqueIdentifierFor(s.getItem()).modId) + .thenComparingInt(Items.feather::getDamage) + .thenComparingInt(s -> s.stackSize)); int tAmount = ((Number) objs[1]).intValue(); List<ItemStack> uList = new ArrayList<>(); for (ItemStack tStack : tList) { @@ -1460,16 +1486,30 @@ public class GT_RecipeAdder implements IGT_RecipeAdder { tInputs[i] = uStack; } } - tAlts[i] = uList.toArray(new ItemStack[uList.size()]); + tAlts[i] = uList.toArray(new ItemStack[0]); + tPersistentHash = tPersistentHash * 31 + (objs[0] == null ? "" : objs[0].toString()).hashCode(); + tPersistentHash = tPersistentHash * 31 + tAmount; continue; } catch (Exception t) {} } } GT_FML_LOGGER.info("addAssemblingLineRecipe "+aResearchItem.getDisplayName()+" --> "+aOutput.getUnlocalizedName()+" there is some null item in that recipe"); } + tPersistentHash = tPersistentHash * 31 + GT_Utility.persistentHash(aResearchItem, true, false); + tPersistentHash = tPersistentHash * 31 + GT_Utility.persistentHash(aOutput, true, false); + for (FluidStack tFluidInput : aFluidInputs) { + if (tFluidInput == null) + continue; + tPersistentHash = tPersistentHash * 31 + GT_Utility.persistentHash(tFluidInput, true, false); + } + tPersistentHash = tPersistentHash * 31 + aResearchTime; + tPersistentHash = tPersistentHash * 31 + aDuration; + tPersistentHash = tPersistentHash * 31 + aEUt; GT_Recipe.GT_Recipe_Map.sScannerFakeRecipes.addFakeRecipe(false, new ItemStack[]{aResearchItem}, new ItemStack[]{aOutput}, new ItemStack[]{ItemList.Tool_DataStick.getWithName(1L, "Writes Research result", new Object[0])}, null, null, aResearchTime, 30, -201); GT_Recipe.GT_Recipe_Map.sAssemblylineVisualRecipes.addFakeRecipe(false,tInputs,new ItemStack[]{aOutput},new ItemStack[]{ItemList.Tool_DataStick.getWithName(1L, "Reads Research result", new Object[0])},aFluidInputs,null,aDuration,aEUt,0,tAlts,true); - GT_Recipe.GT_Recipe_AssemblyLine.sAssemblylineRecipes.add(new GT_Recipe_AssemblyLine( aResearchItem, aResearchTime, tInputs, aFluidInputs, aOutput, aDuration, aEUt, tAlts)); + GT_Recipe_AssemblyLine tRecipe = new GT_Recipe_AssemblyLine(aResearchItem, aResearchTime, tInputs, aFluidInputs, aOutput, aDuration, aEUt, tAlts); + tRecipe.setPersistentHash(tPersistentHash == 0 ? 1 : tPersistentHash); + GT_Recipe.GT_Recipe_AssemblyLine.sAssemblylineRecipes.add(tRecipe); return true; } diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_AssemblyLine.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_AssemblyLine.java index 41475fd600..075ca564cb 100644 --- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_AssemblyLine.java +++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_AssemblyLine.java @@ -16,6 +16,7 @@ import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMul import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch; import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_DataAccess; import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input; +import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_InputBus; import gregtech.api.render.TextureFactory; import gregtech.api.util.GT_AssemblyLineUtils; import gregtech.api.util.GT_Multiblock_Tooltip_Builder; @@ -24,10 +25,10 @@ import gregtech.api.util.GT_Recipe.GT_Recipe_AssemblyLine; import gregtech.api.util.GT_Utility; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.fluids.FluidStack; import java.util.ArrayList; +import java.util.Arrays; import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock; import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlockAnyMeta; @@ -169,77 +170,71 @@ public class GT_MetaTileEntity_AssemblyLine extends GT_MetaTileEntity_EnhancedMu GT_FML_LOGGER.info("Stick accepted, " + tDataStickList.size() + " Data Sticks found"); } - ItemStack[] tStack = null; - FluidStack[] tFluids = null; - boolean findRecipe = false; + int[] tStack = null; + int[] tFluids = null; + boolean foundRecipe = false; nextDataStick: for (ItemStack tDataStick : tDataStickList) { - GT_Recipe_AssemblyLine aFoundRecipe = GT_AssemblyLineUtils.findAssemblyLineRecipeFromDataStick(tDataStick); + GT_AssemblyLineUtils.LookupResult tLookupResult = GT_AssemblyLineUtils.findAssemblyLineRecipeFromDataStick(tDataStick, false); - if (aFoundRecipe == null) + if (tLookupResult.getType() == GT_AssemblyLineUtils.LookupResultType.INVALID_STICK) continue; + GT_Recipe_AssemblyLine tRecipe = tLookupResult.getRecipe(); // Check if the recipe on the data stick is the current recipe for it's given output, if not we update it and continue to next. - if (!GT_AssemblyLineUtils.processDataStick(tDataStick)) { - continue; - } - - tStack = aFoundRecipe.mInputs; - tFluids = aFoundRecipe.mFluidInputs; + if (tLookupResult.getType() != GT_AssemblyLineUtils.LookupResultType.VALID_STACK_AND_VALID_HASH) { + tRecipe = GT_AssemblyLineUtils.processDataStick(tDataStick); + if (tRecipe == null) { + continue; + } + } // So here we check against the recipe found on the data stick. // If we run into missing buses/hatches or bad inputs, we go to the next data stick. // This check only happens if we have a valid up to date data stick. // Check Inputs allign - int aItemCount = aFoundRecipe.mInputs.length; - for (int i = 0; i < 15; i++) { - if (i >= aItemCount) { - continue; - } - else { - if (mInputBusses.get(i) == null) { - continue nextDataStick; - } - else { - ItemStack stackInSlot = mInputBusses.get(i).getBaseMetaTileEntity().getStackInSlot(0); - if (!GT_Utility.areStacksEqual(tStack[i], stackInSlot, true) || tStack[i].stackSize <= stackInSlot.stackSize) { - continue nextDataStick; - } - if (GT_Values.D1) { - GT_FML_LOGGER.info("Item: " + i + " accepted"); - } - } - } + int aItemCount = tRecipe.mInputs.length; + tStack = new int[aItemCount]; + for (int i = 0; i < aItemCount; i++) { + GT_MetaTileEntity_Hatch_InputBus tInputBus = mInputBusses.get(i); + if (tInputBus == null) { + continue nextDataStick; + } + ItemStack tSlotStack = tInputBus.getStackInSlot(0); + int tRequiredStackSize = isStackValidIngredient(tSlotStack, tRecipe.mInputs[i], tRecipe.mOreDictAlt[i]); + if (tRequiredStackSize < 0) continue nextDataStick; + + tStack[i] = tRequiredStackSize; + if (GT_Values.D1) { + GT_FML_LOGGER.info("Item: " + i + " accepted"); + } } // Check Fluid Inputs allign - int aFluidCount = aFoundRecipe.mFluidInputs.length; - for (int i = 0; i < 4; i++){ - if (i >= aFluidCount) { - continue; - } - else { - if (mInputHatches.get(i) == null) { + int aFluidCount = tRecipe.mFluidInputs.length; + tFluids = new int[aFluidCount]; + for (int i = 0; i < aFluidCount; i++){ + if (mInputHatches.get(i) == null) { + continue nextDataStick; + } + else { + FluidStack fluidInHatch = mInputHatches.get(i).mFluid; + if (!GT_Utility.areFluidsEqual(fluidInHatch, tRecipe.mFluidInputs[i], true) || fluidInHatch.amount < tRecipe.mFluidInputs[i].amount) { continue nextDataStick; } - else { - FluidStack fluidInHatch = mInputHatches.get(i).mFluid; - if (!GT_Utility.areFluidsEqual(fluidInHatch, tFluids[i], true) || fluidInHatch.amount < tFluids[i].amount) { - continue nextDataStick; - } - if (GT_Values.D1) { - GT_FML_LOGGER.info("Fluid:" + i + " accepted"); - } - } - } + tFluids[i] = tRecipe.mFluidInputs[i].amount; + if (GT_Values.D1) { + GT_FML_LOGGER.info("Fluid:" + i + " accepted"); + } + } } if (GT_Values.D1) { GT_FML_LOGGER.info("Check overclock"); } - calculateOverclockedNessMulti(aFoundRecipe.mEUt, aFoundRecipe.mDuration, 1, getMaxInputVoltage()); + calculateOverclockedNessMulti(tRecipe.mEUt, tRecipe.mDuration, 1, getMaxInputVoltage()); //In case recipe is too OP for that machine if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1) { if (GT_Values.D1) { @@ -250,11 +245,13 @@ public class GT_MetaTileEntity_AssemblyLine extends GT_MetaTileEntity_EnhancedMu if (GT_Values.D1) { GT_FML_LOGGER.info("Find available recipe"); } - findRecipe = true; + mOutputItems = new ItemStack[] {tRecipe.mOutput}; + foundRecipe = true; + break ; } // Best not to run this recipe. - if (!findRecipe || tStack == null || tStack.length <= 0 || tFluids == null || tFluids.length <= 0) { + if (!foundRecipe || tStack.length <= 0) { return false; } @@ -262,18 +259,13 @@ public class GT_MetaTileEntity_AssemblyLine extends GT_MetaTileEntity_EnhancedMu if (GT_Values.D1) { GT_FML_LOGGER.info("All checked start consuming inputs"); } - for (int i = 0; i < 15; i++) { - if (tStack[i] == null) { - continue; - } - ItemStack stackInSlot = mInputBusses.get(i).getBaseMetaTileEntity().getStackInSlot(0); - stackInSlot.stackSize -= tStack[i].stackSize; + for (int i = 0; i < tStack.length; i++) { + ItemStack stackInSlot = mInputBusses.get(i).getStackInSlot(0); + stackInSlot.stackSize -= tStack[i]; } - for (int i = 0; i < 4; i++) { - if (tFluids[i] == null) - continue; - mInputHatches.get(i).mFluid.amount -= tFluids[i].amount; + for (int i = 0; i < tFluids.length; i++) { + mInputHatches.get(i).mFluid.amount -= tFluids[i]; if (mInputHatches.get(i).mFluid.amount <= 0) { mInputHatches.get(i).mFluid = null; } @@ -286,11 +278,28 @@ public class GT_MetaTileEntity_AssemblyLine extends GT_MetaTileEntity_EnhancedMu this.mEfficiencyIncrease = 10000; updateSlots(); if (GT_Values.D1) { - GT_FML_LOGGER.info("Recipe sucessfull"); + GT_FML_LOGGER.info("Recipe successful"); } return true; } + private static int isStackValidIngredient(ItemStack aSlotStack, ItemStack aIngredient, ItemStack[] alts) { + if (alts == null || alts.length == 0) + return isStackValidIngredient(aSlotStack, aIngredient); + for (ItemStack tAltStack : alts) { + int i = isStackValidIngredient(aSlotStack, tAltStack); + if (i >= 0) + return i; + } + return -1; + } + + private static int isStackValidIngredient(ItemStack aSlotStack, ItemStack aIngredient) { + if (GT_Utility.areStacksEqual(aSlotStack, aIngredient, true) && aIngredient.stackSize <= aSlotStack.stackSize) + return aIngredient.stackSize; + return -1; + } + @Override public boolean onRunningTick(ItemStack aStack) { for(GT_MetaTileEntity_Hatch_DataAccess hatch_dataAccess:mDataAccessHatches){ |