Skip to content

Commit

Permalink
Sub-tick OC and long EUt in recipe logic (GregTechCEu#2432)
Browse files Browse the repository at this point in the history
  • Loading branch information
TechLord22 authored Jul 26, 2024
1 parent bee5a11 commit e0a7e53
Show file tree
Hide file tree
Showing 50 changed files with 1,455 additions and 623 deletions.
346 changes: 218 additions & 128 deletions src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java

Large diffs are not rendered by default.

51 changes: 30 additions & 21 deletions src/main/java/gregtech/api/capability/impl/BoilerRecipeLogic.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import gregtech.api.recipes.category.ICategoryOverride;
import gregtech.api.unification.material.Materials;
import gregtech.api.util.GTLog;
import gregtech.api.util.GTUtility;
import gregtech.common.ConfigHolder;
import gregtech.common.metatileentities.multi.MetaTileEntityLargeBoiler;

Expand All @@ -17,7 +18,11 @@
import net.minecraft.network.PacketBuffer;
import net.minecraft.tileentity.TileEntityFurnace;
import net.minecraft.util.NonNullList;
import net.minecraftforge.fluids.*;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidUtil;
import net.minecraftforge.fluids.IFluidTank;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.IItemHandlerModifiable;

Expand All @@ -32,14 +37,16 @@

public class BoilerRecipeLogic extends AbstractRecipeLogic implements ICategoryOverride {

private static final long STEAM_PER_WATER = 160;
private static final int STEAM_PER_WATER = 160;

private static final int FLUID_DRAIN_MULTIPLIER = 100;
private static final int FLUID_BURNTIME_TO_EU = 800 / FLUID_DRAIN_MULTIPLIER;

private int currentHeat;
private int lastTickSteamOutput;
private int excessWater, excessFuel, excessProjectedEU;
private int excessWater;
private int excessFuel;
private int excessProjectedEU;

public BoilerRecipeLogic(MetaTileEntityLargeBoiler tileEntity) {
super(tileEntity, null);
Expand Down Expand Up @@ -88,7 +95,8 @@ protected void trySearchNewRecipe() {
fluidTank.drain(dieselRecipe.getFluidInputs().get(0).getAmount() * FLUID_DRAIN_MULTIPLIER, true);
// divide by 2, as it is half burntime for combustion
setMaxProgress(adjustBurnTimeForThrottle(Math.max(1, boiler.boilerType.runtimeBoost(
(Math.abs(dieselRecipe.getEUt()) * dieselRecipe.getDuration()) / FLUID_BURNTIME_TO_EU / 2))));
GTUtility.safeCastLongToInt((Math.abs(dieselRecipe.getEUt()) * dieselRecipe.getDuration()) /
FLUID_BURNTIME_TO_EU / 2)))));
didStartRecipe = true;
break;
}
Expand All @@ -101,8 +109,10 @@ protected void trySearchNewRecipe() {
fluidTank.drain(denseFuelRecipe.getFluidInputs().get(0).getAmount() * FLUID_DRAIN_MULTIPLIER, true);
// multiply by 2, as it is 2x burntime for semi-fluid
setMaxProgress(adjustBurnTimeForThrottle(
Math.max(1, boiler.boilerType.runtimeBoost((Math.abs(denseFuelRecipe.getEUt()) *
denseFuelRecipe.getDuration() / FLUID_BURNTIME_TO_EU * 2)))));
Math.max(1,
boiler.boilerType
.runtimeBoost(GTUtility.safeCastLongToInt((Math.abs(denseFuelRecipe.getEUt()) *
denseFuelRecipe.getDuration() / FLUID_BURNTIME_TO_EU * 2))))));
didStartRecipe = true;
break;
}
Expand Down Expand Up @@ -142,14 +152,15 @@ protected void trySearchNewRecipe() {
@Override
protected void updateRecipeProgress() {
if (canRecipeProgress) {
int generatedSteam = this.recipeEUt * getMaximumHeatFromMaintenance() / getMaximumHeat();
int generatedSteam = GTUtility
.safeCastLongToInt(this.recipeEUt * getMaximumHeatFromMaintenance() / getMaximumHeat());
if (generatedSteam > 0) {
long amount = (generatedSteam + STEAM_PER_WATER) / STEAM_PER_WATER;
int amount = (generatedSteam + STEAM_PER_WATER) / STEAM_PER_WATER;
excessWater += amount * STEAM_PER_WATER - generatedSteam;
amount -= excessWater / STEAM_PER_WATER;
excessWater %= STEAM_PER_WATER;

FluidStack drainedWater = getBoilerFluidFromContainer(getInputTank(), (int) amount);
FluidStack drainedWater = getBoilerFluidFromContainer(getInputTank(), amount);
if (amount != 0 && (drainedWater == null || drainedWater.amount < amount)) {
getMetaTileEntity().explodeMultiblock((1.0f * currentHeat / getMaximumHeat()) * 8.0f);
} else {
Expand All @@ -176,15 +187,15 @@ private int getMaximumHeatFromMaintenance() {

private int adjustEUtForThrottle(int rawEUt) {
int throttle = ((MetaTileEntityLargeBoiler) metaTileEntity).getThrottle();
return Math.max(25, (int) (rawEUt * (throttle / 100.0)));
return (int) Math.max(25, rawEUt * (throttle / 100.0));
}

private int adjustBurnTimeForThrottle(int rawBurnTime) {
MetaTileEntityLargeBoiler boiler = (MetaTileEntityLargeBoiler) metaTileEntity;
int EUt = boiler.boilerType.steamPerTick();
int adjustedEUt = adjustEUtForThrottle(EUt);
int adjustedBurnTime = rawBurnTime * EUt / adjustedEUt;
this.excessProjectedEU += EUt * rawBurnTime - adjustedEUt * adjustedBurnTime;
this.excessProjectedEU += (EUt * rawBurnTime) - (adjustedEUt * adjustedBurnTime);
adjustedBurnTime += this.excessProjectedEU / adjustedEUt;
this.excessProjectedEU %= adjustedEUt;
return adjustedBurnTime;
Expand All @@ -211,13 +222,13 @@ public int getLastTickSteam() {

public void setLastTickSteam(int lastTickSteamOutput) {
if (lastTickSteamOutput != this.lastTickSteamOutput && !metaTileEntity.getWorld().isRemote) {
writeCustomData(BOILER_LAST_TICK_STEAM, b -> b.writeVarInt(lastTickSteamOutput));
writeCustomData(BOILER_LAST_TICK_STEAM, b -> b.writeInt(lastTickSteamOutput));
}
this.lastTickSteamOutput = lastTickSteamOutput;
}

@Override
public int getInfoProviderEUt() {
public long getInfoProviderEUt() {
return this.lastTickSteamOutput;
}

Expand All @@ -226,11 +237,9 @@ public boolean consumesEnergy() {
return false;
}

@Override
public void invalidate() {
progressTime = 0;
maxProgressTime = 0;
recipeEUt = 0;
setActive(false);
super.invalidate();
setLastTickSteam(0);
}

Expand Down Expand Up @@ -272,14 +281,14 @@ public void deserializeNBT(@NotNull NBTTagCompound compound) {
public void writeInitialSyncData(@NotNull PacketBuffer buf) {
super.writeInitialSyncData(buf);
buf.writeVarInt(currentHeat);
buf.writeVarInt(lastTickSteamOutput);
buf.writeInt(lastTickSteamOutput);
}

@Override
public void receiveInitialSyncData(@NotNull PacketBuffer buf) {
super.receiveInitialSyncData(buf);
this.currentHeat = buf.readVarInt();
this.lastTickSteamOutput = buf.readVarInt();
this.lastTickSteamOutput = buf.readInt();
}

@Override
Expand All @@ -288,7 +297,7 @@ public void receiveCustomData(int dataId, @NotNull PacketBuffer buf) {
if (dataId == BOILER_HEAT) {
this.currentHeat = buf.readVarInt();
} else if (dataId == BOILER_LAST_TICK_STEAM) {
this.lastTickSteamOutput = buf.readVarInt();
this.lastTickSteamOutput = buf.readInt();
}
}

Expand All @@ -313,7 +322,7 @@ protected long getEnergyCapacity() {
}

@Override
protected boolean drawEnergy(int recipeEUt, boolean simulate) {
protected boolean drawEnergy(long recipeEUt, boolean simulate) {
GTLog.logger.error("Large Boiler called drawEnergy(), this should not be possible!");
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public boolean checkRecipe(@NotNull Recipe recipe) {
}

@Override
protected void setupRecipe(Recipe recipe) {
protected void setupRecipe(@NotNull Recipe recipe) {
super.setupRecipe(recipe);
this.recipeCWUt = recipe.getProperty(ComputationProperty.getInstance(), 0);
this.isDurationTotalCWU = recipe.hasProperty(TotalComputationProperty.getInstance());
Expand Down
12 changes: 2 additions & 10 deletions src/main/java/gregtech/api/capability/impl/EUToFEProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

import org.jetbrains.annotations.NotNull;

import static gregtech.api.util.GTUtility.safeCastLongToInt;

public class EUToFEProvider extends CapabilityCompatProvider {

/**
Expand Down Expand Up @@ -210,14 +212,4 @@ public boolean isOneProbeHidden() {
return true;
}
}

/**
* Safely cast a Long to an Int without overflow.
*
* @param v The Long value to cast to an Int.
* @return v, casted to Int, or Integer.MAX_VALUE if it would overflow.
*/
public static int safeCastLongToInt(long v) {
return v > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) v;
}
}
13 changes: 8 additions & 5 deletions src/main/java/gregtech/api/capability/impl/FuelRecipeLogic.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@
import gregtech.api.metatileentity.MetaTileEntity;
import gregtech.api.metatileentity.multiblock.ParallelLogicType;
import gregtech.api.recipes.RecipeMap;
import gregtech.api.recipes.logic.OCParams;
import gregtech.api.recipes.logic.OCResult;
import gregtech.api.recipes.recipeproperties.IRecipePropertyStorage;

import org.jetbrains.annotations.NotNull;

import java.util.function.Supplier;

import static gregtech.api.recipes.logic.OverclockingLogic.standardOC;

public class FuelRecipeLogic extends RecipeLogicEnergy {

public FuelRecipeLogic(MetaTileEntity tileEntity, RecipeMap<?> recipeMap,
Expand All @@ -29,16 +33,15 @@ public boolean consumesEnergy() {
}

@Override
protected boolean hasEnoughPower(@NotNull int[] resultOverclock) {
protected boolean hasEnoughPower(long eut, int duration) {
// generators always have enough power to run recipes
return true;
}

@Override
protected void modifyOverclockPost(int[] overclockResults, @NotNull IRecipePropertyStorage storage) {
super.modifyOverclockPost(overclockResults, storage);
// make EUt negative so it is consumed
overclockResults[0] = -overclockResults[0];
protected void runOverclockingLogic(@NotNull OCParams ocParams, @NotNull OCResult ocResult,
@NotNull IRecipePropertyStorage propertyStorage, long maxVoltage) {
standardOC(ocParams, ocResult, maxVoltage, getOverclockingDurationFactor(), getOverclockingVoltageFactor());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import gregtech.api.capability.IHeatingCoil;
import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController;
import gregtech.api.recipes.logic.OCParams;
import gregtech.api.recipes.logic.OCResult;
import gregtech.api.recipes.logic.OverclockingLogic;
import gregtech.api.recipes.recipeproperties.IRecipePropertyStorage;
import gregtech.api.recipes.recipeproperties.TemperatureProperty;

import org.jetbrains.annotations.NotNull;

import static gregtech.api.recipes.logic.OverclockingLogic.heatingCoilOverclockingLogic;
import static gregtech.api.recipes.logic.OverclockingLogic.heatingCoilOC;

/**
* RecipeLogic for multiblocks that use temperature for raising speed and lowering energy usage
Expand All @@ -24,24 +26,18 @@ public HeatingCoilRecipeLogic(RecipeMapMultiblockController metaTileEntity) {
}

@Override
protected void modifyOverclockPre(@NotNull int[] values, @NotNull IRecipePropertyStorage storage) {
super.modifyOverclockPre(values, storage);
protected void modifyOverclockPre(@NotNull OCParams ocParams, @NotNull IRecipePropertyStorage storage) {
super.modifyOverclockPre(ocParams, storage);
// coil EU/t discount
values[0] = OverclockingLogic.applyCoilEUtDiscount(values[0],
ocParams.setEut(OverclockingLogic.applyCoilEUtDiscount(ocParams.eut(),
((IHeatingCoil) metaTileEntity).getCurrentTemperature(),
storage.getRecipePropertyValue(TemperatureProperty.getInstance(), 0));
storage.getRecipePropertyValue(TemperatureProperty.getInstance(), 0)));
}

@NotNull
@Override
protected int[] runOverclockingLogic(@NotNull IRecipePropertyStorage propertyStorage, int recipeEUt,
long maxVoltage, int duration, int amountOC) {
return heatingCoilOverclockingLogic(
Math.abs(recipeEUt),
maxVoltage,
duration,
amountOC,
((IHeatingCoil) metaTileEntity).getCurrentTemperature(),
protected void runOverclockingLogic(@NotNull OCParams ocParams, @NotNull OCResult ocResult,
@NotNull IRecipePropertyStorage propertyStorage, long maxVoltage) {
heatingCoilOC(ocParams, ocResult, maxVoltage, ((IHeatingCoil) metaTileEntity).getCurrentTemperature(),
propertyStorage.getRecipePropertyValue(TemperatureProperty.getInstance(), 0));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
import gregtech.api.metatileentity.multiblock.ParallelLogicType;
import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController;
import gregtech.api.recipes.Recipe;
import gregtech.api.recipes.logic.OCParams;
import gregtech.api.recipes.logic.OCResult;
import gregtech.api.recipes.recipeproperties.IRecipePropertyStorage;
import gregtech.api.util.GTUtility;
import gregtech.api.util.TextFormattingUtil;

import net.minecraft.util.Tuple;
Expand All @@ -26,28 +29,25 @@ public MultiblockFuelRecipeLogic(RecipeMapMultiblockController tileEntity) {
}

@Override
protected void modifyOverclockPre(@NotNull int[] values, @NotNull IRecipePropertyStorage storage) {
protected void modifyOverclockPre(@NotNull OCParams ocParams, @NotNull IRecipePropertyStorage storage) {
// apply maintenance bonuses
Tuple<Integer, Double> maintenanceValues = getMaintenanceValues();

// duration bonus
if (maintenanceValues.getSecond() != 1.0) {
values[1] = (int) Math.round(values[1] / maintenanceValues.getSecond());
ocParams.setDuration((int) Math.round(ocParams.duration() / maintenanceValues.getSecond()));
}
}

@Override
protected void modifyOverclockPost(int[] overclockResults, @NotNull IRecipePropertyStorage storage) {
protected void modifyOverclockPost(@NotNull OCResult ocResult, @NotNull IRecipePropertyStorage storage) {
// apply maintenance penalties
Tuple<Integer, Double> maintenanceValues = getMaintenanceValues();

// duration penalty
if (maintenanceValues.getFirst() > 0) {
overclockResults[1] = (int) (overclockResults[1] * (1 - 0.1 * maintenanceValues.getFirst()));
ocResult.setDuration((int) (ocResult.duration() * (1 - 0.1 * maintenanceValues.getFirst())));
}

// make EUt negative so it is consumed
overclockResults[0] = -overclockResults[0];
}

@NotNull
Expand All @@ -57,7 +57,7 @@ public ParallelLogicType getParallelLogicType() {
}

@Override
protected boolean hasEnoughPower(@NotNull int[] resultOverclock) {
protected boolean hasEnoughPower(long eut, int duration) {
// generators always have enough power to run recipes
return true;
}
Expand Down Expand Up @@ -95,18 +95,19 @@ protected long boostProduction(long production) {
}

@Override
protected boolean drawEnergy(int recipeEUt, boolean simulate) {
protected boolean drawEnergy(long recipeEUt, boolean simulate) {
long euToDraw = boostProduction(recipeEUt);
long resultEnergy = getEnergyStored() - euToDraw;
if (resultEnergy >= 0L && resultEnergy <= getEnergyCapacity()) {
if (!simulate) getEnergyContainer().changeEnergy(-euToDraw);
return true;
} else return false;
}
return false;
}

@Override
public int getInfoProviderEUt() {
return (int) boostProduction(super.getInfoProviderEUt());
public long getInfoProviderEUt() {
return boostProduction(super.getInfoProviderEUt());
}

@Override
Expand Down Expand Up @@ -138,10 +139,10 @@ public String getRecipeFluidInputInfo() {
}
FluidStack requiredFluidInput = recipe.getFluidInputs().get(0).getInputFluidStack();

int ocAmount = (int) (getMaxVoltage() / recipe.getEUt());
int ocAmount = GTUtility.safeCastLongToInt(getMaxVoltage() / recipe.getEUt());
int neededAmount = ocAmount * requiredFluidInput.amount;
if (rotorHolder != null && rotorHolder.hasRotor()) {
neededAmount /= (rotorHolder.getTotalEfficiency() / 100f);
neededAmount /= (rotorHolder.getTotalEfficiency() / 100.0);
} else if (rotorHolder != null && !rotorHolder.hasRotor()) {
return null;
}
Expand Down
Loading

0 comments on commit e0a7e53

Please sign in to comment.