aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.gradle2
-rw-r--r--src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java24
-rw-r--r--src/main/java/gregtech/api/util/GT_AssemblyLineUtils.java440
-rw-r--r--src/main/java/gregtech/api/util/GT_LanguageManager.java2
-rw-r--r--src/main/java/gregtech/api/util/GT_Recipe.java82
-rw-r--r--src/main/java/gregtech/api/util/GT_Single_Recipe_Check.java284
-rw-r--r--src/main/java/gregtech/api/util/GT_Single_Recipe_Check_Processing_Array.java212
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Machines.java36
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Item_Machines.java29
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Scanner.java97
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_AssemblyLine.java206
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeChemicalReactor.java131
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ProcessingArray.java89
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PyrolyseOven.java45
-rw-r--r--src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_DigitalChestBase.java3
-rw-r--r--src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_QuantumChest.java50
-rw-r--r--src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_QuantumTank.java14
-rw-r--r--src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_SuperChest.java28
-rw-r--r--src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_SuperTank.java14
-rw-r--r--src/main/java/gregtech/loaders/postload/GT_CraftingRecipeLoader.java12
20 files changed, 1506 insertions, 294 deletions
diff --git a/build.gradle b/build.gradle
index f92e2a9a82..5f4aad8103 100644
--- a/build.gradle
+++ b/build.gradle
@@ -109,6 +109,8 @@ dependencies {
//Soft Depths (Without this, it wont compile, not needed as library)
compileOnly 'commons-io:commons-io:2.4'
+ compileOnly 'com.google.auto.value:auto-value-annotations:1.8.2'
+ annotationProcessor 'com.google.auto.value:auto-value:1.8.2'
compileOnly "eu.usrv:YAMCore:${config.minecraft.version}-${config.yamcore.version}:deobf"
compileOnly "tconstruct:TConstruct:${config.minecraft.version}-${config.tconstruct.version}:deobf"
compileOnly "codechicken:Translocator:${config.minecraft.version}-${config.translocators.version}:dev"
diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java
index 7a2f1bedac..6369c48f8e 100644
--- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java
+++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java
@@ -13,6 +13,7 @@ import gregtech.api.objects.GT_ItemStack;
import gregtech.api.util.GT_Log;
import gregtech.api.util.GT_ModHandler;
import gregtech.api.util.GT_Recipe.GT_Recipe_Map;
+import gregtech.api.util.GT_Single_Recipe_Check;
import gregtech.api.util.GT_Utility;
import gregtech.common.GT_Pollution;
import gregtech.common.items.GT_MetaGenerated_Tool_01;
@@ -43,6 +44,9 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity {
public int damageFactorLow = 5;
public float damageFactorHigh = 0.6f;
+ public boolean mLockedToSingleRecipe = false;
+ public GT_Single_Recipe_Check mSingleRecipeCheck = null;
+
public ArrayList<GT_MetaTileEntity_Hatch_Input> mInputHatches = new ArrayList<>();
public ArrayList<GT_MetaTileEntity_Hatch_Output> mOutputHatches = new ArrayList<>();
public ArrayList<GT_MetaTileEntity_Hatch_InputBus> mInputBusses = new ArrayList<>();
@@ -81,6 +85,24 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity {
return aSide != getBaseMetaTileEntity().getFrontFacing();
}
+ /** Override this if you are a multi-block that has added support for single recipe locking. */
+ public boolean supportsSingleRecipeLocking() {
+ return false;
+ }
+
+ @Override
+ public void onScrewdriverRightClick(byte aSide, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (supportsSingleRecipeLocking()) {
+ mLockedToSingleRecipe = !mLockedToSingleRecipe;
+ if (mLockedToSingleRecipe) {
+ GT_Utility.sendChatToPlayer(aPlayer, trans("219","Single recipe locking enabled. Will lock to next recipe."));
+ } else {
+ GT_Utility.sendChatToPlayer(aPlayer, trans("220","Single recipe locking disabled."));
+ mSingleRecipeCheck = null;
+ }
+ }
+ }
+
@Override
public boolean isSimpleMachine() {
return false;
@@ -125,6 +147,7 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity {
aNBT.setInteger("mEfficiency", mEfficiency);
aNBT.setInteger("mPollution", mPollution);
aNBT.setInteger("mRuntime", mRuntime);
+ aNBT.setBoolean("mLockedToSingleRecipe", mLockedToSingleRecipe);
if (mOutputItems != null) {
aNBT.setInteger("mOutputItemsLength", mOutputItems.length);
@@ -162,6 +185,7 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity {
mEfficiency = aNBT.getInteger("mEfficiency");
mPollution = aNBT.getInteger("mPollution");
mRuntime = aNBT.getInteger("mRuntime");
+ mLockedToSingleRecipe = aNBT.getBoolean("mLockedToSingleRecipe");
int aOutputItemsLength = aNBT.getInteger("mOutputItemsLength");
if (aOutputItemsLength > 0) {
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_LanguageManager.java b/src/main/java/gregtech/api/util/GT_LanguageManager.java
index 9faa7b11a6..767c830f79 100644
--- a/src/main/java/gregtech/api/util/GT_LanguageManager.java
+++ b/src/main/java/gregtech/api/util/GT_LanguageManager.java
@@ -335,6 +335,8 @@ public class GT_LanguageManager {
addStringLocalization("Interaction_DESCRIPTION_Index_216", "Deprecated Recipe");
addStringLocalization("Interaction_DESCRIPTION_Index_217", "Stocking mode. Keeps this many items in destination input slots. This mode can be server unfriendly.");
addStringLocalization("Interaction_DESCRIPTION_Index_218", "Transfer size mode. Add exactly this many items in destination input slots as long as there is room.");
+ addStringLocalization("Interaction_DESCRIPTION_Index_219", "Single recipe locking enabled. Will lock to next recipe.");
+ addStringLocalization("Interaction_DESCRIPTION_Index_220", "Single recipe locking disabled.");
addStringLocalization("Interaction_DESCRIPTION_Index_500", "Fitting: Loose - More Flow");
addStringLocalization("Interaction_DESCRIPTION_Index_501", "Fitting: Tight - More Efficiency");
diff --git a/src/main/java/gregtech/api/util/GT_Recipe.java b/src/main/java/gregtech/api/util/GT_Recipe.java
index 1f13ff7b82..7b74f95a6b 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;
+ }
}
@@ -1045,6 +1123,10 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
tFluid.amount = 0;
mRecipesByFluidInput.put(tFluid.getUnlocalizedName(), aRecipe);
}
+ } else if ((aRecipe.mInputs == null || GT_Utility.getNonnullElementCount(aRecipe.mInputs) == 0) &&
+ aRecipe.mFluidInputs != null && GT_Utility.getNonnullElementCount(aRecipe.mFluidInputs) == 1 &&
+ aRecipe.mFluidInputs[0] != null) {
+ mRecipesByFluidInput.put(aRecipe.mFluidInputs[0].getUnlocalizedName(), aRecipe);
}
return aRecipe;
}
diff --git a/src/main/java/gregtech/api/util/GT_Single_Recipe_Check.java b/src/main/java/gregtech/api/util/GT_Single_Recipe_Check.java
new file mode 100644
index 0000000000..469f2d64a1
--- /dev/null
+++ b/src/main/java/gregtech/api/util/GT_Single_Recipe_Check.java
@@ -0,0 +1,284 @@
+package gregtech.api.util;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+
+import javax.annotation.Nullable;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/** Used by machines that are locked to a single recipe, for fast computation. */
+public class GT_Single_Recipe_Check {
+ protected final GT_MetaTileEntity_MultiBlockBase multiBlockBase;
+ protected final GT_Recipe recipe;
+ protected final ImmutableMap<ItemId, Integer> itemCost;
+ protected final ImmutableMap<Fluid, Integer> fluidCost;
+
+ protected final int totalItemCost;
+ protected final int totalFluidCost;
+
+ protected GT_Single_Recipe_Check(
+ GT_MetaTileEntity_MultiBlockBase multiBlockBase,
+ GT_Recipe recipe,
+ ImmutableMap<ItemId, Integer> itemCost,
+ ImmutableMap<Fluid, Integer> fluidCost) {
+ this.multiBlockBase = multiBlockBase;
+ this.recipe = recipe;
+ this.itemCost = itemCost;
+ this.fluidCost = fluidCost;
+
+ this.totalItemCost = itemCost.values().stream().mapToInt(Integer::intValue).sum();
+ this.totalFluidCost = fluidCost.values().stream().mapToInt(Integer::intValue).sum();
+ }
+
+ public GT_Recipe getRecipe() {
+ return recipe;
+ }
+
+ /**
+ * Use this method if recipes cannot require more than a single stack of any item or fluid.
+ * In particular, {@link GT_MetaTileEntity_MultiBlockBase#getCompactedInputs()} and
+ * {@link GT_MetaTileEntity_MultiBlockBase#getCompactedFluids()} both enforce this single-stack
+ * restriction, so any multi-block that calls those can use this method.
+ */
+ public boolean checkRecipeInputsSingleStack(boolean consumeInputs) {
+ Map<ItemId, ItemStack> itemMap = null;
+ if (totalItemCost > 0) {
+ itemMap = new HashMap<>();
+ for (ItemStack itemStack : multiBlockBase.getStoredInputs()) {
+ itemMap.merge(
+ ItemId.createNoCopy(itemStack), itemStack,
+ (a, b) -> a.stackSize >= b.stackSize ? a : b);
+ }
+
+ for (Map.Entry<ItemId, Integer> entry : itemCost.entrySet()) {
+ ItemStack itemStack = itemMap.get(entry.getKey());
+ if (itemStack == null || itemStack.stackSize < entry.getValue()) {
+ return false;
+ }
+ }
+ }
+
+ Map<Fluid, FluidStack> fluidMap = null;
+ if (totalFluidCost > 0) {
+ fluidMap = new HashMap<>();
+ for (FluidStack fluidStack : multiBlockBase.getStoredFluids()) {
+ fluidMap.merge(
+ fluidStack.getFluid(), fluidStack,
+ (a, b) -> a.amount >= b.amount ? a : b);
+ }
+
+ for (Map.Entry<Fluid, Integer> entry : fluidCost.entrySet()) {
+ FluidStack fluidStack = fluidMap.get(entry.getKey());
+ if (fluidStack == null || fluidStack.amount < entry.getValue()) {
+ return false;
+ }
+ }
+ }
+
+ if (consumeInputs) {
+ if (totalItemCost > 0) {
+ for (Map.Entry<ItemId, Integer> entry : itemCost.entrySet()) {
+ itemMap.get(entry.getKey()).stackSize -= entry.getValue();
+ }
+ }
+
+ if (totalFluidCost > 0) {
+ for (Map.Entry<Fluid, Integer> entry : fluidCost.entrySet()) {
+ fluidMap.get(entry.getKey()).amount -= entry.getValue();
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Use this method if recipes can require more than a single stack of any item or fluid.
+ * It is less efficient, though.
+ */
+ public boolean checkRecipeInputs(boolean consumeInputs) {
+ List<ItemStack> items = null;
+ if (totalItemCost > 0) {
+ items = multiBlockBase.getStoredInputs();
+
+ Map<ItemId, Integer> itemMap = new HashMap<>();
+ for (ItemStack itemStack : items) {
+ itemMap.merge(ItemId.createNoCopy(itemStack), itemStack.stackSize, Integer::sum);
+ }
+
+ for (Map.Entry<ItemId, Integer> entry : itemCost.entrySet()) {
+ if (itemMap.getOrDefault(entry.getKey(), 0) < entry.getValue()) {
+ return false;
+ }
+ }
+ }
+
+ List<FluidStack> fluids = null;
+ if (totalFluidCost > 0) {
+ fluids = multiBlockBase.getStoredFluids();
+
+ Map<Fluid, Integer> fluidMap = new HashMap<>();
+ for (FluidStack fluidStack : fluids) {
+ fluidMap.merge(fluidStack.getFluid(), fluidStack.amount, Integer::sum);
+ }
+
+ for (Map.Entry<Fluid, Integer> entry : fluidCost.entrySet()) {
+ if (fluidMap.getOrDefault(entry.getKey(), 0) < entry.getValue()) {
+ return false;
+ }
+ }
+ }
+
+ if (consumeInputs) {
+ if (totalItemCost > 0) {
+ int remainingItemCost = totalItemCost;
+ Map<ItemId, Integer> runningItemCost = Maps.newHashMap(itemCost);
+ for (ItemStack itemStack : items) {
+ ItemId key = ItemId.createNoCopy(itemStack);
+ int runningCost = runningItemCost.getOrDefault(key, 0);
+ int paid = Math.min(itemStack.stackSize, runningCost);
+ itemStack.stackSize -= paid;
+ runningItemCost.put(key, runningCost - paid);
+
+ remainingItemCost -= paid;
+ if (remainingItemCost <= 0) {
+ break;
+ }
+ }
+ }
+
+ if (totalFluidCost > 0) {
+ int remainingFluidCost = totalFluidCost;
+ Map<Fluid, Integer> runningFluidCost = Maps.newHashMap(fluidCost);
+ for (FluidStack fluidStack : fluids) {
+ Fluid key = fluidStack.getFluid();
+ int runningCost = runningFluidCost.getOrDefault(key, 0);
+ int paid = Math.min(fluidStack.amount, runningCost);
+ fluidStack.amount -= paid;
+ runningFluidCost.put(key, runningCost - paid);
+
+ remainingFluidCost -= paid;
+ if (remainingFluidCost <= 0) {
+ break;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ protected static Map<ItemId, Integer> buildItemMap(
+ GT_MetaTileEntity_MultiBlockBase multiBlockBase) {
+ Map<ItemId, Integer> itemMap = new HashMap<>();
+ for (ItemStack itemStack : multiBlockBase.getStoredInputs()) {
+ itemMap.merge(ItemId.create(itemStack), itemStack.stackSize, Integer::sum);
+ }
+ return itemMap;
+ }
+
+ protected static Map<Fluid, Integer> buildFluidMap(
+ GT_MetaTileEntity_MultiBlockBase multiBlockBase) {
+ Map<Fluid, Integer> fluidMap = new HashMap<>();
+ for (FluidStack fluidStack : multiBlockBase.getStoredFluids()) {
+ fluidMap.merge(fluidStack.getFluid(), fluidStack.amount, Integer::sum);
+ }
+ return fluidMap;
+ }
+
+ public static Builder builder(GT_MetaTileEntity_MultiBlockBase multiBlockBase) {
+ return new Builder(multiBlockBase);
+ }
+
+ public static final class Builder {
+ private final GT_MetaTileEntity_MultiBlockBase multiBlockBase;
+
+ // In order to compute which items and fluids are consumed by the recipe, we compare the
+ // multi-block's items and fluids before and after inputs are consumed by the recipe.
+ private Map<ItemId, Integer> beforeItems;
+ private Map<Fluid, Integer> beforeFluids;
+ private Map<ItemId, Integer> afterItems;
+ private Map<Fluid, Integer> afterFluids;
+
+ private GT_Recipe recipe;
+
+ private Builder(GT_MetaTileEntity_MultiBlockBase multiBlockBase) {
+ this.multiBlockBase = multiBlockBase;
+ }
+
+ /** Call this before inputs are consumed by the recipe. */
+ public Builder setBefore() {
+ beforeItems = buildItemMap(multiBlockBase);
+ beforeFluids = buildFluidMap(multiBlockBase);
+ return this;
+ }
+
+ /** Call this after inputs are consumed by the recipe. */
+ public Builder setAfter() {
+ afterItems = buildItemMap(multiBlockBase);
+ afterFluids = buildFluidMap(multiBlockBase);
+ return this;
+ }
+
+ public Builder setRecipe(GT_Recipe recipe) {
+ this.recipe = recipe;
+ return this;
+ }
+
+ public GT_Single_Recipe_Check build() {
+ ImmutableMap.Builder<ItemId, Integer> itemCostBuilder = ImmutableMap.builder();
+ for (Map.Entry<ItemId, Integer> entry : beforeItems.entrySet()) {
+ int cost = entry.getValue() - afterItems.getOrDefault(entry.getKey(), 0);
+ if (cost > 0) {
+ itemCostBuilder.put(entry.getKey(), cost);
+ }
+ }
+
+ ImmutableMap.Builder<Fluid, Integer> fluidCostBuilder = ImmutableMap.builder();
+ for (Map.Entry<Fluid, Integer> entry : beforeFluids.entrySet()) {
+ int cost = entry.getValue() - afterFluids.getOrDefault(entry.getKey(), 0);
+ if (cost > 0) {
+ fluidCostBuilder.put(entry.getKey(), cost);
+ }
+ }
+
+ return new GT_Single_Recipe_Check(
+ multiBlockBase, recipe, itemCostBuilder.build(), fluidCostBuilder.build());
+ }
+ }
+
+ @AutoValue
+ protected abstract static class ItemId {
+ /** This method copies NBT, as it is mutable. */
+ protected static ItemId create(ItemStack itemStack) {
+ NBTTagCompound nbt = itemStack.getTagCompound();
+ if (nbt != null) {
+ nbt = (NBTTagCompound) nbt.copy();
+ }
+
+ return new AutoValue_GT_Single_Recipe_Check_ItemId(
+ itemStack.getItem(), itemStack.getItemDamage(), nbt);
+ }
+
+ /** This method does not copy NBT in order to save time. Make sure not to mutate it! */
+ protected static ItemId createNoCopy(ItemStack itemStack) {
+ return new AutoValue_GT_Single_Recipe_Check_ItemId(
+ itemStack.getItem(), itemStack.getItemDamage(), itemStack.getTagCompound());
+ }
+
+ protected abstract Item item();
+ protected abstract int metaData();
+
+ @Nullable
+ protected abstract NBTTagCompound nbt();
+ }
+}
diff --git a/src/main/java/gregtech/api/util/GT_Single_Recipe_Check_Processing_Array.java b/src/main/java/gregtech/api/util/GT_Single_Recipe_Check_Processing_Array.java
new file mode 100644
index 0000000000..225e0bd723
--- /dev/null
+++ b/src/main/java/gregtech/api/util/GT_Single_Recipe_Check_Processing_Array.java
@@ -0,0 +1,212 @@
+package gregtech.api.util;
+
+import com.google.common.collect.ImmutableMap;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/** Processing Array-specialized version of {@link gregtech.api.util.GT_Single_Recipe_Check}. */
+public class GT_Single_Recipe_Check_Processing_Array extends GT_Single_Recipe_Check {
+ protected final int recipeAmperage;
+
+ /**
+ * The machine type that the locked recipe is for.
+ * We will not allow running with other machines.
+ */
+ protected final ItemStack machineStack;
+
+ protected GT_Single_Recipe_Check_Processing_Array(
+ GT_MetaTileEntity_MultiBlockBase multiBlockBase,
+ GT_Recipe recipe,
+ ImmutableMap<ItemId, Integer> itemCost,
+ ImmutableMap<Fluid, Integer> fluidCost,
+ int recipeAmperage,
+ ItemStack machineStack) {
+ super(multiBlockBase, recipe, itemCost, fluidCost);
+
+ this.recipeAmperage = recipeAmperage;
+ this.machineStack = machineStack;
+ }
+
+ public int getRecipeAmperage() {
+ return recipeAmperage;
+ }
+
+ @Override
+ public boolean checkRecipeInputsSingleStack(boolean consumeInputs) {
+ throw new UnsupportedOperationException("Use checkRecipeInputs(boolean, int) instead.");
+ }
+
+ @Override
+ public boolean checkRecipeInputs(boolean consumeInputs) {
+ throw new UnsupportedOperationException("Use checkRecipeInputs(boolean, int) instead.");
+ }
+
+ /** Returns the number of parallel recipes, or 0 if recipe is not satisfied at all. */
+ public int checkRecipeInputs(boolean consumeInputs, int maxParallel) {
+ if (!GT_Utility.areStacksEqual(machineStack, multiBlockBase.mInventory[1])) {
+ // Machine stack was modified. This is not allowed, so stop processing.
+ return 0;
+ }
+ int parallel = maxParallel;
+
+ List<ItemStack> items = null;
+ if (totalItemCost > 0) {
+ items = multiBlockBase.getStoredInputs();
+
+ Map<ItemId, Integer> itemMap = new HashMap<>();
+ for (ItemStack itemStack : items) {
+ itemMap.merge(ItemId.createNoCopy(itemStack), itemStack.stackSize, Integer::sum);
+ }
+
+ for (Map.Entry<ItemId, Integer> entry : itemCost.entrySet()) {
+ parallel = Math.min(parallel, itemMap.getOrDefault(entry.getKey(), 0) / entry.getValue());
+ if (parallel <= 0) {
+ return 0;
+ }
+ }
+ }
+
+ List<FluidStack> fluids = null;
+ if (totalFluidCost > 0) {
+ fluids = multiBlockBase.getStoredFluids();
+
+ Map<Fluid, Integer> fluidMap = new HashMap<>();
+ for (FluidStack fluidStack : fluids) {
+ fluidMap.merge(fluidStack.getFluid(), fluidStack.amount, Integer::sum);
+ }
+
+ for (Map.Entry<Fluid, Integer> entry : fluidCost.entrySet()) {
+ parallel = Math.min(parallel, fluidMap.getOrDefault(entry.getKey(), 0) / entry.getValue());
+ if (parallel <= 0) {
+ return 0;
+ }
+ }
+ }
+
+ final int finalParallel = parallel;
+ if (consumeInputs) {
+ if (totalItemCost > 0) {
+ int remainingItemCost = totalItemCost * finalParallel;
+ Map<ItemId, Integer> runningItemCost =
+ itemCost.entrySet().stream()
+ .collect(
+ Collectors.toMap(
+ Map.Entry::getKey,
+ entry -> entry.getValue() * finalParallel));
+
+ for (ItemStack itemStack : items) {
+ ItemId key = ItemId.createNoCopy(itemStack);
+ int runningCost = runningItemCost.getOrDefault(key, 0);
+ int paid = Math.min(itemStack.stackSize, runningCost);
+ itemStack.stackSize -= paid;
+ runningItemCost.put(key, runningCost - paid);
+
+ remainingItemCost -= paid;
+ if (remainingItemCost <= 0) {
+ break;
+ }
+ }
+ }
+
+ if (totalFluidCost > 0) {
+ int remainingFluidCost = totalFluidCost * finalParallel;
+ Map<Fluid, Integer> runningFluidCost =
+ fluidCost.entrySet().stream()
+ .collect(
+ Collectors.toMap(
+ Map.Entry::getKey,
+ entry -> entry.getValue() * finalParallel));
+
+ for (FluidStack fluidStack : fluids) {
+ Fluid key = fluidStack.getFluid();
+ int runningCost = runningFluidCost.getOrDefault(key, 0);
+ int paid = Math.min(fluidStack.amount, runningCost);
+ fluidStack.amount -= paid;
+ runningFluidCost.put(key, runningCost - paid);
+
+ remainingFluidCost -= paid;
+ if (remainingFluidCost <= 0) {
+ break;
+ }
+ }
+ }
+ }
+
+ return finalParallel;
+ }
+
+ public static Builder processingArrayBuilder(GT_MetaTileEntity_MultiBlockBase multiBlockBase) {
+ return new Builder(multiBlockBase);
+ }
+
+ public static final class Builder {
+ private final GT_MetaTileEntity_MultiBlockBase multiBlockBase;
+
+ // In order to compute which items and fluids are consumed by the recipe, we compare the
+ // multi-block's items and fluids before and after inputs are consumed by the recipe.
+ private Map<ItemId, Integer> beforeItems;
+ private Map<Fluid, Integer> beforeFluids;
+ private Map<ItemId, Integer> afterItems;
+ private Map<Fluid, Integer> afterFluids;
+
+ private GT_Recipe recipe;
+ private int recipeAmperage;
+
+ private Builder(GT_MetaTileEntity_MultiBlockBase multiBlockBase) {
+ this.multiBlockBase = multiBlockBase;
+ }
+
+ /** Call this before inputs are consumed by the recipe. */
+ public Builder setBefore() {
+ beforeItems = buildItemMap(multiBlockBase);
+ beforeFluids = buildFluidMap(multiBlockBase);
+ return this;
+ }
+
+ /** Call this after inputs are consumed by the recipe. */
+ public Builder setAfter() {
+ afterItems = buildItemMap(multiBlockBase);
+ afterFluids = buildFluidMap(multiBlockBase);
+ return this;
+ }
+
+ public Builder setRecipe(GT_Recipe recipe) {
+ this.recipe = recipe;
+ return this;
+ }
+
+ public Builder setRecipeAmperage(int recipeAmperage) {
+ this.recipeAmperage = recipeAmperage;
+ return this;
+ }
+
+ public GT_Single_Recipe_Check_Processing_Array build() {
+ ImmutableMap.Builder<ItemId, Integer> itemCostBuilder = ImmutableMap.builder();
+ for (Map.Entry<ItemId, Integer> entry : beforeItems.entrySet()) {
+ int cost = entry.getValue() - afterItems.getOrDefault(entry.getKey(), 0);
+ if (cost > 0) {
+ itemCostBuilder.put(entry.getKey(), cost);
+ }
+ }
+
+ ImmutableMap.Builder<Fluid, Integer> fluidCostBuilder = ImmutableMap.builder();
+ for (Map.Entry<Fluid, Integer> entry : beforeFluids.entrySet()) {
+ int cost = entry.getValue() - afterFluids.getOrDefault(entry.getKey(), 0);
+ if (cost > 0) {
+ fluidCostBuilder.put(entry.getKey(), cost);
+ }
+ }
+
+ return new GT_Single_Recipe_Check_Processing_Array(
+ multiBlockBase, recipe, itemCostBuilder.build(), fluidCostBuilder.build(),
+ recipeAmperage, multiBlockBase.mInventory[1].copy());
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Machines.java b/src/main/java/gregtech/common/blocks/GT_Block_Machines.java
index 0d673a020e..2c9254bf28 100644
--- a/src/main/java/gregtech/common/blocks/GT_Block_Machines.java
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Machines.java
@@ -16,6 +16,8 @@ import gregtech.api.util.GT_BaseCrop;
import gregtech.api.util.GT_Log;
import gregtech.api.util.GT_Utility;
import gregtech.common.render.GT_Renderer_Block;
+import gregtech.common.tileentities.storage.GT_MetaTileEntity_QuantumChest;
+import gregtech.common.tileentities.storage.GT_MetaTileEntity_SuperChest;
import net.minecraft.block.Block;
import net.minecraft.block.ITileEntityProvider;
import net.minecraft.client.renderer.texture.IIconRegister;
@@ -396,23 +398,25 @@ public class GT_Block_Machines extends GT_Generic_Block implements IDebugableBlo
if (tTileEntity instanceof IGregTechTileEntity) {
IGregTechTileEntity tGregTechTileEntity = (IGregTechTileEntity) tTileEntity;
mTemporaryTileEntity.set(tGregTechTileEntity);
- for (int i = 0; i < tGregTechTileEntity.getSizeInventory(); i++) {
- ItemStack tItem = tGregTechTileEntity.getStackInSlot(i);
- if ((tItem != null) && (tItem.stackSize > 0) && (tGregTechTileEntity.isValidSlot(i))) {
- EntityItem tItemEntity = new EntityItem(aWorld,
- aX + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F,
- aY + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F,
- aZ + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F,
- new ItemStack(tItem.getItem(), tItem.stackSize, tItem.getItemDamage()));
- if (tItem.hasTagCompound()) {
- tItemEntity.getEntityItem().setTagCompound((NBTTagCompound) tItem.getTagCompound().copy());
+ if (!(tGregTechTileEntity.getMetaTileEntity() instanceof GT_MetaTileEntity_SuperChest || tGregTechTileEntity.getMetaTileEntity() instanceof GT_MetaTileEntity_QuantumChest)) {
+ for (int i = 0; i < tGregTechTileEntity.getSizeInventory(); i++) {
+ ItemStack tItem = tGregTechTileEntity.getStackInSlot(i);
+ if ((tItem != null) && (tItem.stackSize > 0) && (tGregTechTileEntity.isValidSlot(i))) {
+ EntityItem tItemEntity = new EntityItem(aWorld,
+ aX + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F,
+ aY + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F,
+ aZ + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F,
+ new ItemStack(tItem.getItem(), tItem.stackSize, tItem.getItemDamage()));
+ if (tItem.hasTagCompound()) {
+ tItemEntity.getEntityItem().setTagCompound((NBTTagCompound) tItem.getTagCompound().copy());
+ }
+ tItemEntity.motionX = (XSTR_INSTANCE.nextGaussian() * 0.05D);
+ tItemEntity.motionY = (XSTR_INSTANCE.nextGaussian() * 0.25D);
+ tItemEntity.motionZ = (XSTR_INSTANCE.nextGaussian() * 0.05D);
+ aWorld.spawnEntityInWorld(tItemEntity);
+ tItem.stackSize = 0;
+ tGregTechTileEntity.setInventorySlotContents(i, null);
}
- tItemEntity.motionX = (XSTR_INSTANCE.nextGaussian() * 0.05D);
- tItemEntity.motionY = (XSTR_INSTANCE.nextGaussian() * 0.25D);
- tItemEntity.motionZ = (XSTR_INSTANCE.nextGaussian() * 0.05D);
- aWorld.spawnEntityInWorld(tItemEntity);
- tItem.stackSize = 0;
- tGregTechTileEntity.setInventorySlotContents(i, null);
}
}
}
diff --git a/src/main/java/gregtech/common/blocks/GT_Item_Machines.java b/src/main/java/gregtech/common/blocks/GT_Item_Machines.java
index 74e3e3653d..55743f445d 100644
--- a/src/main/java/gregtech/common/blocks/GT_Item_Machines.java
+++ b/src/main/java/gregtech/common/blocks/GT_Item_Machines.java
@@ -15,11 +15,19 @@ import gregtech.api.util.GT_ItsNotMyFaultException;
import gregtech.api.util.GT_LanguageManager;
import gregtech.api.util.GT_Log;
import gregtech.api.util.GT_Utility;
+import gregtech.common.tileentities.storage.GT_MetaTileEntity_QuantumChest;
+import gregtech.common.tileentities.storage.GT_MetaTileEntity_QuantumTank;
+import gregtech.common.tileentities.storage.GT_MetaTileEntity_SuperChest;
+import gregtech.common.tileentities.storage.GT_MetaTileEntity_SuperTank;
import net.minecraft.block.Block;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.potion.Potion;
+import net.minecraft.potion.PotionEffect;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.world.World;
@@ -211,4 +219,25 @@ public class GT_Item_Machines extends ItemBlock {
}
return true;
}
+
+ @Override
+ public void onUpdate(ItemStack aStack, World aWorld, Entity aPlayer, int aTimer, boolean aIsInHand) {
+ super.onUpdate(aStack, aWorld, aPlayer, aTimer, aIsInHand);
+ short tDamage = (short) getDamage(aStack);
+ EntityLivingBase tPlayer = (EntityPlayer) aPlayer;
+ if (GregTech_API.METATILEENTITIES[tDamage] instanceof GT_MetaTileEntity_SuperChest ||
+ GregTech_API.METATILEENTITIES[tDamage] instanceof GT_MetaTileEntity_QuantumChest ||
+ GregTech_API.METATILEENTITIES[tDamage] instanceof GT_MetaTileEntity_SuperTank ||
+ GregTech_API.METATILEENTITIES[tDamage] instanceof GT_MetaTileEntity_QuantumTank) {
+ NBTTagCompound tNBT = aStack.stackTagCompound;
+ if (tNBT == null) return;
+ if ((tNBT.hasKey("mItemCount") && tNBT.getInteger("mItemCount") > 0) ||
+ tNBT.hasKey("mFluid")) {
+ tPlayer.addPotionEffect(new PotionEffect(Potion.hunger.id, 12000, 4));
+ tPlayer.addPotionEffect(new PotionEffect(Potion.moveSlowdown.id, 12000, 4));
+ tPlayer.addPotionEffect(new PotionEffect(Potion.digSlowdown.id, 12000, 4));
+ tPlayer.addPotionEffect(new PotionEffect(Potion.weakness.id, 12000, 4));
+ }
+ }
+ }
}
diff --git a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Scanner.java b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Scanner.java
index eba61ad1b1..1573c951eb 100644
--- a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Scanner.java
+++ b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Scanner.java
@@ -15,6 +15,7 @@ import gregtech.api.metatileentity.MetaTileEntity;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine;
import gregtech.api.objects.ItemData;
import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_AssemblyLineUtils;
import gregtech.api.util.GT_Assemblyline_Server;
import gregtech.api.util.GT_Log;
import gregtech.api.util.GT_ModHandler;
@@ -253,6 +254,7 @@ public class GT_MetaTileEntity_Scanner extends GT_MetaTileEntity_BasicMachine {
if (failScanner) {
return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
}
+
String s = tRecipe.mOutput.getDisplayName();
if (FMLCommonHandler.instance().getEffectiveSide().isServer()) {
@@ -261,92 +263,19 @@ public class GT_MetaTileEntity_Scanner extends GT_MetaTileEntity_BasicMachine {
s = tRecipe.mOutput.getDisplayName();
}
this.mOutputItems[0] = GT_Utility.copyAmount(1L, getSpecialSlot());
- //remove possible old NBTTagCompound
- this.mOutputItems[0].setTagCompound(new NBTTagCompound());
- GT_Utility.ItemNBT.setBookTitle(this.mOutputItems[0], s + " Construction Data");
+
- NBTTagCompound tNBT = this.mOutputItems[0].getTagCompound();
- if (tNBT == null) {
- tNBT = new NBTTagCompound();
- }
-
- tNBT.setTag("output", tRecipe.mOutput.writeToNBT(new NBTTagCompound()));
- tNBT.setInteger("time", tRecipe.mDuration);
- tNBT.setInteger("eu", tRecipe.mEUt);
- for (int i = 0; i < tRecipe.mInputs.length; i++) {
- tNBT.setTag("" + i, tRecipe.mInputs[i].writeToNBT(new NBTTagCompound()));
- }
- for (int i = 0; i < tRecipe.mOreDictAlt.length; i++) {
- if (tRecipe.mOreDictAlt[i] != null && tRecipe.mOreDictAlt[i].length > 0) {
- tNBT.setInteger("a" + i, tRecipe.mOreDictAlt[i].length);
- for (int j = 0; j < tRecipe.mOreDictAlt[i].length; j++) {
- tNBT.setTag("a" + i + ":" + j, tRecipe.mOreDictAlt[i][j].writeToNBT(new NBTTagCompound()));
- }
- }
- }
- for (int i = 0; i < tRecipe.mFluidInputs.length; i++) {
- tNBT.setTag("f" + i, tRecipe.mFluidInputs[i].writeToNBT(new NBTTagCompound()));
- }
- tNBT.setString("author", "Assembling Line Recipe Generator");
- NBTTagList tNBTList = new NBTTagList();
- s = tRecipe.mOutput.getDisplayName();
- if (FMLCommonHandler.instance().getEffectiveSide().isServer()) {
- s = GT_Assemblyline_Server.lServerNames.get(tRecipe.mOutput.getDisplayName());
- if (s == null)
- s = tRecipe.mOutput.getDisplayName();
- }
- tNBTList.appendTag(new NBTTagString("Construction plan for " + tRecipe.mOutput.stackSize + " " + s + ". Needed EU/t: " + tRecipe.mEUt + " Production time: " + (tRecipe.mDuration / 20)));
- for (int i = 0; i < tRecipe.mInputs.length; i++) {
- if (tRecipe.mOreDictAlt[i] != null) {
- int count = 0;
- StringBuilder tBuilder = new StringBuilder("Input Bus " + (i + 1) + ": ");
- for (ItemStack tStack : tRecipe.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 (tRecipe.mInputs[i] != null) {
- s = tRecipe.mInputs[i].getDisplayName();
- if (FMLCommonHandler.instance().getEffectiveSide().isServer()) {
- s = GT_Assemblyline_Server.lServerNames.get(tRecipe.mInputs[i].getDisplayName());
- if (s == null)
- s = tRecipe.mInputs[i].getDisplayName();
- }
- tNBTList.appendTag(new NBTTagString("Input Bus " + (i + 1) + ": " + tRecipe.mInputs[i].stackSize + " " + s));
- }
- }
- for (int i = 0; i < tRecipe.mFluidInputs.length; i++) {
- if (tRecipe.mFluidInputs[i] != null) {
- s = tRecipe.mFluidInputs[i].getLocalizedName();
- if (FMLCommonHandler.instance().getEffectiveSide().isServer()) {
- s = GT_Assemblyline_Server.lServerNames.get(tRecipe.mFluidInputs[i].getLocalizedName());
- if (s == null)
- s = tRecipe.mFluidInputs[i].getLocalizedName();
- }
- tNBTList.appendTag(new NBTTagString("Input Hatch " + (i + 1) + ": " + tRecipe.mFluidInputs[i].amount + "L " + s));
- }
+ // Use Assline Utils
+ if (GT_AssemblyLineUtils.setAssemblyLineRecipeOnDataStick(this.mOutputItems[0], tRecipe)) {
+ aStack.stackSize -= 1;
+ calculateOverclockedNess(30, tRecipe.mResearchTime);
+ //In case recipe is too OP for that machine
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ getSpecialSlot().stackSize -= 1;
+ return 2;
}
- tNBT.setTag("pages", tNBTList);
-
- this.mOutputItems[0].setTagCompound(tNBT);
-
- aStack.stackSize -= 1;
- calculateOverclockedNess(30, tRecipe.mResearchTime);
- //In case recipe is too OP for that machine
- if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
- return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
- getSpecialSlot().stackSize -= 1;
- return 2;
+
}
}
}
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 0a19536bf1..c2460213c8 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
@@ -17,8 +17,10 @@ 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.render.TextureFactory;
+import gregtech.api.util.GT_AssemblyLineUtils;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
import gregtech.api.util.GT_Recipe;
+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;
@@ -156,117 +158,111 @@ public class GT_MetaTileEntity_AssemblyLine extends GT_MetaTileEntity_EnhancedMu
@Override
public boolean checkRecipe(ItemStack aStack) {
- if (GT_Values.D1)
- GT_FML_LOGGER.info("Start ALine recipe check");
+ if (GT_Values.D1) {
+ GT_FML_LOGGER.info("Start ALine recipe check");
+ }
ArrayList<ItemStack> tDataStickList = getDataItems(2);
- if (tDataStickList.isEmpty()) return false;
- if (GT_Values.D1)
- GT_FML_LOGGER.info("Stick accepted, " + tDataStickList.size() + " Data Sticks found");
+ if (tDataStickList.isEmpty()) {
+ return false;
+ }
+ if (GT_Values.D1) {
+ GT_FML_LOGGER.info("Stick accepted, " + tDataStickList.size() + " Data Sticks found");
+ }
- ItemStack[] tStack = new ItemStack[15];
- FluidStack[] tFluids = new FluidStack[4];
+ ItemStack[] tStack = null;
+ FluidStack[] tFluids = null;
boolean findRecipe = false;
- nextDS:
+
+ nextDataStick:
for (ItemStack tDataStick : tDataStickList) {
- NBTTagCompound tTag = tDataStick.getTagCompound();
- if (tTag == null)
- continue;
+ GT_Recipe_AssemblyLine aFoundRecipe = GT_AssemblyLineUtils.findAssemblyLineRecipeFromDataStick(tDataStick);
+
+ // 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;
+
+ // 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++) {
- int count = tTag.getInteger("a" + i);
- if (!tTag.hasKey("" + i) && count <= 0)
- continue;
- if (mInputBusses.get(i) == null) {
- continue nextDS;
- }
-
- ItemStack stackInSlot = mInputBusses.get(i).getBaseMetaTileEntity().getStackInSlot(0);
- boolean flag = true;
- if (count > 0) {
- for (int j = 0; j < count; j++) {
- tStack[i] = GT_Utility.loadItem(tTag, "a" + i + ":" + j);
- if (tStack[i] == null) continue;
- if (GT_Values.D1)
- GT_FML_LOGGER.info("Item " + i + " : " + tStack[i].getUnlocalizedName());
- if (GT_Utility.areStacksEqual(tStack[i], stackInSlot, true) && tStack[i].stackSize <= stackInSlot.stackSize) {
- flag = false;
- break;
- }
- }
- }
- if (flag) {
- tStack[i] = GT_Utility.loadItem(tTag, "" + i);
- if (tStack[i] == null) {
- flag = false;
- continue;
- }
- if (GT_Values.D1)
- GT_FML_LOGGER.info("Item " + i + " : " + tStack[i].getUnlocalizedName());
- if (GT_Utility.areStacksEqual(tStack[i], stackInSlot, true) && tStack[i].stackSize <= stackInSlot.stackSize) {
- flag = false;
+ if (i >= aItemCount) {
+ continue;
+ }
+ else {
+ if (mInputBusses.get(i) == null) {
+ continue nextDataStick;
}
- }
- if (GT_Values.D1)
- GT_FML_LOGGER.info(i + (flag ? " not accepted" : " accepted"));
- if (flag)
- continue nextDS;
- }
-
- if (GT_Values.D1) GT_FML_LOGGER.info("All Items done, start fluid check");
- for (int i = 0; i < 4; i++) {
- if (!tTag.hasKey("f" + i)) continue;
- tFluids[i] = GT_Utility.loadFluid(tTag, "f" + i);
- if (tFluids[i] == null) continue;
- if (GT_Values.D1)
- GT_FML_LOGGER.info("Fluid " + i + " " + tFluids[i].getUnlocalizedName());
- if (mInputHatches.get(i) == null) {
- continue nextDS;
- }
- FluidStack fluidInHatch = mInputHatches.get(i).mFluid;
- if (!GT_Utility.areFluidsEqual(fluidInHatch, tFluids[i], true) || fluidInHatch.amount < tFluids[i].amount) {
- if (GT_Values.D1)
- GT_FML_LOGGER.info(i + " not accepted");
- continue nextDS;
- }
- if (GT_Values.D1)
- GT_FML_LOGGER.info(i + " accepted");
+ 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");
+ }
+ }
+ }
}
-
- if (GT_Values.D1)
- GT_FML_LOGGER.info("Input accepted, check other values");
- if (!tTag.hasKey("output"))
- continue;
- mOutputItems = new ItemStack[]{GT_Utility.loadItem(tTag, "output")};
- if (mOutputItems[0] == null || !GT_Utility.isStackValid(mOutputItems[0]))
- continue;
-
- if (!tTag.hasKey("time"))
- continue;
- int tMaxProgressTime = tTag.getInteger("time");
- if (tMaxProgressTime <= 0)
- continue;
-
- if (!tTag.hasKey("eu"))
- continue;
-
- if (GT_Values.D1) GT_FML_LOGGER.info("Check overclock");
-
- calculateOverclockedNessMulti(tTag.getInteger("eu"), tMaxProgressTime, 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) GT_FML_LOGGER.info("Recipe too OP");
- continue;
+
+ // 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) {
+ 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");
+ }
+ }
+ }
}
-
- if (GT_Values.D1) GT_FML_LOGGER.info("Find avaiable recipe");
- findRecipe = true;
- break;
+
+ if (GT_Values.D1) {
+ GT_FML_LOGGER.info("Check overclock");
+ }
+ calculateOverclockedNessMulti(aFoundRecipe.mEUt, aFoundRecipe.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) {
+ GT_FML_LOGGER.info("Recipe too OP");
+ }
+ continue;
+ }
+ if (GT_Values.D1) {
+ GT_FML_LOGGER.info("Find available recipe");
+ }
+ findRecipe = true;
}
- if (!findRecipe) return false;
+
+ // Best not to run this recipe.
+ if (!findRecipe || tStack == null || tStack.length <= 0 || tFluids == null || tFluids.length <= 0) {
+ return false;
+ }
+
- if (GT_Values.D1) GT_FML_LOGGER.info("All checked start consuming inputs");
+ 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;
+ if (tStack[i] == null) {
+ continue;
+ }
ItemStack stackInSlot = mInputBusses.get(i).getBaseMetaTileEntity().getStackInSlot(0);
stackInSlot.stackSize -= tStack[i].stackSize;
}
@@ -280,13 +276,15 @@ public class GT_MetaTileEntity_AssemblyLine extends GT_MetaTileEntity_EnhancedMu
}
}
- if (this.mEUt > 0)
- this.mEUt = -this.mEUt;
+ if (this.mEUt > 0) {
+ this.mEUt = -this.mEUt;
+ }
this.mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000);
this.mEfficiencyIncrease = 10000;
updateSlots();
- if (GT_Values.D1)
- GT_FML_LOGGER.info("Recipe sucessfull");
+ if (GT_Values.D1) {
+ GT_FML_LOGGER.info("Recipe sucessfull");
+ }
return true;
}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeChemicalReactor.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeChemicalReactor.java
index 63b536fc72..87eddb7e13 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeChemicalReactor.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeChemicalReactor.java
@@ -11,6 +11,7 @@ import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMul
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Single_Recipe_Check;
import gregtech.api.util.GT_Utility;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.item.ItemStack;
@@ -123,68 +124,98 @@ public class GT_MetaTileEntity_LargeChemicalReactor extends GT_MetaTileEntity_En
}
@Override
+ public boolean supportsSingleRecipeLocking() {
+ return true;
+ }
+
+ @Override
public boolean checkRecipe(ItemStack aStack) {
- ArrayList<ItemStack> tInputList = getStoredInputs();
- int tInputList_sS = tInputList.size();
- for (int i = 0; i < tInputList_sS - 1; i++) {
- for (int j = i + 1; j < tInputList_sS; j++) {
- if (GT_Utility.areStacksEqual(tInputList.get(i), tInputList.get(j))) {
- if (tInputList.get(i).stackSize >= tInputList.get(j).stackSize) {
- tInputList.remove(j--);
- tInputList_sS = tInputList.size();
- } else {
- tInputList.remove(i--);
- tInputList_sS = tInputList.size();
- break;
+ long tVoltage = getMaxInputVoltage();
+ byte tier = (byte) Math.max(1, GT_Utility.getTier(tVoltage));
+ GT_Recipe tRecipe;
+
+ if (mLockedToSingleRecipe && mSingleRecipeCheck != null) {
+ if (!mSingleRecipeCheck.checkRecipeInputsSingleStack(true)) {
+ return false;
+ }
+
+ tRecipe = mSingleRecipeCheck.getRecipe();
+ } else {
+ ArrayList<ItemStack> tInputList = getStoredInputs();
+ int tInputList_sS = tInputList.size();
+ for (int i = 0; i < tInputList_sS - 1; i++) {
+ for (int j = i + 1; j < tInputList_sS; j++) {
+ if (GT_Utility.areStacksEqual(tInputList.get(i), tInputList.get(j))) {
+ if (tInputList.get(i).stackSize >= tInputList.get(j).stackSize) {
+ tInputList.remove(j--);
+ tInputList_sS = tInputList.size();
+ } else {
+ tInputList.remove(i--);
+ tInputList_sS = tInputList.size();
+ break;
+ }
}
}
}
- }
- tInputList.add(mInventory[1]);
- ItemStack[] inputs = tInputList.toArray(new ItemStack[0]);
-
- ArrayList<FluidStack> tFluidList = getStoredFluids();
- int tFluidList_sS = tFluidList.size();
- for (int i = 0; i < tFluidList_sS - 1; i++) {
- for (int j = i + 1; j < tFluidList_sS; j++) {
- if (GT_Utility.areFluidsEqual(tFluidList.get(i), tFluidList.get(j))) {
- if (tFluidList.get(i).amount >= tFluidList.get(j).amount) {
- tFluidList.remove(j--);
- tFluidList_sS = tFluidList.size();
- } else {
- tFluidList.remove(i--);
- tFluidList_sS = tFluidList.size();
- break;
+ tInputList.add(mInventory[1]);
+ ItemStack[] inputs = tInputList.toArray(new ItemStack[0]);
+
+ ArrayList<FluidStack> tFluidList = getStoredFluids();
+ int tFluidList_sS = tFluidList.size();
+ for (int i = 0; i < tFluidList_sS - 1; i++) {
+ for (int j = i + 1; j < tFluidList_sS; j++) {
+ if (GT_Utility.areFluidsEqual(tFluidList.get(i), tFluidList.get(j))) {
+ if (tFluidList.get(i).amount >= tFluidList.get(j).amount) {
+ tFluidList.remove(j--);
+ tFluidList_sS = tFluidList.size();
+ } else {
+ tFluidList.remove(i--);
+ tFluidList_sS = tFluidList.size();
+ break;
+ }
}
}
}
- }
- FluidStack[] fluids = tFluidList.toArray(new FluidStack[0]);
+ FluidStack[] fluids = tFluidList.toArray(new FluidStack[0]);
+
+ if (inputs.length == 0 && fluids.length == 0) {
+ return false;
+ }
- if (inputs.length > 0 || fluids.length > 0) {
- long tVoltage = getMaxInputVoltage();
- byte tier = (byte) Math.max(1, GT_Utility.getTier(tVoltage));
- GT_Recipe tRecipe = GT_Recipe.GT_Recipe_Map.sMultiblockChemicalRecipes.findRecipe(getBaseMetaTileEntity(), false,
+ GT_Single_Recipe_Check.Builder tSingleRecipeCheckBuilder = null;
+ if (mLockedToSingleRecipe) {
+ // We're locked to a single recipe, but haven't built the recipe checker yet.
+ // Build the checker on next successful recipe.
+ tSingleRecipeCheckBuilder = GT_Single_Recipe_Check.builder(this).setBefore();
+ }
+
+ tRecipe = GT_Recipe.GT_Recipe_Map.sMultiblockChemicalRecipes.findRecipe(getBaseMetaTileEntity(), false,
false, gregtech.api.enums.GT_Values.V[tier], fluids, inputs);
- if (tRecipe != null && tRecipe.isRecipeInputEqual(true, fluids, inputs)) {
- this.mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000);
- this.mEfficiencyIncrease = 10000;
-
- calculatePerfectOverclockedNessMulti(tRecipe.mEUt, tRecipe.mDuration, 1, tVoltage);
- //In case recipe is too OP for that machine
- if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
- return false;
- if (this.mEUt > 0) {
- this.mEUt = (-this.mEUt);
- }
- this.mOutputItems = tRecipe.mOutputs;
- this.mOutputFluids = tRecipe.mFluidOutputs;
- this.updateSlots();
- return true;
+ if (tRecipe == null || !tRecipe.isRecipeInputEqual(true, fluids, inputs)) {
+ return false;
+ }
+
+ if (mLockedToSingleRecipe) {
+ mSingleRecipeCheck = tSingleRecipeCheckBuilder.setAfter().setRecipe(tRecipe).build();
}
}
- return false;
+
+ this.mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000);
+ this.mEfficiencyIncrease = 10000;
+
+ calculatePerfectOverclockedNessMulti(tRecipe.mEUt, tRecipe.mDuration, 1, tVoltage);
+ //In case recipe is too OP for that machine
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return false;
+ if (this.mEUt > 0) {
+ this.mEUt = (-this.mEUt);
+ }
+
+ this.mOutputItems = tRecipe.mOutputs;
+ this.mOutputFluids = tRecipe.mFluidOutputs;
+ this.updateSlots();
+ return true;
}
@Override
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ProcessingArray.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ProcessingArray.java
index ad0f5bd7f8..a48f63c60a 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ProcessingArray.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ProcessingArray.java
@@ -19,6 +19,7 @@ import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
import gregtech.api.util.GT_ProcessingArray_Manager;
import gregtech.api.util.GT_Recipe;
import gregtech.api.util.GT_Recipe.GT_Recipe_Map;
+import gregtech.api.util.GT_Single_Recipe_Check_Processing_Array;
import gregtech.api.util.GT_Utility;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
@@ -145,7 +146,16 @@ public class GT_MetaTileEntity_ProcessingArray extends GT_MetaTileEntity_CubicMu
}
@Override
+ public boolean supportsSingleRecipeLocking() {
+ return true;
+ }
+
+ @Override
public boolean checkRecipe(ItemStack aStack) {
+ if (mLockedToSingleRecipe && mSingleRecipeCheck != null) {
+ return processLockedRecipe();
+ }
+
if (!isCorrectMachinePart(mInventory[1])) {
return false;
}
@@ -228,6 +238,15 @@ public class GT_MetaTileEntity_ProcessingArray extends GT_MetaTileEntity_CubicMu
return false;
}
+ public boolean processLockedRecipe() {
+ GT_Single_Recipe_Check_Processing_Array tSingleRecipeCheck = (GT_Single_Recipe_Check_Processing_Array) mSingleRecipeCheck;
+
+ int machines = Math.min(64, mInventory[1].stackSize << mMult); //Upped max Cap to 64
+ int parallel = tSingleRecipeCheck.checkRecipeInputs(true, machines);
+
+ return processRecipeOutputs(tSingleRecipeCheck.getRecipe(), tSingleRecipeCheck.getRecipeAmperage(), parallel);
+ }
+
public boolean processRecipe(ItemStack[] tInputs, FluidStack[] tFluids, GT_Recipe.GT_Recipe_Map map) {
if (tInputs.length <= 0 && tFluids.length <= 0) return false;
GT_Recipe tRecipe = map.findRecipe(getBaseMetaTileEntity(), mLastRecipe, false, gregtech.api.enums.GT_Values.V[tTier], tFluids, tInputs);
@@ -236,54 +255,77 @@ public class GT_MetaTileEntity_ProcessingArray extends GT_MetaTileEntity_CubicMu
!isValidForLowGravity(tRecipe, getBaseMetaTileEntity().getWorld().provider.dimensionId))
return false;
+ GT_Single_Recipe_Check_Processing_Array.Builder tSingleRecipeCheckBuilder = null;
+ if (mLockedToSingleRecipe) {
+ // We're locked to a single recipe, but haven't built the recipe checker yet.
+ // Build the checker on next successful recipe.
+ tSingleRecipeCheckBuilder = GT_Single_Recipe_Check_Processing_Array.processingArrayBuilder(this).setBefore();
+ }
+
+ boolean recipeLocked = false;
mLastRecipe = tRecipe;
- this.mEUt = 0;
- this.mOutputItems = null;
- this.mOutputFluids = null;
int machines = Math.min(64, mInventory[1].stackSize << mMult); //Upped max Cap to 64
int i = 0;
for (; i < machines; i++) {
if (!tRecipe.isRecipeInputEqual(true, tFluids, tInputs)) {
- if (i == 0) {
- return false;
- }
break;
+ } else if (mLockedToSingleRecipe && !recipeLocked) {
+ // We want to lock to a single run of the recipe.
+ mSingleRecipeCheck =
+ tSingleRecipeCheckBuilder
+ .setAfter()
+ .setRecipe(tRecipe)
+ .setRecipeAmperage(map.mAmperage)
+ .build();
+ recipeLocked = true;
}
}
- this.mMaxProgresstime = tRecipe.mDuration;
+
+ return processRecipeOutputs(tRecipe, map.mAmperage, i);
+ }
+
+ public boolean processRecipeOutputs(GT_Recipe aRecipe, int aAmperage, int parallel) {
+ this.mEUt = 0;
+ this.mOutputItems = null;
+ this.mOutputFluids = null;
+ if (parallel == 0) {
+ return false;
+ }
+
+ this.mMaxProgresstime = aRecipe.mDuration;
this.mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000);
this.mEfficiencyIncrease = 10000;
- calculateOverclockedNessMulti(tRecipe.mEUt, tRecipe.mDuration, map.mAmperage, GT_Values.V[tTier]);
+ calculateOverclockedNessMulti(aRecipe.mEUt, aRecipe.mDuration, aAmperage, GT_Values.V[tTier]);
//In case recipe is too OP for that machine
if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
return false;
- this.mEUt = GT_Utility.safeInt(((long) this.mEUt * i) >> mMult, 1);
+ this.mEUt = GT_Utility.safeInt(((long) this.mEUt * parallel) >> mMult, 1);
if (mEUt == Integer.MAX_VALUE - 1)
return false;
if (this.mEUt > 0) {
this.mEUt = (-this.mEUt);
}
- ItemStack[] tOut = new ItemStack[tRecipe.mOutputs.length];
- for (int h = 0; h < tRecipe.mOutputs.length; h++) {
- if (tRecipe.getOutput(h) != null) {
- tOut[h] = tRecipe.getOutput(h).copy();
+ ItemStack[] tOut = new ItemStack[aRecipe.mOutputs.length];
+ for (int h = 0; h < aRecipe.mOutputs.length; h++) {
+ if (aRecipe.getOutput(h) != null) {
+ tOut[h] = aRecipe.getOutput(h).copy();
tOut[h].stackSize = 0;
}
}
FluidStack tFOut = null;
- if (tRecipe.getFluidOutput(0) != null) tFOut = tRecipe.getFluidOutput(0).copy();
+ if (aRecipe.getFluidOutput(0) != null) tFOut = aRecipe.getFluidOutput(0).copy();
for (int f = 0; f < tOut.length; f++) {
- if (tRecipe.mOutputs[f] != null && tOut[f] != null) {
- for (int g = 0; g < i; g++) {
- if (getBaseMetaTileEntity().getRandomNumber(10000) < tRecipe.getOutputChance(f))
- tOut[f].stackSize += tRecipe.mOutputs[f].stackSize;
+ if (aRecipe.mOutputs[f] != null && tOut[f] != null) {
+ for (int g = 0; g < parallel; g++) {
+ if (getBaseMetaTileEntity().getRandomNumber(10000) < aRecipe.getOutputChance(f))
+ tOut[f].stackSize += aRecipe.mOutputs[f].stackSize;
}
}
}
if (tFOut != null) {
int tSize = tFOut.amount;
- tFOut.amount = tSize * i;
+ tFOut.amount = tSize * parallel;
}
this.mMaxProgresstime = Math.max(1, this.mMaxProgresstime);
this.mOutputItems = Arrays.stream(tOut)
@@ -353,8 +395,13 @@ public class GT_MetaTileEntity_ProcessingArray extends GT_MetaTileEntity_CubicMu
@Override
public final void onScrewdriverRightClick(byte aSide, EntityPlayer aPlayer, float aX, float aY, float aZ) {
- mSeparate = !mSeparate;
- GT_Utility.sendChatToPlayer(aPlayer, StatCollector.translateToLocal("GT5U.machines.separatebus") + " " + mSeparate);
+ if (aPlayer.isSneaking()) {
+ // Lock to single recipe
+ super.onScrewdriverRightClick(aSide, aPlayer, aX, aY, aZ);
+ } else {
+ mSeparate = !mSeparate;
+ GT_Utility.sendChatToPlayer(aPlayer, StatCollector.translateToLocal("GT5U.machines.separatebus") + " " + mSeparate);
+ }
}
@Override
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PyrolyseOven.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PyrolyseOven.java
index ae96b82a23..9542c54ce0 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PyrolyseOven.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PyrolyseOven.java
@@ -16,6 +16,7 @@ import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMul
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Single_Recipe_Check;
import gregtech.api.util.GT_Utility;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.item.ItemStack;
@@ -129,19 +130,45 @@ public class GT_MetaTileEntity_PyrolyseOven extends GT_MetaTileEntity_EnhancedMu
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
- ItemStack[] tInputs = getCompactedInputs();
- FluidStack[] tFluids = getCompactedFluids();
-
- if (tInputs.length <= 0)
- return false;
+ public boolean supportsSingleRecipeLocking() {
+ return true;
+ }
+ @Override
+ public boolean checkRecipe(ItemStack aStack) {
long tVoltage = getMaxInputVoltage();
byte tTier = (byte) Math.max(1, GT_Utility.getTier(tVoltage));
- GT_Recipe tRecipe = GT_Recipe.GT_Recipe_Map.sPyrolyseRecipes.findRecipe(getBaseMetaTileEntity(), false, gregtech.api.enums.GT_Values.V[tTier], tFluids, tInputs);
+ GT_Recipe tRecipe;
- if (tRecipe == null || !tRecipe.isRecipeInputEqual(true, tFluids, tInputs))
- return false;
+ if (mLockedToSingleRecipe && mSingleRecipeCheck != null) {
+ if (!mSingleRecipeCheck.checkRecipeInputsSingleStack(true)) {
+ return false;
+ }
+
+ tRecipe = mSingleRecipeCheck.getRecipe();
+ } else {
+ ItemStack[] tInputs = getCompactedInputs();
+ FluidStack[] tFluids = getCompactedFluids();
+
+ if (tInputs.length <= 0)
+ return false;
+
+ GT_Single_Recipe_Check.Builder tSingleRecipeCheckBuilder = null;
+ if (mLockedToSingleRecipe) {
+ // We're locked to a single recipe, but haven't built the recipe checker yet.
+ // Build the checker on next successful recipe.
+ tSingleRecipeCheckBuilder = GT_Single_Recipe_Check.builder(this).setBefore();
+ }
+
+ tRecipe = GT_Recipe.GT_Recipe_Map.sPyrolyseRecipes.findRecipe(getBaseMetaTileEntity(), false, gregtech.api.enums.GT_Values.V[tTier], tFluids, tInputs);
+
+ if (tRecipe == null || !tRecipe.isRecipeInputEqual(true, tFluids, tInputs))
+ return false;
+
+ if (mLockedToSingleRecipe) {
+ mSingleRecipeCheck = tSingleRecipeCheckBuilder.setAfter().setRecipe(tRecipe).build();
+ }
+ }
this.mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000);
this.mEfficiencyIncrease = 10000;
diff --git a/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_DigitalChestBase.java b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_DigitalChestBase.java
index 7110ed20f9..c7bd5d0029 100644
--- a/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_DigitalChestBase.java
+++ b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_DigitalChestBase.java
@@ -34,7 +34,8 @@ public abstract class GT_MetaTileEntity_DigitalChestBase extends GT_MetaTileEnti
super(aID, aName, aNameRegional, aTier, 3, new String[]{
"This Chest stores " + GT_Utility.formatNumbers(commonSizeCompute(aTier)) + " Blocks",
"Use a screwdriver to enable",
- "voiding items on overflow"
+ "voiding items on overflow",
+ "Can keep its contents when harvested"
});
}
diff --git a/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_QuantumChest.java b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_QuantumChest.java
index 20d333783e..ca3289e218 100644
--- a/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_QuantumChest.java
+++ b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_QuantumChest.java
@@ -3,11 +3,16 @@ package gregtech.common.tileentities.storage;
import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.metatileentity.MetaTileEntity;
+import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
public class GT_MetaTileEntity_QuantumChest extends GT_MetaTileEntity_DigitalChestBase {
public int mItemCount = 0;
public ItemStack mItemStack = null;
+ NBTTagList mInvData = null;
+
public GT_MetaTileEntity_QuantumChest(int aID, String aName, String aNameRegional, int aTier) {
super(aID, aName, aNameRegional, aTier);
}
@@ -24,16 +29,53 @@ public class GT_MetaTileEntity_QuantumChest extends GT_MetaTileEntity_DigitalChe
public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
return new GT_MetaTileEntity_QuantumChest(mName, mTier, mDescriptionArray, mTextures);
}
+
@Override
- protected String chestName(){ return "Quantum Chest"; }
+ public void setItemNBT(NBTTagCompound aNBT) {
+ mInvData = new NBTTagList();
+ for (int i = 0; i < 3; i++) {
+ if (mInventory[i] != null) {
+ NBTTagCompound tNBT = new NBTTagCompound();
+ tNBT.setByte("Count", (byte) mInventory[i].stackSize);
+ tNBT.setShort("Damage", (short) mInventory[i].getItemDamage());
+ tNBT.setShort("id", (short) Item.getIdFromItem(mInventory[i].getItem()));
+ tNBT.setInteger("IntSlot", i);
+ if (mInventory[i].hasTagCompound()) {
+ tNBT.setTag("tag", mInventory[i].getTagCompound());
+ }
+ mInvData.appendTag(tNBT);
+ }
+ }
+ if (mItemStack != null)
+ aNBT.setTag("mItemStack", getItemStack().writeToNBT(new NBTTagCompound()));
+ aNBT.setTag("Inventory", mInvData);
+ aNBT.setInteger("mItemCount", getItemCount());
+ aNBT.setBoolean("mVoidOverflow", mVoidOverflow);
+ super.setItemNBT(aNBT);
+ }
+
@Override
- protected int getItemCount() { return mItemCount; }
+ protected String chestName() {
+ return "Quantum Chest";
+ }
+
+ @Override
+ protected int getItemCount() {
+ return mItemCount;
+ }
+
@Override
public void setItemCount(int aCount) {
mItemCount = aCount;
}
+
@Override
- protected ItemStack getItemStack(){ return mItemStack; }
+ protected ItemStack getItemStack() {
+ return mItemStack;
+ }
+
@Override
- protected void setItemStack(ItemStack s){ mItemStack = s; }
+ protected void setItemStack(ItemStack s) {
+ mItemStack = s;
+ }
}
diff --git a/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_QuantumTank.java b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_QuantumTank.java
index ea935f1360..1637a126e4 100644
--- a/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_QuantumTank.java
+++ b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_QuantumTank.java
@@ -7,6 +7,7 @@ import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicTank;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Utility;
import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumChatFormatting;
import net.minecraftforge.common.util.ForgeDirection;
@@ -16,8 +17,10 @@ import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_QTANK_GLOW;
public class GT_MetaTileEntity_QuantumTank extends GT_MetaTileEntity_BasicTank {
public GT_MetaTileEntity_QuantumTank(int aID, String aName, String aNameRegional, int aTier) {
- super(aID, aName, aNameRegional, aTier, 3,
- "Stores " + GT_Utility.formatNumbers(commonSizeCompute(aTier)) + "L of fluid");
+ super(aID, aName, aNameRegional, aTier, 3, new String[]{
+ "Stores " + GT_Utility.formatNumbers(commonSizeCompute(aTier)) + "L of fluid",
+ "Can keep its contents when harvested"
+ });
}
private static int commonSizeCompute(int tier) {
@@ -51,6 +54,13 @@ public class GT_MetaTileEntity_QuantumTank extends GT_MetaTileEntity_BasicTank {
}
@Override
+ public void setItemNBT(NBTTagCompound aNBT) {
+ if (mFluid != null && mFluid.amount > 0)
+ aNBT.setTag("mFluid", mFluid.writeToNBT(new NBTTagCompound()));
+ super.setItemNBT(aNBT);
+ }
+
+ @Override
public boolean isSimpleMachine() {
return true;
}
diff --git a/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_SuperChest.java b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_SuperChest.java
index e566ba9ed5..4614cc409e 100644
--- a/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_SuperChest.java
+++ b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_SuperChest.java
@@ -3,11 +3,15 @@ package gregtech.common.tileentities.storage;
import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.metatileentity.MetaTileEntity;
+import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
public class GT_MetaTileEntity_SuperChest extends GT_MetaTileEntity_DigitalChestBase {
public int mItemCount = 0;
public ItemStack mItemStack = null;
+ NBTTagList mInvData = null;
public GT_MetaTileEntity_SuperChest(int aID, String aName, String aNameRegional, int aTier) {
super(aID, aName, aNameRegional, aTier);
@@ -22,6 +26,30 @@ public class GT_MetaTileEntity_SuperChest extends GT_MetaTileEntity_DigitalChest
}
@Override
+ public void setItemNBT(NBTTagCompound aNBT) {
+ mInvData = new NBTTagList();
+ for (int i = 0; i < 3; i++) {
+ if (mInventory[i] != null) {
+ NBTTagCompound tNBT = new NBTTagCompound();
+ tNBT.setByte("Count", (byte) mInventory[i].stackSize);
+ tNBT.setShort("Damage", (short) mInventory[i].getItemDamage());
+ tNBT.setShort("id", (short) Item.getIdFromItem(mInventory[i].getItem()));
+ tNBT.setInteger("IntSlot", i);
+ if (mInventory[i].hasTagCompound()) {
+ tNBT.setTag("tag", mInventory[i].getTagCompound());
+ }
+ mInvData.appendTag(tNBT);
+ }
+ }
+ if (mItemStack != null)
+ aNBT.setTag("mItemStack", getItemStack().writeToNBT(new NBTTagCompound()));
+ aNBT.setTag("Inventory", mInvData);
+ aNBT.setInteger("mItemCount", getItemCount());
+ aNBT.setBoolean("mVoidOverflow", mVoidOverflow);
+ super.setItemNBT(aNBT);
+ }
+
+ @Override
protected ItemStack getItemStack() {
return mItemStack;
}
diff --git a/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_SuperTank.java b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_SuperTank.java
index edb69abb20..1aa9f98d82 100644
--- a/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_SuperTank.java
+++ b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_SuperTank.java
@@ -7,6 +7,7 @@ import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicTank;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Utility;
import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumChatFormatting;
import net.minecraftforge.common.util.ForgeDirection;
@@ -16,8 +17,10 @@ import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_QTANK_GLOW;
public class GT_MetaTileEntity_SuperTank extends GT_MetaTileEntity_BasicTank {
public GT_MetaTileEntity_SuperTank(int aID, String aName, String aNameRegional, int aTier) {
- super(aID, aName, aNameRegional, aTier, 3,
- "Stores " + GT_Utility.formatNumbers(commonSizeCompute(aTier)) + "L of fluid");
+ super(aID, aName, aNameRegional, aTier, 3, new String[]{
+ "Stores " + GT_Utility.formatNumbers(commonSizeCompute(aTier)) + "L of fluid",
+ "Can keep its contents when harvested"
+ });
}
private static int commonSizeCompute(int tier) {
@@ -51,6 +54,13 @@ public class GT_MetaTileEntity_SuperTank extends GT_MetaTileEntity_BasicTank {
}
@Override
+ public void setItemNBT(NBTTagCompound aNBT) {
+ if (mFluid != null && mFluid.amount > 0)
+ aNBT.setTag("mFluid", mFluid.writeToNBT(new NBTTagCompound()));
+ super.setItemNBT(aNBT);
+ }
+
+ @Override
public boolean isSimpleMachine() {
return true;
}
diff --git a/src/main/java/gregtech/loaders/postload/GT_CraftingRecipeLoader.java b/src/main/java/gregtech/loaders/postload/GT_CraftingRecipeLoader.java
index 68cdf15583..449aa556bd 100644
--- a/src/main/java/gregtech/loaders/postload/GT_CraftingRecipeLoader.java
+++ b/src/main/java/gregtech/loaders/postload/GT_CraftingRecipeLoader.java
@@ -502,7 +502,17 @@ public class GT_CraftingRecipeLoader implements Runnable {
GT_ModHandler.addShapelessCraftingRecipe(GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Saltpeter, 5L), bits_no_remove_buffered, new Object[]{OrePrefixes.dust.get(Materials.Potassium), OrePrefixes.cell.get(Materials.Nitrogen), OrePrefixes.cell.get(Materials.Oxygen), OrePrefixes.cell.get(Materials.Oxygen), OrePrefixes.cell.get(Materials.Oxygen)});
GT_ModHandler.removeRecipeByOutputDelayed(GT_ModHandler.getIC2Item("carbonFiber", 1L));
-
+
+ ItemStack[] tChestAndTank = new ItemStack[]{
+ ItemList.Super_Chest_EV.get(1), ItemList.Super_Chest_IV.get(1), ItemList.Super_Chest_HV.get(1), ItemList.Super_Chest_MV.get(1), ItemList.Super_Chest_LV.get(1),
+ ItemList.Quantum_Chest_EV.get(1), ItemList.Quantum_Chest_IV.get(1), ItemList.Quantum_Chest_HV.get(1), ItemList.Quantum_Chest_MV.get(1), ItemList.Quantum_Chest_LV.get(1),
+ ItemList.Super_Tank_EV.get(1), ItemList.Super_Tank_IV.get(1), ItemList.Super_Tank_HV.get(1), ItemList.Super_Tank_MV.get(1), ItemList.Super_Tank_LV.get(1),
+ ItemList.Quantum_Chest_EV.get(1), ItemList.Quantum_Chest_IV.get(1), ItemList.Quantum_Chest_HV.get(1), ItemList.Quantum_Chest_MV.get(1), ItemList.Quantum_Chest_LV.get(1)
+ };
+ for (ItemStack tItem : tChestAndTank) {
+ GT_ModHandler.addShapelessCraftingRecipe(tItem, GT_ModHandler.RecipeBits.DISMANTLEABLE, new Object[]{tItem});
+ }
+
if (GT_Mod.gregtechproxy.mDisableIC2Cables) {
List<ItemStack> iToRemoveAndHide = Arrays.stream(new String[] {