diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/generator/LargeTurbineWorkableHandler.java b/src/main/java/gregtech/common/metatileentities/multi/electric/generator/LargeTurbineWorkableHandler.java index 482d6c710b5..db414ae4da7 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/generator/LargeTurbineWorkableHandler.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/generator/LargeTurbineWorkableHandler.java @@ -1,6 +1,7 @@ package gregtech.common.metatileentities.multi.electric.generator; import gregtech.api.GTValues; +import gregtech.api.capability.IMultipleTankHandler; import gregtech.api.capability.IRotorHolder; import gregtech.api.capability.impl.MultiblockFuelRecipeLogic; import gregtech.api.metatileentity.multiblock.FuelMultiblockController; @@ -8,13 +9,20 @@ import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController; import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeBuilder; +import gregtech.api.recipes.RecipeMap; +import gregtech.api.util.GTUtility; +import net.minecraft.item.ItemStack; import net.minecraft.util.math.MathHelper; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.IFluidTank; import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.items.IItemHandlerModifiable; + +import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.stream.Collectors; public class LargeTurbineWorkableHandler extends MultiblockFuelRecipeLogic { @@ -42,7 +50,9 @@ protected void updateRecipeProgress() { public FluidStack getInputFluidStack() { // Previous Recipe is always null on first world load, so try to acquire a new recipe if (previousRecipe == null) { - Recipe recipe = findRecipe(Integer.MAX_VALUE, getInputInventory(), getInputTank()); + // previousRecipe is set whenever a valid recipe is found + // if it's not set, find *any* recipe we have at least the base (non-parallel) inputs for + Recipe recipe = super.findRecipe(Integer.MAX_VALUE, getInputInventory(), getInputTank()); return recipe == null ? null : getInputTank().drain( new FluidStack(recipe.getFluidInputs().get(0).getInputFluidStack().getFluid(), Integer.MAX_VALUE), @@ -73,6 +83,53 @@ protected long boostProduction(long production) { return 0; } + private int getParallel(Recipe recipe, double totalHolderEfficiencyCoefficient, int turbineMaxVoltage) { + return MathHelper.ceil((turbineMaxVoltage - this.excessVoltage) / + (Math.abs(recipe.getEUt()) * totalHolderEfficiencyCoefficient)); + } + + private boolean canDoRecipeWithParallel(Recipe recipe) { + IRotorHolder rotorHolder = ((MetaTileEntityLargeTurbine) metaTileEntity).getRotorHolder(); + if (rotorHolder == null || !rotorHolder.hasRotor()) + return false; + double totalHolderEfficiencyCoefficient = rotorHolder.getTotalEfficiency() / 100.0; + int turbineMaxVoltage = (int) getMaxVoltage(); + int parallel = getParallel(recipe, totalHolderEfficiencyCoefficient, turbineMaxVoltage); + + FluidStack recipeFluidStack = recipe.getFluidInputs().get(0).getInputFluidStack(); + + // Intentionally not using this.getInputFluidStack because that is locked to the previous recipe + FluidStack inputFluid = getInputTank().drain( + new FluidStack(recipeFluidStack.getFluid(), Integer.MAX_VALUE), + false); + return inputFluid != null && inputFluid.amount >= recipeFluidStack.amount * parallel; + } + + @Override + protected boolean checkPreviousRecipe() { + return super.checkPreviousRecipe() && canDoRecipeWithParallel(this.previousRecipe); + } + + @Override + protected @Nullable Recipe findRecipe(long maxVoltage, IItemHandlerModifiable inputs, + IMultipleTankHandler fluidInputs) { + RecipeMap map = getRecipeMap(); + if (map == null || !isRecipeMapValid(map)) { + return null; + } + + final List items = GTUtility.itemHandlerToList(inputs).stream().filter(s -> !s.isEmpty()).collect( + Collectors.toList()); + final List fluids = GTUtility.fluidHandlerToList(fluidInputs).stream() + .filter(f -> f != null && f.amount != 0) + .collect(Collectors.toList()); + + return map.find(items, fluids, recipe -> { + if (recipe.getEUt() > maxVoltage) return false; + return recipe.matches(false, inputs, fluidInputs) && this.canDoRecipeWithParallel(recipe); + }); + } + @Override protected boolean prepareRecipe(Recipe recipe) { IRotorHolder rotorHolder = ((MetaTileEntityLargeTurbine) metaTileEntity).getRotorHolder(); @@ -83,13 +140,12 @@ protected boolean prepareRecipe(Recipe recipe) { FluidStack recipeFluidStack = recipe.getFluidInputs().get(0).getInputFluidStack(); int parallel = 0; - if (excessVoltage >= turbineMaxVoltage) { - excessVoltage -= turbineMaxVoltage; + if (this.excessVoltage >= turbineMaxVoltage) { + this.excessVoltage -= turbineMaxVoltage; } else { double holderEfficiency = rotorHolder.getTotalEfficiency() / 100.0; // get the amount of parallel required to match the desired output voltage - parallel = MathHelper.ceil((turbineMaxVoltage - excessVoltage) / - (Math.abs(recipe.getEUt()) * holderEfficiency)); + parallel = getParallel(recipe, holderEfficiency, turbineMaxVoltage); // Null check fluid here, since it can return null on first join into world or first form FluidStack inputFluid = getInputFluidStack(); @@ -98,7 +154,7 @@ protected boolean prepareRecipe(Recipe recipe) { } // this is necessary to prevent over-consumption of fuel - excessVoltage += (int) (parallel * Math.abs(recipe.getEUt()) * holderEfficiency - turbineMaxVoltage); + this.excessVoltage += (int) (parallel * Math.abs(recipe.getEUt()) * holderEfficiency - turbineMaxVoltage); } // rebuild the recipe and adjust voltage to match the turbine