aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/gregtech/api/util/GT_AssemblyLineUtils.java44
-rw-r--r--src/main/java/gregtech/api/util/GT_Recipe.java47
-rw-r--r--src/main/java/gregtech/common/GT_RecipeAdder.java13
3 files changed, 76 insertions, 28 deletions
diff --git a/src/main/java/gregtech/api/util/GT_AssemblyLineUtils.java b/src/main/java/gregtech/api/util/GT_AssemblyLineUtils.java
index 25f4b35ab3..07353882ec 100644
--- a/src/main/java/gregtech/api/util/GT_AssemblyLineUtils.java
+++ b/src/main/java/gregtech/api/util/GT_AssemblyLineUtils.java
@@ -17,6 +17,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTTagString;
+import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.fluids.FluidStack;
import javax.annotation.Nonnull;
@@ -72,11 +73,11 @@ public class GT_AssemblyLineUtils {
*/
@Nonnull
public static LookupResult findAssemblyLineRecipeFromDataStick(ItemStack aDataStick, boolean aReturnBuiltRecipe) {
- if (!isItemDataStick(aDataStick)) {
+ if (!isItemDataStick(aDataStick) || doesDataStickHaveOutput(aDataStick)) {
return LookupResultType.INVALID_STICK.getResult();
}
List<ItemStack> aInputs = new ArrayList<>(15);
- ItemStack aOutput = null;
+ ItemStack aOutput = getDataStickOutput(aDataStick);
List<List<ItemStack>> mOreDictAlt = new ArrayList<>(15);
List<FluidStack> aFluidInputs = new ArrayList<>(4);
@@ -88,9 +89,9 @@ public class GT_AssemblyLineUtils {
//Get From Cache
if (doesDataStickHaveRecipeHash(aDataStick)) {
GT_Recipe_AssemblyLine aRecipeFromCache = sRecipeCacheByRecipeHash.get(getHashFromDataStack(aDataStick));
- if (aRecipeFromCache != null) {
+ if (aRecipeFromCache != null && GT_Utility.areStacksEqual(aOutput, aRecipeFromCache.mOutput)) {
return LookupResultType.VALID_STACK_AND_VALID_HASH.getResult(aRecipeFromCache);
- }
+ } // else: no cache, or the old recipe run into a hash collision with a different new recipe
}
for (int i = 0; i < 15; i++) {
@@ -133,7 +134,6 @@ public class GT_AssemblyLineUtils {
GT_FML_LOGGER.info("Fluid " + i + " " + tLoaded.getUnlocalizedName());
}
}
- 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();
}
@@ -227,14 +227,29 @@ public class GT_AssemblyLineUtils {
}
/**
+ * @param aRecipe - The recipe to add to internal caches
+ * @throws IllegalArgumentException if given recipe collide with any existing recipe in the cache
+ */
+ public static void addRecipeToCache(GT_Recipe_AssemblyLine aRecipe) {
+ if (aRecipe != null) {
+ String aHash = "Hash." + aRecipe.getPersistentHash();
+ GT_Recipe_AssemblyLine existing = sRecipeCacheByOutput.put(new GT_ItemStack(aRecipe.mOutput), aRecipe);
+ if (existing != null)
+ throw new IllegalArgumentException("Duplicate assline recipe for " + aRecipe.mOutput);
+ existing = sRecipeCacheByRecipeHash.put(aHash, aRecipe);
+ if (existing != null && !existing.equals(aRecipe))
+ throw new IllegalArgumentException("Recipe hash collision for " + aRecipe + " and " + existing);
+ }
+ }
+
+ /**
* @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;
- }
+ // persistent hash can never be 0
+ return !aHash.equals("Invalid.Recipe.Hash") && !aHash.equals("Hash.0");
}
return false;
}
@@ -283,7 +298,7 @@ public class GT_AssemblyLineUtils {
public static boolean doesDataStickHaveRecipeHash(ItemStack aDataStick) {
if (isItemDataStick(aDataStick) && aDataStick.hasTagCompound()) {
NBTTagCompound aNBT = aDataStick.getTagCompound();
- if (aNBT.hasKey("Data.Recipe.Hash")) {
+ if (aNBT.hasKey("Data.Recipe.Hash") && aNBT.getString("Data.Recipe.Hash").equals("Hash.0")) {
return true;
}
}
@@ -304,17 +319,18 @@ public class GT_AssemblyLineUtils {
}
/**
- * @param aDataStick - The Data Stick to procces.
+ * @param aDataStick - The Data Stick to process.
* @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>
+ * The hash will be guaranteed to pass 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");
-
+ if (aNBT.hasKey("Data.Recipe.Hash", NBT.TAG_STRING)) {
+ String hash = aNBT.getString("Data.Recipe.Hash");
+ if (isValidHash(hash))
+ return hash;
}
}
return "Invalid.Recipe.Hash";
diff --git a/src/main/java/gregtech/api/util/GT_Recipe.java b/src/main/java/gregtech/api/util/GT_Recipe.java
index 1b54e10795..84d4eb25c7 100644
--- a/src/main/java/gregtech/api/util/GT_Recipe.java
+++ b/src/main/java/gregtech/api/util/GT_Recipe.java
@@ -556,7 +556,7 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
public static class GT_Recipe_AssemblyLine{
public static final ArrayList<GT_Recipe_AssemblyLine> sAssemblylineRecipes = new ArrayList<GT_Recipe_AssemblyLine>();
-
+
public ItemStack mResearchItem;
public int mResearchTime;
public ItemStack[] mInputs;
@@ -567,10 +567,31 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
public ItemStack[][] mOreDictAlt;
private int mPersistentHash;
+ /**
+ * THIS CONSTRUCTOR DOES SET THE PERSISTENT HASH.
+ *
+ * if you set one yourself, it will give you one of the RunetimeExceptions!
+ */
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][]);
+ 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;
+ setPersistentHash(tPersistentHash);
}
-
+
+ /**
+ * THIS CONSTRUCTOR DOES <b>NOT</b> SET THE PERSISTENT HASH.
+ *
+ * if you don't set one yourself, it will break a lot of stuff!
+ */
public GT_Recipe_AssemblyLine(ItemStack aResearchItem, int aResearchTime, ItemStack[] aInputs, FluidStack[] aFluidInputs, ItemStack aOutput, int aDuration, int aEUt, ItemStack[][] aAlt) {
mResearchItem = aResearchItem;
mResearchTime = aResearchTime;
@@ -661,9 +682,30 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
}
public int getPersistentHash() {
+ if (mPersistentHash == 0)
+ GT_Log.err.println("Assline recipe persistent hash has not been set! Recipe: " + mOutput);
return mPersistentHash;
}
+ @Override
+ public String toString() {
+ return "GT_Recipe_AssemblyLine{" +
+ "mResearchItem=" + mResearchItem +
+ ", mResearchTime=" + mResearchTime +
+ ", mInputs=" + Arrays.toString(mInputs) +
+ ", mFluidInputs=" + Arrays.toString(mFluidInputs) +
+ ", mOutput=" + mOutput +
+ ", mDuration=" + mDuration +
+ ", mEUt=" + mEUt +
+ ", mOreDictAlt=" + Arrays.toString(mOreDictAlt) +
+ '}';
+ }
+
+ /**
+ * @param aPersistentHash the persistent hash. it should reflect the exact input used to generate this recipe
+ * If 0 is passed in, the actual persistent hash will be automatically remapped to 1 instead.
+ * @throws IllegalStateException if the persistent hash has been set already
+ */
public void setPersistentHash(int aPersistentHash) {
if (this.mPersistentHash != 0)
throw new IllegalStateException("Cannot set persistent hash twice!");
@@ -671,6 +713,7 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
this.mPersistentHash = 1;
else
this.mPersistentHash = aPersistentHash;
+ GT_AssemblyLineUtils.addRecipeToCache(this);
}
}
diff --git a/src/main/java/gregtech/common/GT_RecipeAdder.java b/src/main/java/gregtech/common/GT_RecipeAdder.java
index f130c65adf..72a187f23a 100644
--- a/src/main/java/gregtech/common/GT_RecipeAdder.java
+++ b/src/main/java/gregtech/common/GT_RecipeAdder.java
@@ -1422,17 +1422,6 @@ 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_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;
}
@@ -1508,7 +1497,7 @@ 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,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_AssemblyLine tRecipe = new GT_Recipe_AssemblyLine(aResearchItem, aResearchTime, tInputs, aFluidInputs, aOutput, aDuration, aEUt, tAlts);
- tRecipe.setPersistentHash(tPersistentHash == 0 ? 1 : tPersistentHash);
+ tRecipe.setPersistentHash(tPersistentHash);
GT_Recipe.GT_Recipe_AssemblyLine.sAssemblylineRecipes.add(tRecipe);
return true;
}