aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorGlease <4586901+Glease@users.noreply.github.com>2022-08-31 00:02:15 +0800
committerGitHub <noreply@github.com>2022-08-30 18:02:15 +0200
commit15ec51bb053de5fca2ecf3521ccec0afd1ee373e (patch)
treeeea0c50c15a5eb7b1518592174f2cb9ebe1991fc /src/main
parent277200c3a830abf88bb416707405c35eb9185dc3 (diff)
downloadGT5-Unofficial-15ec51bb053de5fca2ecf3521ccec0afd1ee373e.tar.gz
GT5-Unofficial-15ec51bb053de5fca2ecf3521ccec0afd1ee373e.tar.bz2
GT5-Unofficial-15ec51bb053de5fca2ecf3521ccec0afd1ee373e.zip
a less buggy and more performant canBufferOutput implementation for fluid management (#317)
* a less buggy and more performant canBufferOutput implementation for fluid management * fix CME * spotless * also redo item canBufferOutputs * spotless Co-authored-by: kuba6000 <kuba.123123.6000@gmail.com>
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMeta_MultiBlockBase.java479
1 files changed, 190 insertions, 289 deletions
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMeta_MultiBlockBase.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMeta_MultiBlockBase.java
index 4bd18819c6..2e3bb86147 100644
--- a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMeta_MultiBlockBase.java
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMeta_MultiBlockBase.java
@@ -2,6 +2,7 @@ package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.base;
import static gtPlusPlus.core.util.data.ArrayUtils.removeNulls;
+import com.gtnewhorizon.gtnhlib.util.map.ItemStackMap;
import com.gtnewhorizon.structurelib.StructureLibAPI;
import com.gtnewhorizon.structurelib.structure.IItemSource;
import com.gtnewhorizon.structurelib.structure.IStructureElement;
@@ -23,6 +24,7 @@ import gregtech.api.metatileentity.MetaTileEntity;
import gregtech.api.metatileentity.implementations.*;
import gregtech.api.objects.GT_ItemStack;
import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_ModHandler;
import gregtech.api.util.GT_OreDictUnificator;
import gregtech.api.util.GT_Recipe;
import gregtech.api.util.GT_Recipe.GT_Recipe_Map;
@@ -49,6 +51,7 @@ import gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
+import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;
@@ -124,24 +127,19 @@ public abstract class GregtechMeta_MultiBlockBase<T extends GT_MetaTileEntity_En
protected long mTotalRunTime = 0;
protected boolean mVoidExcess = false;
- public ArrayList<GT_MetaTileEntity_Hatch_ControlCore> mControlCoreBus =
- new ArrayList<GT_MetaTileEntity_Hatch_ControlCore>();
+ public ArrayList<GT_MetaTileEntity_Hatch_ControlCore> mControlCoreBus = new ArrayList<>();
/**
* Don't use this for recipe input check, otherwise you'll get duplicated fluids
*/
- public ArrayList<GT_MetaTileEntity_Hatch_AirIntake> mAirIntakes =
- new ArrayList<GT_MetaTileEntity_Hatch_AirIntake>();
+ public ArrayList<GT_MetaTileEntity_Hatch_AirIntake> mAirIntakes = new ArrayList<>();
- public ArrayList<GT_MetaTileEntity_Hatch_InputBattery> mChargeHatches =
- new ArrayList<GT_MetaTileEntity_Hatch_InputBattery>();
- public ArrayList<GT_MetaTileEntity_Hatch_OutputBattery> mDischargeHatches =
- new ArrayList<GT_MetaTileEntity_Hatch_OutputBattery>();
- public ArrayList<GT_MetaTileEntity_Hatch> mAllEnergyHatches = new ArrayList<GT_MetaTileEntity_Hatch>();
- public ArrayList<GT_MetaTileEntity_Hatch> mAllDynamoHatches = new ArrayList<GT_MetaTileEntity_Hatch>();
+ public ArrayList<GT_MetaTileEntity_Hatch_InputBattery> mChargeHatches = new ArrayList<>();
+ public ArrayList<GT_MetaTileEntity_Hatch_OutputBattery> mDischargeHatches = new ArrayList<>();
+ public ArrayList<GT_MetaTileEntity_Hatch> mAllEnergyHatches = new ArrayList<>();
+ public ArrayList<GT_MetaTileEntity_Hatch> mAllDynamoHatches = new ArrayList<>();
// Custom Behaviour Map
- private static final HashMap<String, SpecialMultiBehaviour> mCustomBehviours =
- new HashMap<String, SpecialMultiBehaviour>();
+ private static final HashMap<String, SpecialMultiBehaviour> mCustomBehviours = new HashMap<>();
public GregtechMeta_MultiBlockBase(final int aID, final String aName, final String aNameRegional) {
super(aID, aName, aNameRegional);
@@ -157,6 +155,12 @@ public abstract class GregtechMeta_MultiBlockBase<T extends GT_MetaTileEntity_En
&& !aMetaTileEntity.getBaseMetaTileEntity().isDead();
}
+ private static int toStackCount(Entry<ItemStack, Integer> e) {
+ int tMaxStackSize = e.getKey().getMaxStackSize();
+ int tStackSize = e.getValue();
+ return (tStackSize + tMaxStackSize - 1) / tMaxStackSize;
+ }
+
public abstract boolean hasSlotInGUI();
public long getTotalRuntimeInTicks() {
@@ -222,7 +226,7 @@ public abstract class GregtechMeta_MultiBlockBase<T extends GT_MetaTileEntity_En
@Override
public final String[] getInfoData() {
- ArrayList<String> mInfo = new ArrayList<String>();
+ ArrayList<String> mInfo = new ArrayList<>();
try {
if (!this.getMetaName().equals("")) {
mInfo.add(this.getMetaName());
@@ -473,306 +477,203 @@ public abstract class GregtechMeta_MultiBlockBase<T extends GT_MetaTileEntity_En
*/
if (aDoesOutputItems) {
- log("We have items to output.");
+ aParallelRecipes = canBufferOutputs(aItemOutputs, aParallelRecipes);
+ if (aParallelRecipes == 0) {
+ log("Failed to find enough space for all item outputs.");
+ return 0;
+ }
+ }
- // How many slots are free across all the output buses?
- int aInputBusSlotsFree = 0;
+ /* ========================================
+ * Fluid Management
+ * ========================================
+ */
- /*
- * Create Variables for Item Output
- */
+ if (aDoesOutputFluids) {
+ aParallelRecipes = canBufferOutputs(aFluidOutputs, aParallelRecipes);
+ }
- AutoMap<FlexiblePair<ItemStack, Integer>> aItemMap = new AutoMap<FlexiblePair<ItemStack, Integer>>();
- AutoMap<ItemStack> aOutputs = new AutoMap<ItemStack>(aItemOutputs);
+ return aParallelRecipes;
+ }
- for (final GT_MetaTileEntity_Hatch_OutputBus tBus : this.mOutputBusses) {
- if (!isValidMetaTileEntity(tBus)) {
- continue;
- }
- final IInventory tBusInv = tBus.getBaseMetaTileEntity();
- for (int i = 0; i < tBusInv.getSizeInventory(); i++) {
- if (tBus.getStackInSlot(i) == null) {
- aInputBusSlotsFree++;
- } else {
- ItemStack aT = tBus.getStackInSlot(i);
- int aSize = aT.stackSize;
- aT = aT.copy();
- aT.stackSize = 0;
- aItemMap.put(new FlexiblePair<ItemStack, Integer>(aT, aSize));
- }
- }
+ private int canBufferOutputs(ItemStack[] aItemOutputs, int aParallelRecipes) {
+ // the basic idea is to merge stacks as much as we can, and see how many vacant slots do we have left compared
+ // with the count of stacks to put.
+ // How many slots are free across all the output buses?
+ int aInputBusSlotsFree = 0;
+
+ // A map to hold the items we will be 'inputting' into the output buses. These itemstacks are actually the
+ // recipe outputs.
+ Map<ItemStack, Integer> aInputMap = new ItemStackMap<>();
+
+ // Iterate over the outputs, calculating require stack spacing they will require.
+ for (ItemStack aY : aItemOutputs) {
+ if (GT_Utility.isStackInvalid(aY)) {
+ continue;
}
+ aInputMap.merge(aY, aY.stackSize * aParallelRecipes, Integer::sum);
+ }
- // A map to hold the items we will be 'inputting' into the output buses. These itemstacks are actually the
- // recipe outputs.
- ConcurrentSet<FlexiblePair<ItemStack, Integer>> aInputMap =
- new ConcurrentHashSet<FlexiblePair<ItemStack, Integer>>();
+ if (aInputMap.isEmpty()) {
+ // nothing to output, bail early
+ return aParallelRecipes;
+ }
- // Iterate over the outputs, calculating require stack spacing they will require.
- for (int i = 0; i < aOutputs.size(); i++) {
- ItemStack aY = aOutputs.get(i);
- if (aY == null) {
- continue;
+ log("We have items to output.");
+
+ for (final GT_MetaTileEntity_Hatch_OutputBus tBus : this.mOutputBusses) {
+ if (!isValidMetaTileEntity(tBus)) {
+ continue;
+ }
+ final IInventory tBusInv = tBus.getBaseMetaTileEntity();
+ for (int i = 0; i < tBusInv.getSizeInventory(); i++) {
+ ItemStack tBusStack = tBus.getStackInSlot(i);
+ if (tBusStack == null) {
+ aInputBusSlotsFree++;
} else {
- int aStackSize = aY.stackSize * aParallelRecipes;
-
- int aSlotsNeedsForThisStack = (int) Math.ceil((float) aStackSize / aY.getMaxStackSize());
- // Should round up and add as many stacks as required nicely.
- for (int o = 0; o < aSlotsNeedsForThisStack; o++) {
- if (aStackSize < 1) break;
- int aStackToRemove = Math.min(aStackSize, aY.getMaxStackSize());
- aStackSize -= aStackToRemove;
- aY = aY.copy();
- aY.stackSize = 0;
- aInputMap.add(new FlexiblePair<ItemStack, Integer>(aY, aStackToRemove));
+ // get the real stack size
+ // we ignore the bus inventory stack limit here as no one set it to anything other than 64
+ int tMaxBusStackSize = tBusStack.getMaxStackSize();
+ if (tBusStack.stackSize >= tMaxBusStackSize)
+ // this bus stack is full. no checking
+ continue;
+ int tSpaceLeft = tMaxBusStackSize - tBusStack.stackSize;
+ Integer tOutputCountBoxed = aInputMap.get(tBusStack);
+ if (tOutputCountBoxed == null)
+ // we don't have a matching stack to output, ignore this bus stack
+ continue;
+ int tOutputCount = tOutputCountBoxed;
+ if (tOutputCount <= tSpaceLeft) {
+ // completely fits in this bus stack, remove this input stack
+ aInputMap.remove(tBusStack);
+ } else {
+ // have left over
+ aInputMap.put(tBusStack, tOutputCount - tSpaceLeft);
}
}
}
+ }
- // We have items to add to the output buses. See if any are not full stacks and see if we can make them
- // full.
- if (aInputMap.size() > 0) {
- // Iterate over the current stored items in the Output busses, if any match and are not full, we can try
- // account for merging.
- busItems:
- for (FlexiblePair<ItemStack, Integer> y : aItemMap) {
- // Iterate over the 'inputs', we can safely remove these as we go.
- outputItems:
- for (FlexiblePair<ItemStack, Integer> u : aInputMap) {
- // Create local vars for readability.
- ItemStack aOutputBusStack = y.getKey();
- ItemStack aOutputStack = u.getKey();
- // Stacks match, including NBT.
- if (GT_Utility.areStacksEqual(aOutputBusStack, aOutputStack, false)) {
- // Stack Matches, but it's full, continue.
- if (aOutputBusStack.stackSize >= 64) {
- // This stack is full, no point checking it.
- continue busItems;
- } else {
- // We can merge these two stacks without any hassle.
- if ((aOutputBusStack.stackSize + aOutputStack.stackSize) <= 64) {
- // Update the stack size in the bus storage map.
- y.setValue(aOutputBusStack.stackSize + aOutputStack.stackSize);
- // Remove the 'input' stack from the recipe outputs, so we don't try count it again.
- aInputMap.remove(u);
- continue outputItems;
- }
- // Stack merging is too much, so we fill this stack, leave the remainder.
- else {
- int aRemainder = (aOutputBusStack.stackSize + aOutputStack.stackSize) - 64;
- // Update the stack size in the bus storage map.
- y.setValue(64);
- // Create a new object to iterate over later, with the remainder data;
- FlexiblePair<ItemStack, Integer> t =
- new FlexiblePair<ItemStack, Integer>(u.getKey(), aRemainder);
- // Remove the 'input' stack from the recipe outputs, so we don't try count it again.
- aInputMap.remove(u);
- // Add the remainder stack.
- aInputMap.add(t);
- continue outputItems;
- }
- }
- } else {
- continue outputItems;
- }
- }
- }
+ // We have stacks that did not merge, do we have space for them?
+ if (aInputMap.size() > 0) {
+ int tTotalLeftStacks = aInputMap.entrySet().stream()
+ .mapToInt(GregtechMeta_MultiBlockBase::toStackCount)
+ .sum();
+ if (tTotalLeftStacks > aInputBusSlotsFree) {
+ aParallelRecipes = (int) Math.floor((double) aInputBusSlotsFree / tTotalLeftStacks * aParallelRecipes);
+ // We do not have enough free slots in total to accommodate the remaining managed stacks.
+ log(" Free: " + aInputBusSlotsFree + ", Required: " + aInputMap.size());
}
+ }
+ return aParallelRecipes;
+ }
- // We have stacks that did not merge, do we have space for them?
- if (aInputMap.size() > 0) {
- if (aInputMap.size() > aInputBusSlotsFree) {
- aParallelRecipes =
- (int) Math.floor((double) aInputBusSlotsFree / aInputMap.size() * aParallelRecipes);
- // We do not have enough free slots in total to accommodate the remaining managed stacks.
- log(" Free: " + aInputBusSlotsFree + ", Required: " + aInputMap.size());
- if (aParallelRecipes == 0) {
- log("Failed to find enough space for all item outputs.");
- return 0;
- }
- }
- }
+ private int canBufferOutputs(FluidStack[] aFluidOutputs, int aParallelRecipes) {
+ // the basic idea is to iterate over each output hatch one by one, prioritizing the locked hatches,
+ // and try to fill them with each of the fluid we have.
- /*
- * End Item Management
- */
+ // this algorithm can only determine if it works under current parallel
+ // it cannot figure out if a reduced parallel will not overflow
+ // make a copy of fluid left to output, since we cannot modify the original FluidStack[]
+ // use ArrayList as we will usually have less than 12 fluid to output (hopefully)
+ List<FluidStack> tFluidsLeft = new ArrayList<>(aFluidOutputs.length);
+ for (FluidStack aFluidOutput : aFluidOutputs) {
+ if (aFluidOutput == null) continue;
+ FluidStack copy = aFluidOutput.copy();
+ copy.amount *= aParallelRecipes;
+ tFluidsLeft.add(copy);
}
+ if (tFluidsLeft.isEmpty()) return aParallelRecipes;
- /* ========================================
- * Fluid Management
- * ========================================
- */
+ log("We have Fluids to output.");
- if (aDoesOutputFluids) {
- log("We have Fluids to output.");
- // How many slots are free across all the output buses?
- int aFluidHatches = 0;
- int aEmptyFluidHatches = 0;
- int aFullFluidHatches = 0;
- // Create Map for Fluid Output
- ArrayList<Triplet<GT_MetaTileEntity_Hatch_Output, FluidStack, Integer>> aOutputHatches =
- new ArrayList<Triplet<GT_MetaTileEntity_Hatch_Output, FluidStack, Integer>>();
- for (final GT_MetaTileEntity_Hatch_Output tBus : this.mOutputHatches) {
- if (!isValidMetaTileEntity(tBus)) {
- continue;
- }
- aFluidHatches++;
- // Map the Hatch with the space left for easy checking later.
- if (tBus.getFluid() == null) {
- aOutputHatches.add(new Triplet<GT_MetaTileEntity_Hatch_Output, FluidStack, Integer>(
- tBus, null, tBus.getCapacity()));
+ // go over restrictive hatches first
+ for (GT_MetaTileEntity_Hatch_Output tHatch : mOutputHatches) {
+ int tSpaceLeft = tHatch.getCapacity() - tHatch.getFluidAmount();
+
+ // check if hatch filled
+ if (tSpaceLeft <= 0) continue;
+
+ String tLockedFluidName = tHatch.getLockedFluidName();
+ // not restrictive hatch. leave for next pass
+ if (tHatch.mMode == 0) continue;
+
+ for (Iterator<FluidStack> iterator = tFluidsLeft.iterator(); iterator.hasNext(); ) {
+ FluidStack tFluidOutput = iterator.next();
+ if (GT_ModHandler.isSteam(tFluidOutput)) {
+ if (!tHatch.outputsSteam()) {
+ continue;
+ }
} else {
- int aSpaceLeft = tBus.getCapacity() - tBus.getFluidAmount();
- aOutputHatches.add(new Triplet<GT_MetaTileEntity_Hatch_Output, FluidStack, Integer>(
- tBus, tBus.getFluid(), aSpaceLeft));
- }
- }
- // Create a map of all the fluids we would like to output, we can iterate over this and see how many we can
- // merge into existing hatch stacks.
- ArrayList<FluidStack> aOutputFluids = new ArrayList<FluidStack>();
- // Ugly ass boxing
- aOutputFluids.addAll(new AutoMap<FluidStack>(aFluidOutputs));
- // Iterate the Hatches, updating their 'stored' data.
- // for (Triplet<GT_MetaTileEntity_Hatch_Output, FluidStack, Integer> aHatchData : aOutputHatches) {
- for (int i = 0; i < aOutputHatches.size(); i++) {
- // The Hatch Itself
- GT_MetaTileEntity_Hatch_Output aHatch = aOutputHatches.get(i).getValue_1();
- // Fluid in the Hatch
- FluidStack aHatchStack = aOutputHatches.get(i).getValue_2();
- // Fluid that the hatch is locked to
- String aHatchLockedFluid = aOutputHatches.get(i).getValue_1().getLockedFluidName();
- // Space left in Hatch
- int aSpaceLeftInHatch = aHatch.getCapacity() - aHatch.getFluidAmount();
- // Hatch is full,
- if (aSpaceLeftInHatch <= 0) {
- aFullFluidHatches++;
- aOutputHatches.remove(aOutputHatches.get(i));
- i--;
- continue;
+ if (!tHatch.outputsLiquids()) {
+ continue;
+ }
+ if (tHatch.isFluidLocked()
+ && tLockedFluidName != null
+ && !tLockedFluidName.equals(tFluidOutput.getFluid().getName())) {
+ continue;
+ }
}
- // Hatch has space
- else {
- // Check if any fluids match
- // aFluidMatch: for (FluidStack aOutputStack : aOutputFluids) {
- for (int j = 0; j < aOutputFluids.size(); j++) {
- // log(" aHatchStack "+aHatchStack.getLocalizedName()+" aOutput stack
- // "+aOutputStack.getLocalizedName());
- if (GT_Utility.areFluidsEqual(aHatchStack, aOutputFluids.get(j))
- && (aHatchLockedFluid == null
- || aHatchLockedFluid.equals(
- aOutputFluids.get(j).getFluid().getName()))) {
- int aFluidToPutIntoHatch = aOutputFluids.get(j).amount * aParallelRecipes;
- // Not Enough space to insert all of the fluid.
- // We fill this hatch and add a smaller Fluidstack back to the iterator.
- if (aSpaceLeftInHatch < aFluidToPutIntoHatch) {
- // Copy existing Hatch Stack
- FluidStack aNewHatchStack = aHatchStack.copy();
- aNewHatchStack.amount = 0;
- // Copy existing Hatch Stack again
- FluidStack aNewOutputStack = aHatchStack.copy();
- aNewOutputStack.amount = 0;
- // How much fluid do we have left after we fill the hatch?
- int aFluidLeftAfterInsert = aFluidToPutIntoHatch - aSpaceLeftInHatch;
- // Set new stacks to appropriate values
- aNewHatchStack.amount = aHatch.getCapacity();
- aNewOutputStack.amount = aFluidLeftAfterInsert;
- // Remove fluid from output list, merge success
- aOutputFluids.remove(aOutputFluids.get(j));
- j--;
- // Remove hatch from hatch list, data is now invalid.
- aOutputHatches.remove(aOutputHatches.get(i));
- i--;
- // Add remaining Fluid to Output list
- aOutputFluids.add(aNewOutputStack);
- // Re-add hatch to hatch list, with new data.
- // Triplet<GT_MetaTileEntity_Hatch_Output, FluidStack, Integer> aNewHatchData = new
- // Triplet<GT_MetaTileEntity_Hatch_Output, FluidStack, Integer>(aHatch, aNewHatchStack,
- // aNewHatchStack.amount);
- // aOutputHatches.add(aNewHatchData);
- break;
- }
- // We can fill this hatch perfectly (rare case), may as well add it directly to the full
- // list.
- else if (aSpaceLeftInHatch == aFluidToPutIntoHatch) {
- // Copy Old Stack
- FluidStack aNewHatchStack = aHatchStack.copy();
- // Add in amount from output stack
- aNewHatchStack.amount += aFluidToPutIntoHatch;
- // Remove fluid from output list, merge success
- aOutputFluids.remove(aOutputFluids.get(j));
- j--;
- // Remove hatch from hatch list, data is now invalid.
- aOutputHatches.remove(aOutputHatches.get(i));
- i--;
- // Re-add hatch to hatch list, with new data.
- Triplet<GT_MetaTileEntity_Hatch_Output, FluidStack, Integer> aNewHatchData =
- new Triplet<GT_MetaTileEntity_Hatch_Output, FluidStack, Integer>(
- aHatch, aNewHatchStack, aNewHatchStack.amount);
- aOutputHatches.add(aNewHatchData);
- break;
- }
- // We have more space than we need to merge, so we remove the stack from the output list and
- // update the hatch list.
- else {
- // Copy Old Stack
- FluidStack aNewHatchStack = aHatchStack.copy();
- // Add in amount from output stack
- aNewHatchStack.amount += aFluidToPutIntoHatch;
- // Remove fluid from output list, merge success
- aOutputFluids.remove(aOutputFluids.get(j));
- j--;
- // Remove hatch from hatch list, data is now invalid.
- aOutputHatches.remove(aOutputHatches.get(i));
- i--;
- // Re-add hatch to hatch list, with new data.
- Triplet<GT_MetaTileEntity_Hatch_Output, FluidStack, Integer> aNewHatchData =
- new Triplet<GT_MetaTileEntity_Hatch_Output, FluidStack, Integer>(
- aHatch, aNewHatchStack, aNewHatchStack.amount);
- aOutputHatches.add(aNewHatchData);
- // Check next fluid
- continue;
- }
-
- } else if (aHatchLockedFluid == null
- || aHatchLockedFluid.equals(
- aOutputFluids.get(j).getFluid().getName())) {
- aEmptyFluidHatches++;
- } else {
- continue;
- }
+ // this fluid is not prevented by restrictions on output hatch
+ if (tHatch.getFluidAmount() == 0 || GT_Utility.areFluidsEqual(tHatch.getFluid(), tFluidOutput)) {
+ // empty or same fluid - in any case, can accept
+ if (tSpaceLeft >= tFluidOutput.amount) {
+ // enough to hold all fluid
+ tSpaceLeft -= tFluidOutput.amount;
+ iterator.remove();
+ } else {
+ tFluidOutput.amount -= tSpaceLeft;
+ break;
}
}
}
+ // at this point we have either visited all output or is completed empty, so we can go over to next
+ // before that, check if we have handled all fluid, if yes, bail out for early exit.
+ if (tFluidsLeft.isEmpty()) break;
+ }
- for (Triplet<GT_MetaTileEntity_Hatch_Output, FluidStack, Integer> aFreeHatchCheck : aOutputHatches) {
- // Free Hatch
- if ((aFreeHatchCheck.getValue_2() == null
- || aFreeHatchCheck.getValue_3() == 0
- || aFreeHatchCheck.getValue_1().getFluid() == null)
- && !aFreeHatchCheck.getValue_1().isFluidLocked()) {
- aEmptyFluidHatches++;
- }
- }
+ // check non-restrictive hatches
+ for (GT_MetaTileEntity_Hatch_Output tHatch : mOutputHatches) {
+ int tSpaceLeft = tHatch.getCapacity() - tHatch.getFluidAmount();
- // We have Fluid Stacks we did not merge. Do we have space?
- log("fluids to output " + aOutputFluids.size() + " empty hatches " + aEmptyFluidHatches);
- if (aOutputFluids.size() > 0) {
- // Not enough space to add fluids.
- if (aOutputFluids.size() > aEmptyFluidHatches) {
- aParallelRecipes =
- (int) Math.floor((double) aEmptyFluidHatches / aOutputFluids.size() * aParallelRecipes);
- log("Failed to find enough space for all fluid outputs. Free: " + aEmptyFluidHatches
- + ", Required: " + aOutputFluids.size());
- return 0;
+ // check if hatch filled
+ if (tSpaceLeft <= 0) continue;
+
+ // restrictive hatch. done in last pass
+ if (tHatch.mMode != 0) continue;
+
+ for (Iterator<FluidStack> iterator = tFluidsLeft.iterator(); iterator.hasNext(); ) {
+ FluidStack tFluidOutput = iterator.next();
+ // these are not restrictive hatches, so no need to check other stuff
+ if (tHatch.getFluidAmount() == 0 || GT_Utility.areFluidsEqual(tHatch.getFluid(), tFluidOutput)) {
+ // empty or same fluid - in any case, can accept
+ if (tSpaceLeft >= tFluidOutput.amount) {
+ // enough to hold all fluid
+ tSpaceLeft -= tFluidOutput.amount;
+ iterator.remove();
+ } else {
+ tFluidOutput.amount -= tSpaceLeft;
+ break;
+ }
}
}
+ // at this point we have either visited all output or is completed empty, so go over to next
+ // before that, check if we have handled all fluid, if yes, bail out for early exit.
+ if (tFluidsLeft.isEmpty()) break;
+ }
- /*
- * End Fluid Management
- */
+ // We have Fluid Stacks we did not merge. Do we have space?
+ log("fluids to output " + tFluidsLeft.size());
+ if (!tFluidsLeft.isEmpty()) {
+ // Not enough space to add fluids.
+ log("Failed to find enough space for all fluid outputs. Fluids left: " + tFluidsLeft.size());
+ return 0;
}
+ /*
+ * End Fluid Management
+ */
return aParallelRecipes;
}
@@ -1182,7 +1083,7 @@ public abstract class GregtechMeta_MultiBlockBase<T extends GT_MetaTileEntity_En
tOutputItems = removeNulls(tOutputItems);
// Sanitize item stack size, splitting any stacks greater than max stack size
- List<ItemStack> splitStacks = new ArrayList<ItemStack>();
+ List<ItemStack> splitStacks = new ArrayList<>();
for (ItemStack tItem : tOutputItems) {
while (tItem.getMaxStackSize() < tItem.stackSize) {
ItemStack tmp = tItem.copy();
@@ -1199,7 +1100,7 @@ public abstract class GregtechMeta_MultiBlockBase<T extends GT_MetaTileEntity_En
}
// Strip empty stacks
- List<ItemStack> tSList = new ArrayList<ItemStack>();
+ List<ItemStack> tSList = new ArrayList<>();
for (ItemStack tS : tOutputItems) {
if (tS.stackSize > 0) tSList.add(tS);
}
@@ -1264,7 +1165,7 @@ public abstract class GregtechMeta_MultiBlockBase<T extends GT_MetaTileEntity_En
}
public GT_Recipe generateAdditionalOutputForRecipe(GT_Recipe aRecipe) {
- AutoMap<Integer> aNewChances = new AutoMap<Integer>();
+ AutoMap<Integer> aNewChances = new AutoMap<>();
for (int chance : aRecipe.mChances) {
aNewChances.put(boostOutput(chance));
}
@@ -1488,7 +1389,7 @@ public abstract class GregtechMeta_MultiBlockBase<T extends GT_MetaTileEntity_En
tOutputItems = removeNulls(tOutputItems);
// Sanitize item stack size, splitting any stacks greater than max stack size
- List<ItemStack> splitStacks = new ArrayList<ItemStack>();
+ List<ItemStack> splitStacks = new ArrayList<>();
for (ItemStack tItem : tOutputItems) {
while (tItem.getMaxStackSize() < tItem.stackSize) {
ItemStack tmp = tItem.copy();
@@ -1505,7 +1406,7 @@ public abstract class GregtechMeta_MultiBlockBase<T extends GT_MetaTileEntity_En
}
// Strip empty stacks
- List<ItemStack> tSList = new ArrayList<ItemStack>();
+ List<ItemStack> tSList = new ArrayList<>();
for (ItemStack tS : tOutputItems) {
if (tS.stackSize > 0) tSList.add(tS);
}
@@ -2162,12 +2063,12 @@ public abstract class GregtechMeta_MultiBlockBase<T extends GT_MetaTileEntity_En
/**
* This is the array Used to Store the Tectech Multi-Amp Dynamo hatches.
*/
- public ArrayList<GT_MetaTileEntity_Hatch> mTecTechDynamoHatches = new ArrayList<GT_MetaTileEntity_Hatch>();
+ public ArrayList<GT_MetaTileEntity_Hatch> mTecTechDynamoHatches = new ArrayList<>();
/**
* This is the array Used to Store the Tectech Multi-Amp Energy hatches.
*/
- public ArrayList<GT_MetaTileEntity_Hatch> mTecTechEnergyHatches = new ArrayList<GT_MetaTileEntity_Hatch>();
+ public ArrayList<GT_MetaTileEntity_Hatch> mTecTechEnergyHatches = new ArrayList<>();
/**
* TecTech Multi-Amp Dynamo Support