diff options
Diffstat (limited to 'src/main/java/gregtech/api')
4 files changed, 522 insertions, 1 deletions
diff --git a/src/main/java/gregtech/api/enums/Materials.java b/src/main/java/gregtech/api/enums/Materials.java index 7517f379b1..c2bd9cee92 100644 --- a/src/main/java/gregtech/api/enums/Materials.java +++ b/src/main/java/gregtech/api/enums/Materials.java @@ -752,8 +752,9 @@ public class Materials implements IColorModulationContainer, ISubTagContainer { public static Materials Polybenzimidazole = new Materials(599, TextureSet.SET_DULL ,3.0F, 64, 1, 1|2 |64|128 , 45, 45, 45, 0, "Polybenzimidazole" , "Polybenzimidazole" , 0, 0, 1450, 0, false, false, 1, 1, 1, Dyes.dyeBlack , 0, Arrays.asList(new MaterialStack(Carbon, 20), new MaterialStack(Nitrogen, 4), new MaterialStack(Hydrogen, 12)), Arrays.asList(new TC_AspectStack(TC_Aspects.ORDO, 2),new TC_AspectStack(TC_Aspects.VOLATUS, 1))); + public static Materials MTBEMixture = new MaterialBuilder(983, TextureSet.SET_FLUID , "MTBE Reaction Mixture").addCell().addGas().setRGB(255, 255, 255).setColor(Dyes.dyeWhite).constructMaterial(); public static Materials NitrousOxide = new MaterialBuilder(993, TextureSet.SET_FLUID , "Nitrous Oxide").addCell().addGas().setRGB(125, 200, 255).setColor(Dyes.dyeBlue).setMaterialList(new MaterialStack(Nitrogen, 2), new MaterialStack(Oxygen, 1)).addElectrolyzerRecipe().constructMaterial(); - public static Materials AntiKnock = new MaterialBuilder(994, TextureSet.SET_FLUID , "Ethyl Tert-Butyl Ether").addCell().addFluid().setRGB(255, 255, 255).setColor(Dyes.dyeWhite).constructMaterial(); + public static Materials AntiKnock = new MaterialBuilder(994, TextureSet.SET_FLUID , "Anti-Knock Agent").setName("EthylTertButylEther").addCell().addFluid().setRGB(255, 255, 255).setColor(Dyes.dyeWhite).constructMaterial(); public static Materials Octane = new MaterialBuilder(995, TextureSet.SET_FLUID , "Octane").addCell().addFluid().setRGB(255, 255, 255).setColor(Dyes.dyeWhite).setFuelType(MaterialBuilder.DIESEL).setFuelPower(80).setMaterialList(new MaterialStack(Carbon, 8), new MaterialStack(Hydrogen, 18)).constructMaterial(); public static Materials GasolineRaw = new MaterialBuilder(996, TextureSet.SET_FLUID , "Raw Gasoline").addCell().addFluid().setRGB(255,100,0).setColor(Dyes.dyeOrange).constructMaterial(); public static Materials GasolineRegular = new MaterialBuilder(997, TextureSet.SET_FLUID , "Gasoline").addCell().addFluid().setRGB(255,165,0).setColor(Dyes.dyeOrange).setFuelType(MaterialBuilder.DIESEL).setFuelPower(576).constructMaterial(); diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Fluid.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Fluid.java index 8479477d12..8cce529050 100644 --- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Fluid.java +++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Fluid.java @@ -338,6 +338,7 @@ public class GT_MetaPipeEntity_Fluid extends MetaPipeEntity { // Tank, From, Amount to receive List<MutableTriple<IFluidHandler, ForgeDirection, Integer>> tTanks = new ArrayList<>(); + int amount = tFluid.amount; for (byte aSide, i = 0, j = (byte) aBaseMetaTileEntity.getRandomNumber(6); i < 6; i++) { // Get a list of tanks accepting fluids, and what side they're on @@ -352,6 +353,7 @@ public class GT_MetaPipeEntity_Fluid extends MetaPipeEntity { if (tTank.fill(ForgeDirection.getOrientation(tSide), tFluid, false) > 0) { tTanks.add(new MutableTriple<>(tTank, ForgeDirection.getOrientation(tSide), 0)); } + tFluid.amount = amount; // Because some mods do actually modify input fluid stack } } diff --git a/src/main/java/gregtech/api/util/GT_AssemblyLineUtils.java b/src/main/java/gregtech/api/util/GT_AssemblyLineUtils.java new file mode 100644 index 0000000000..f35f1962d1 --- /dev/null +++ b/src/main/java/gregtech/api/util/GT_AssemblyLineUtils.java @@ -0,0 +1,440 @@ +package gregtech.api.util; + +import static gregtech.GT_Mod.GT_FML_LOGGER; + +import java.util.HashMap; + +import cpw.mods.fml.common.FMLCommonHandler; +import gregtech.api.enums.GT_Values; +import gregtech.api.enums.ItemList; +import gregtech.api.objects.GT_ItemStack; +import gregtech.api.util.GT_Recipe.GT_Recipe_AssemblyLine; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTTagString; +import net.minecraftforge.fluids.FluidStack; +import scala.actors.threadpool.Arrays; + +public class GT_AssemblyLineUtils { + + /** + * A cache of Recipes using the Output as Key. + */ + private static HashMap<GT_ItemStack, GT_Recipe_AssemblyLine> sRecipeCacheByOutput = new HashMap<GT_ItemStack, GT_Recipe_AssemblyLine>(); + /** + * A cache of Recipes using the Recipe Hash String as Key. + */ + private static HashMap<String, GT_Recipe_AssemblyLine> sRecipeCacheByRecipeHash = new HashMap<String, GT_Recipe_AssemblyLine>(); + + + + /** + * Checks the DataStick for deprecated/invalid recipes, updating them as required. + * @param aDataStick - The DataStick to process + * @return Is this DataStick now valid with a current recipe? + */ + public static boolean processDataStick(ItemStack aDataStick) { + if (!isItemDataStick(aDataStick)) { + return false; + } + if (doesDataStickNeedUpdate(aDataStick)) { + ItemStack aStickOutput = getDataStickOutput(aDataStick); + if (aStickOutput != null) { + GT_Recipe_AssemblyLine aIntendedRecipe = findAssemblyLineRecipeByOutput(aStickOutput); + if (aIntendedRecipe != null) { + return setAssemblyLineRecipeOnDataStick(aDataStick, aIntendedRecipe); + } + } + return false; + } + return true; + } + + + /** + * Finds an Assembly Line recipe from a DataStick. + * @param aDataStick - The DataStick to check. + * @return The GT_Recipe_AssemblyLine recipe contained on the DataStick, if any. + */ + public static GT_Recipe_AssemblyLine findAssemblyLineRecipeFromDataStick(ItemStack aDataStick) { + return findAssemblyLineRecipeFromDataStick(aDataStick, false); + } + + /** + * Finds an Assembly Line recipe from a DataStick. + * @param aDataStick - The DataStick to check. + * @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) { + if (!isItemDataStick(aDataStick)) { + return null; + } + ItemStack[] aInputs = new ItemStack[15]; + ItemStack[] aOutputs = new ItemStack[1]; + FluidStack[] aFluidInputs = new FluidStack[4]; + + NBTTagCompound aTag = aDataStick.getTagCompound(); + if (aTag == null) { + return null; + } + + //Get From Cache + if (doesDataStickHaveRecipeHash(aDataStick)) { + GT_Recipe_AssemblyLine aRecipeFromCache = sRecipeCacheByRecipeHash.get(getHashFromDataStack(aDataStick)); + if (aRecipeFromCache != null) { + return aRecipeFromCache; + } + } + + for (int i = 0; i < 15; i++) { + int count = aTag.getInteger("a" + i); + if (!aTag.hasKey("" + i) && count <= 0) { + 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; + continue; + } + if (GT_Values.D1) { + GT_FML_LOGGER.info("Item " + i + " : " + aInputs[i].getUnlocalizedName()); + } + flag = false; + } + if (GT_Values.D1) { + GT_FML_LOGGER.info(i + (flag ? " not accepted" : " accepted")); + } + } + + if (GT_Values.D1) { + GT_FML_LOGGER.info("All Items done, start fluid check"); + } + 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; + if (GT_Values.D1) { + GT_FML_LOGGER.info("Fluid " + i + " " + aFluidInputs[i].getUnlocalizedName()); + } + if (GT_Values.D1) { + GT_FML_LOGGER.info(i + " accepted"); + } + } + 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; + } + if (GT_Values.D1) { + GT_FML_LOGGER.info("Found Data Stick recipe"); + } + + int aTime = aTag.getInteger("time"); + int aEU = aTag.getInteger("eu"); + + // 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; + } + + + 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; + } + } + } + } + return null; + } + + + /** + * Finds a GT_Recipe_AssemblyLine based on the expected output ItemStack. + * @param aOutput - The Output of a GT_Recipe_AssemblyLine. + * @return First found GT_Recipe_AssemblyLine with matching output. + */ + public static GT_Recipe_AssemblyLine findAssemblyLineRecipeByOutput(ItemStack aOutput) { + if (aOutput == null) { + return null; + } + + // Check the cache + GT_ItemStack aCacheStack = new GT_ItemStack(aOutput); + GT_Recipe_AssemblyLine aRecipeFromCache = sRecipeCacheByOutput.get(aCacheStack); + if (aRecipeFromCache != null) { + return aRecipeFromCache; + } + + // Iterate all recipes and return the first matching based on Output. + for (GT_Recipe_AssemblyLine aRecipe : GT_Recipe.GT_Recipe_AssemblyLine.sAssemblylineRecipes) { + ItemStack aRecipeOutput = aRecipe.mOutput; + if (GT_Utility.areStacksEqual(aRecipeOutput, aOutput)) { + // Cache it to prevent future iterations of all recipes + sRecipeCacheByOutput.put(aCacheStack, aRecipe); + sRecipeCacheByRecipeHash.put(generateRecipeHash(aRecipe), aRecipe); + return aRecipe; + } + } + return null; + } + + /** + * @param aRecipe - The recipe to generate a Recipe Hash String from. + * @return The Recipe Hash String. + */ + public static String generateRecipeHash(GT_Recipe_AssemblyLine aRecipe) { + String aHash = "Invalid.Recipe.Hash"; + if (aRecipe != null) { + aHash = "Hash."+aRecipe.hashCode(); + } + return aHash; + } + + /** + * @param aHash - Recipe hash String, may be null but will just be treated as invalid. + * @return Is this Recipe Hash String valid? + */ + public static boolean isValidHash(String aHash) { + if (aHash != null && aHash.length() > 0) { + if (!aHash.equals("Invalid.Recipe.Hash") && aHash.contains("Hash.")) { + return true; + } + } + return false; + } + + /** + * @param aStack - The ItemStack to check. + * @return Is this ItemStack a Data Stick? + */ + public static boolean isItemDataStick(ItemStack aStack) { + return GT_Utility.isStackValid(aStack) && ItemList.Tool_DataStick.isStackEqual(aStack, false, true); + } + + /** + * @param aDataStick - The Data Stick to check. + * @return Does this Data Stick have a valid output ItemStack? + */ + public static boolean doesDataStickHaveOutput(ItemStack aDataStick) { + if (isItemDataStick(aDataStick) && aDataStick.hasTagCompound() && aDataStick.getTagCompound().hasKey("output")) { + return true; + } + return false; + } + + /** + * @param aDataStick - The Data Stick to check. + * @return Does this Data Stick need recipe data updated. + */ + public static boolean doesDataStickNeedUpdate(ItemStack aDataStick) { + if (isItemDataStick(aDataStick) && doesDataStickHaveRecipeHash(aDataStick)) { + String aStickHash = getHashFromDataStack(aDataStick); + if (isValidHash(aStickHash) && doesDataStickHaveOutput(aDataStick)) { + ItemStack aStickOutput = getDataStickOutput(aDataStick); + GT_Recipe_AssemblyLine aIntendedRecipe = findAssemblyLineRecipeByOutput(aStickOutput); + if (aStickHash.equals(generateRecipeHash(aIntendedRecipe))) { + return false; + } + } + } + return true; + } + + /** + * @param aDataStick - The Data Stick to check. + * @return Does this have a Recipe Hash String at all? + */ + public static boolean doesDataStickHaveRecipeHash(ItemStack aDataStick) { + if (isItemDataStick(aDataStick) && aDataStick.hasTagCompound()) { + NBTTagCompound aNBT = aDataStick.getTagCompound(); + if (aNBT.hasKey("Data.Recipe.Hash")) { + return true; + } + } + return false; + } + + /** + * Get the Output ItemStack from a Data Stick. + * @param aDataStick - The Data Stick to check. + * @return Output ItemStack contained on the Data Stick. + */ + public static ItemStack getDataStickOutput(ItemStack aDataStick) { + if (doesDataStickHaveOutput(aDataStick)) { + ItemStack aOutput = GT_Utility.loadItem(aDataStick.getTagCompound(), "output"); + return aOutput; + } + return null; + } + + /** + * @param aDataStick - The Data Stick to procces. + * @return The stored Recipe Hash String on the Data Stick, will return an invalid Hash if one is not found. <p> + * Check with isValidHash(). <p> + * Will not return Null. + */ + public static String getHashFromDataStack(ItemStack aDataStick) { + if (isItemDataStick(aDataStick) && aDataStick.hasTagCompound()) { + NBTTagCompound aNBT = aDataStick.getTagCompound(); + if (aNBT.hasKey("Data.Recipe.Hash")) { + return aNBT.getString("Data.Recipe.Hash"); + + } + } + return "Invalid.Recipe.Hash"; + } + + /** + * + * @param aDataStick - The Data Stick to update. + * @param aRecipeHash - The Recipe Hash String to update with. + * @return Did we update the Recipe Hash String on the Data Stick? + */ + public static boolean setRecipeHashOnDataStick(ItemStack aDataStick, String aRecipeHash) { + if (isItemDataStick(aDataStick) && aDataStick.hasTagCompound()) { + NBTTagCompound aNBT = aDataStick.getTagCompound(); + aNBT.setString("Data.Recipe.Hash", aRecipeHash); + aDataStick.setTagCompound(aNBT); + return true; + } + return false; + } + + /** + * + * @param aDataStick - The Data Stick to update. + * @param aNewRecipe - The New GT_Recipe_AssemblyLine recipe to update it with. + * @return Did we set the new recipe data & Recipe Hash String on the Data Stick? + */ + public static boolean setAssemblyLineRecipeOnDataStick(ItemStack aDataStick, GT_Recipe_AssemblyLine aNewRecipe) { + if (isItemDataStick(aDataStick)) { + String s = aNewRecipe.mOutput.getDisplayName(); + if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { + s = GT_Assemblyline_Server.lServerNames.get(aNewRecipe.mOutput.getDisplayName()); + if (s == null) { + s = aNewRecipe.mOutput.getDisplayName(); + } + } + + String aHash = generateRecipeHash(aNewRecipe); + if (GT_Values.D1) { + GT_Recipe_AssemblyLine aOldRecipe = findAssemblyLineRecipeFromDataStick(aDataStick, true); + GT_FML_LOGGER.info("Updating data stick: "+aDataStick.getDisplayName()+" | Old Recipe Hash: "+generateRecipeHash(aOldRecipe)+", New Recipe Hash: "+aHash); + } + + + //remove possible old NBTTagCompound + aDataStick.setTagCompound(new NBTTagCompound()); + if (GT_Values.D1) { + GT_Utility.ItemNBT.setBookTitle(aDataStick, s + " Construction Data ("+aHash+")"); + } + else { + GT_Utility.ItemNBT.setBookTitle(aDataStick, s + " Construction Data"); + } + + NBTTagCompound tNBT = aDataStick.getTagCompound(); + if (tNBT == null) { + tNBT = new NBTTagCompound(); + } + + tNBT.setTag("output", aNewRecipe.mOutput.writeToNBT(new NBTTagCompound())); + tNBT.setInteger("time", aNewRecipe.mDuration); + tNBT.setInteger("eu", aNewRecipe.mEUt); + for (int i = 0; i < aNewRecipe.mInputs.length; i++) { + tNBT.setTag("" + i, aNewRecipe.mInputs[i].writeToNBT(new NBTTagCompound())); + } + for (int i = 0; i < aNewRecipe.mOreDictAlt.length; i++) { + if (aNewRecipe.mOreDictAlt[i] != null && aNewRecipe.mOreDictAlt[i].length > 0) { + tNBT.setInteger("a" + i, aNewRecipe.mOreDictAlt[i].length); + for (int j = 0; j < aNewRecipe.mOreDictAlt[i].length; j++) { + tNBT.setTag("a" + i + ":" + j, aNewRecipe.mOreDictAlt[i][j].writeToNBT(new NBTTagCompound())); + } + } + } + for (int i = 0; i < aNewRecipe.mFluidInputs.length; i++) { + tNBT.setTag("f" + i, aNewRecipe.mFluidInputs[i].writeToNBT(new NBTTagCompound())); + } + tNBT.setString("author", "Assembling Line Recipe Generator"); + NBTTagList tNBTList = new NBTTagList(); + s = aNewRecipe.mOutput.getDisplayName(); + if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { + s = GT_Assemblyline_Server.lServerNames.get(aNewRecipe.mOutput.getDisplayName()); + if (s == null) + s = aNewRecipe.mOutput.getDisplayName(); + } + tNBTList.appendTag(new NBTTagString("Construction plan for " + aNewRecipe.mOutput.stackSize + " " + s + ". Needed EU/t: " + aNewRecipe.mEUt + " Production time: " + (aNewRecipe.mDuration / 20))); + for (int i = 0; i < aNewRecipe.mInputs.length; i++) { + if (aNewRecipe.mOreDictAlt[i] != null) { + int count = 0; + StringBuilder tBuilder = new StringBuilder("Input Bus " + (i + 1) + ": "); + for (ItemStack tStack : aNewRecipe.mOreDictAlt[i]) { + if (tStack != null) { + s = tStack.getDisplayName(); + if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { + s = GT_Assemblyline_Server.lServerNames.get(tStack.getDisplayName()); + if (s == null) + s = tStack.getDisplayName(); + } + + + tBuilder.append(count == 0 ? "" : "\nOr ").append(tStack.stackSize).append(" ").append(s); + count++; + } + } + if (count > 0) tNBTList.appendTag(new NBTTagString(tBuilder.toString())); + } else if (aNewRecipe.mInputs[i] != null) { + s = aNewRecipe.mInputs[i].getDisplayName(); + if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { + s = GT_Assemblyline_Server.lServerNames.get(aNewRecipe.mInputs[i].getDisplayName()); + if (s == null) + s = aNewRecipe.mInputs[i].getDisplayName(); + } + tNBTList.appendTag(new NBTTagString("Input Bus " + (i + 1) + ": " + aNewRecipe.mInputs[i].stackSize + " " + s)); + } + } + for (int i = 0; i < aNewRecipe.mFluidInputs.length; i++) { + if (aNewRecipe.mFluidInputs[i] != null) { + s = aNewRecipe.mFluidInputs[i].getLocalizedName(); + if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { + s = GT_Assemblyline_Server.lServerNames.get(aNewRecipe.mFluidInputs[i].getLocalizedName()); + if (s == null) + s = aNewRecipe.mFluidInputs[i].getLocalizedName(); + } + tNBTList.appendTag(new NBTTagString("Input Hatch " + (i + 1) + ": " + aNewRecipe.mFluidInputs[i].amount + "L " + s)); + } + } + tNBT.setTag("pages", tNBTList); + aDataStick.setTagCompound(tNBT); + // Set recipe hash + setRecipeHashOnDataStick(aDataStick, aHash); + return true; + } + return false; + } + +} diff --git a/src/main/java/gregtech/api/util/GT_Recipe.java b/src/main/java/gregtech/api/util/GT_Recipe.java index 1f13ff7b82..2c5b2df5bf 100644 --- a/src/main/java/gregtech/api/util/GT_Recipe.java +++ b/src/main/java/gregtech/api/util/GT_Recipe.java @@ -564,6 +564,84 @@ public class GT_Recipe implements Comparable<GT_Recipe> { mEUt = aEUt; mOreDictAlt = aAlt; } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + GT_ItemStack[] thisInputs = new GT_ItemStack[this.mInputs.length]; + int totalInputStackSize = 0; + for (int i=0;i<this.mInputs.length;i++) { + thisInputs[i] = new GT_ItemStack(this.mInputs[i]); + totalInputStackSize += thisInputs[i].mStackSize; + } + int inputHash = Arrays.deepHashCode(thisInputs); + int inputFluidHash = Arrays.deepHashCode(this.mFluidInputs); + GT_ItemStack thisOutput = new GT_ItemStack(mOutput); + GT_ItemStack thisResearch = new GT_ItemStack(mResearchItem); + int miscRecipeDataHash = Arrays.deepHashCode(new Object[] { + totalInputStackSize, + mDuration, mEUt, + thisOutput, + thisResearch, + mResearchTime + }); + result = prime * result + inputFluidHash; + result = prime * result + inputHash; + result = prime * result + miscRecipeDataHash; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof GT_Recipe_AssemblyLine)) { + return false; + } + GT_Recipe_AssemblyLine other = (GT_Recipe_AssemblyLine) obj; + if (this.mInputs.length != other.mInputs.length) { + return false; + } + if (this.mFluidInputs.length != other.mFluidInputs.length) { + return false; + } + // Check Outputs Match + GT_ItemStack output1 = new GT_ItemStack(this.mOutput); + GT_ItemStack output2 = new GT_ItemStack(other.mOutput); + if (!output1.equals(output2)) { + return false; + } + // Check Scanned Item Match + GT_ItemStack scan1 = new GT_ItemStack(this.mResearchItem); + GT_ItemStack scan2 = new GT_ItemStack(other.mResearchItem); + if (!scan1.equals(scan2)) { + return false; + } + // Check Items Match + GT_ItemStack[] thisInputs = new GT_ItemStack[this.mInputs.length]; + GT_ItemStack[] otherInputs = new GT_ItemStack[other.mInputs.length]; + for (int i=0;i<thisInputs.length;i++) { + thisInputs[i] = new GT_ItemStack(this.mInputs[i]); + otherInputs[i] = new GT_ItemStack(other.mInputs[i]); + } + for (int i=0;i<thisInputs.length;i++) { + if (!thisInputs[i].equals(otherInputs[i]) || thisInputs[i].mStackSize != otherInputs[i].mStackSize) { + return false; + } + } + // Check Fluids Match + for (int i=0;i<this.mFluidInputs.length;i++) { + if (!this.mFluidInputs[i].isFluidStackIdentical(other.mFluidInputs[i])) { + return false; + } + } + + return this.mDuration == other.mDuration + && this.mEUt == other.mEUt + && this.mResearchTime == other.mResearchTime; + } } |