aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/gregtech')
-rw-r--r--src/main/java/gregtech/api/util/GT_AssemblyLineUtils.java176
-rw-r--r--src/main/java/gregtech/api/util/GT_Recipe.java15
-rw-r--r--src/main/java/gregtech/api/util/GT_Utility.java52
-rw-r--r--src/main/java/gregtech/common/GT_RecipeAdder.java46
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_AssemblyLine.java133
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){