diff options
Diffstat (limited to 'src/main/java/net/glease/ggfab/mte/MTE_AdvAssLine.java')
-rw-r--r-- | src/main/java/net/glease/ggfab/mte/MTE_AdvAssLine.java | 136 |
1 files changed, 114 insertions, 22 deletions
diff --git a/src/main/java/net/glease/ggfab/mte/MTE_AdvAssLine.java b/src/main/java/net/glease/ggfab/mte/MTE_AdvAssLine.java index ed04c2fbce..e540bb4562 100644 --- a/src/main/java/net/glease/ggfab/mte/MTE_AdvAssLine.java +++ b/src/main/java/net/glease/ggfab/mte/MTE_AdvAssLine.java @@ -36,6 +36,7 @@ import net.glease.ggfab.GGConstants; import net.glease.ggfab.mui.ClickableTextWidget; import net.glease.ggfab.util.OverclockHelper; import net.minecraft.client.resources.I18n; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; @@ -189,6 +190,10 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_ExtendedPowerMultiBlockBas private boolean sortFluidHatches; private int currentInputLength; private String lastStopReason = ""; + private int currentRecipeParallel = 1; + // Batch mode will increase parallel per slice to try to get as close as possible to this amount of ticks + // per slice, but will never go over this amount. + private static final int BATCH_MODE_DESIRED_TICKS_PER_SLICE = 128; public MTE_AdvAssLine(int aID, String aName, String aNameRegional) { super(aID, aName, aNameRegional); @@ -343,6 +348,8 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_ExtendedPowerMultiBlockBas currentRecipe = recipe; currentStick = stick; currentInputLength = recipe.mInputs.length; + // Reset parallel, we need to re-check on next recipe check to see if there are enough items in the first slice + currentRecipeParallel = 1; } private void clearCurrentRecipe() { @@ -375,6 +382,7 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_ExtendedPowerMultiBlockBas aNBT.setLong("inputV", inputVoltage); aNBT.setLong("inputEU", inputEUt); aNBT.setLong("baseEU", baseEUt); + aNBT.setInteger("currentParallel", currentRecipeParallel); } } @@ -406,6 +414,7 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_ExtendedPowerMultiBlockBas inputVoltage = aNBT.getLong("inputV"); inputEUt = aNBT.getLong("inputEU"); baseEUt = aNBT.getLong("baseEU"); + currentRecipeParallel = aNBT.getInteger("currentParallel"); if (inputVoltage <= 0 || inputEUt <= 0 || baseEUt >= 0) { criticalStopMachine("ggfab.gui.advassline.shutdown.load.energy"); loadedStack = null; @@ -604,8 +613,10 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_ExtendedPowerMultiBlockBas } if (getBaseMetaTileEntity().isAllowedToWork()) { - if (hasAllItems(currentRecipe) && hasAllFluids(currentRecipe) && slices[0].start()) { - drainAllFluids(currentRecipe); + if (hasAllItems(currentRecipe, this.currentRecipeParallel) + && hasAllFluids(currentRecipe, this.currentRecipeParallel) + && slices[0].start()) { + drainAllFluids(currentRecipe, this.currentRecipeParallel); mProgresstime = 0; } } @@ -621,6 +632,10 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_ExtendedPowerMultiBlockBas if (index < mInputBusses.size()) { GT_MetaTileEntity_Hatch_InputBus bus = mInputBusses.get(index); if (bus.isValid()) { + // This limits items extracted per slice to 64. Normally this is not an issue, but with batch + // mode it can suddenly cause the AAL to get stuck because it thinks there are not enough + // items in the bus. I'm not quite sure how to get around this, even though it should not matter + // in practice since all AAL automation uses stocking buses instead of regular input buses. stuff = bus.getStackInSlot(0); } } @@ -649,11 +664,12 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_ExtendedPowerMultiBlockBas // 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 item Inputs align - if (!hasAllItems(tRecipe)) return null; + // Check item Inputs align. For this we do not need to consider batch mode parallels yet, this will be done + // later on during recipe start. + if (!hasAllItems(tRecipe, 1)) return null; - // Check Fluid Inputs align - if (!hasAllFluids(tRecipe)) return null; + // Check Fluid Inputs align. Again, do not consider parallels + if (!hasAllFluids(tRecipe, 1)) return null; if (GT_Values.D1) { GT_FML_LOGGER.info("Check overclock"); @@ -664,13 +680,17 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_ExtendedPowerMultiBlockBas return tRecipe; } - private boolean hasAllItems(GT_Recipe.GT_Recipe_AssemblyLine tRecipe) { + private boolean hasAllItems(GT_Recipe.GT_Recipe_AssemblyLine tRecipe, int parallel) { int aItemCount = tRecipe.mInputs.length; if (mInputBusses.size() < aItemCount) return false; for (int i = 0; i < aItemCount; i++) { ItemStack tSlotStack = getInputBusContent(i); if (tSlotStack == null) return false; - int tRequiredStackSize = isStackValidIngredient(tSlotStack, tRecipe.mInputs[i], tRecipe.mOreDictAlt[i]); + int tRequiredStackSize = isStackValidIngredient( + tSlotStack, + tRecipe.mInputs[i], + tRecipe.mOreDictAlt[i], + parallel); if (tRequiredStackSize < 0) return false; if (GT_Values.D1) { @@ -680,7 +700,9 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_ExtendedPowerMultiBlockBas return true; } - private boolean hasAllFluids(GT_Recipe.GT_Recipe_AssemblyLine tRecipe) { + private boolean hasAllFluids(GT_Recipe.GT_Recipe_AssemblyLine tRecipe, int parallel) { + // TODO: Actually use the parallel parameter here, though this is already checked on recipe check, + // we may need to re-check int aFluidCount = tRecipe.mFluidInputs.length; if (mInputHatches.size() < aFluidCount) return false; for (int i = 0; i < aFluidCount; i++) { @@ -780,8 +802,41 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_ExtendedPowerMultiBlockBas mMaxProgresstime = laserOverclock.getDuration(); } } + // Save this for batch mode parallel calculations + int timePerSlice = mMaxProgresstime; // correct the recipe duration mMaxProgresstime *= recipe.mInputs.length; + + // Finally apply batch mode parallels if possible. + // For this we need to verify the first item slot and all fluids slots have enough resources + // to execute parallels. + // Note that we skip this entirely if the time for each slice is more than + // BATCH_MODE_DESIRED_TICKS_PER_SLICE ticks, since in this case the amount of batches will always be 1 + if (super.isBatchModeEnabled() && timePerSlice < BATCH_MODE_DESIRED_TICKS_PER_SLICE) { + // Calculate parallel based on time per slice, and the amount of items in the first slot. + // If there is not enough fluid, no batching will be done. + + ItemStack firstItemSlot = getInputBusContent(0); + int recipesAvailable = Math.floorDiv(firstItemSlot.stackSize, recipe.mInputs[0].stackSize); + // Divide recipes available by the amount of slices in the recipe. This will prevent the AAL from + // batching instead of parallelizing, which would make it effectively slower. + recipesAvailable = Math.floorDiv(recipesAvailable, recipe.mInputs.length); + // Sanity check to avoid this being zero when there is only one recipe available. + recipesAvailable = Math.max(recipesAvailable, 1); + int desiredBatches = Math.floorDiv(BATCH_MODE_DESIRED_TICKS_PER_SLICE, timePerSlice); + // Limit the amount of parallel to both the amount of recipes available and the maximum number + // of batches we want to run. The latter is done to prevent batch mode from ever going above + // BATCH_MODE_DESIRED_TICKS_PER_SLICE ticks per slice (see also where it is defined above). + int parallel = Math.min(recipesAvailable, desiredBatches); + // We no longer need to check if we have enough items in the first slot, as this is + // guaranteed by taking the minimum earlier. + if (hasAllFluids(recipe, parallel)) { + this.currentRecipeParallel = parallel; + // Update recipe duration with final batch mode multiplier + mMaxProgresstime *= this.currentRecipeParallel; + } + } + break; } } @@ -802,9 +857,11 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_ExtendedPowerMultiBlockBas // something very very wrong... return CheckRecipeResultRegistry.NONE; } - drainAllFluids(recipe); + drainAllFluids(recipe, this.currentRecipeParallel); - mOutputItems = new ItemStack[] { recipe.mOutput }; + // Apply parallel + mOutputItems = new ItemStack[] { recipe.mOutput.copy() }; + mOutputItems[0].stackSize *= this.currentRecipeParallel; if (this.lEUt > 0) { this.lEUt = -this.lEUt; @@ -904,9 +961,12 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_ExtendedPowerMultiBlockBas * Caller is responsible to check and ensure the hatches are there and has all the fluid needed. You will usually * want to ensure hasAllFluid was called right before calling this, otherwise very bad things can happen. */ - private void drainAllFluids(GT_Recipe.GT_Recipe_AssemblyLine recipe) { + private void drainAllFluids(GT_Recipe.GT_Recipe_AssemblyLine recipe, int parallel) { for (int i = 0; i < recipe.mFluidInputs.length; i++) { - mInputHatches.get(i).drain(ForgeDirection.UNKNOWN, recipe.mFluidInputs[i], true); + // Apply parallel + FluidStack fluidInput = recipe.mFluidInputs[i].copy(); + fluidInput.amount *= parallel; + mInputHatches.get(i).drain(ForgeDirection.UNKNOWN, fluidInput, true); } sortFluidHatches = true; } @@ -917,21 +977,43 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_ExtendedPowerMultiBlockBas super.stopMachine(); } - private static int isStackValidIngredient(ItemStack aSlotStack, ItemStack aIngredient, ItemStack[] alts) { - if (alts == null || alts.length == 0) return isStackValidIngredient(aSlotStack, aIngredient); + private static int isStackValidIngredient(ItemStack aSlotStack, ItemStack aIngredient, ItemStack[] alts, + int parallel) { + if (alts == null || alts.length == 0) return isStackValidIngredient(aSlotStack, aIngredient, parallel); for (ItemStack tAltStack : alts) { - int i = isStackValidIngredient(aSlotStack, tAltStack); + int i = isStackValidIngredient(aSlotStack, tAltStack, parallel); 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; + private static int isStackValidIngredient(ItemStack aSlotStack, ItemStack aIngredient, int parallel) { + int ingredientStackSizeWithParallel = aIngredient.stackSize * parallel; + if (GT_Utility.areStacksEqual(aSlotStack, aIngredient, true) + && ingredientStackSizeWithParallel <= aSlotStack.stackSize) + return ingredientStackSizeWithParallel; return -1; } + @Override + public boolean supportsBatchMode() { + return true; + } + + @Override + public boolean onWireCutterRightClick(ForgeDirection side, ForgeDirection wrenchingSide, EntityPlayer aPlayer, + float aX, float aY, float aZ) { + if (aPlayer.isSneaking()) { + batchMode = !batchMode; + if (batchMode) { + GT_Utility.sendChatToPlayer(aPlayer, "Batch recipes"); + } else { + GT_Utility.sendChatToPlayer(aPlayer, "Don't batch recipes"); + } + } + return true; + } + private class SliceStatusWidget extends TextWidget implements ISyncedWidget { private final Slice slice; @@ -1008,7 +1090,9 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_ExtendedPowerMultiBlockBas if (progress == 0 || --progress == 0) { // id==0 will be end of chain if 1 input, so we need a +1 here if (id + 1 >= currentInputLength) { - if (addOutput(currentRecipe.mOutput) || !voidingMode.protectItem) reset(); + // use previously calculated parallel output + ItemStack output = mOutputItems[0]; + if (addOutput(output) || !voidingMode.protectItem) reset(); else stuck = true; } else { if (slices[id + 1].start()) reset(); @@ -1022,7 +1106,11 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_ExtendedPowerMultiBlockBas startRecipeProcessing(); ItemStack stack = getInputBusContent(id); if (stack == null) return false; - int size = isStackValidIngredient(stack, currentRecipe.mInputs[id], currentRecipe.mOreDictAlt[id]); + int size = isStackValidIngredient( + stack, + currentRecipe.mInputs[id], + currentRecipe.mOreDictAlt[id], + currentRecipeParallel); if (size < 0) return false; progress = mMaxProgresstime / currentInputLength; stack.stackSize -= size; @@ -1040,7 +1128,11 @@ public class MTE_AdvAssLine extends GT_MetaTileEntity_ExtendedPowerMultiBlockBas public boolean hasInput() { ItemStack stack = getInputBusContent(id); if (stack == null) return false; - return isStackValidIngredient(stack, currentRecipe.mInputs[id], currentRecipe.mOreDictAlt[id]) >= 0; + return isStackValidIngredient( + stack, + currentRecipe.mInputs[id], + currentRecipe.mOreDictAlt[id], + currentRecipeParallel) >= 0; } @Override |