Skip to content

Commit d2db225

Browse files
Rework FuelRecipeLogic (#166)
* Rework FuelRecipeLogic * Fix JEI display for turbines * Try to address notifiable feedback * Some review feedback * Feedback changes
1 parent f81e7b2 commit d2db225

10 files changed

Lines changed: 151 additions & 31 deletions

File tree

src/main/java/gregtech/api/capability/IMultiblockController.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,8 @@
33
public interface IMultiblockController {
44

55
boolean isStructureFormed();
6+
7+
default boolean isStructureObstructed() {
8+
return false;
9+
}
610
}

src/main/java/gregtech/api/capability/impl/FuelRecipeLogic.java

Lines changed: 76 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import gregtech.api.metatileentity.MTETrait;
66
import gregtech.api.metatileentity.MetaTileEntity;
77
import gregtech.api.metatileentity.multiblock.MultiblockWithDisplayBase;
8+
import gregtech.api.multiblock.IMaintenance;
89
import gregtech.api.recipes.machines.FuelRecipeMap;
910
import gregtech.api.recipes.recipes.FuelRecipe;
1011
import gregtech.api.util.GTUtility;
@@ -35,6 +36,7 @@ public class FuelRecipeLogic extends MTETrait implements IControllable, IFuelabl
3536
private boolean isActive;
3637
private boolean workingEnabled = true;
3738
private boolean wasActiveAndNeedsUpdate = false;
39+
protected boolean invalidInputsForRecipes;
3840

3941
public FuelRecipeLogic(MetaTileEntity metaTileEntity, FuelRecipeMap recipeMap, Supplier<IEnergyContainer> energyContainer, Supplier<IMultipleTankHandler> fluidTank, long maxVoltage) {
4042
super(metaTileEntity);
@@ -108,20 +110,43 @@ public <T> T getCapability(Capability<T> capability) {
108110
return null;
109111
}
110112

113+
protected boolean hasNotifiedInputs() {
114+
return metaTileEntity.getNotifiedFluidInputList().size() > 0;
115+
}
116+
117+
protected boolean canWorkWithInputs() {
118+
// if the inputs were bad last time, check if they've changed before trying to find a new recipe.
119+
if (this.invalidInputsForRecipes && !hasNotifiedInputs()) return false;
120+
else {
121+
this.invalidInputsForRecipes = false;
122+
}
123+
return true;
124+
}
125+
111126
@Override
112127
public void update() {
113-
if (getMetaTileEntity().getWorld().isRemote) return;
128+
if (getMetaTileEntity().getWorld().isRemote) {
129+
return;
130+
}
131+
114132
if (workingEnabled) {
115133
if (recipeDurationLeft > 0) {
116-
if (energyContainer.get().getEnergyCanBeInserted() >=
117-
recipeOutputVoltage || shouldVoidExcessiveEnergy()) {
134+
//Check for if the full energy amount can be added to the output container, or if the energy should be voided
135+
//In addition, checks if the recipe should be canceled for any reason (Once per second)
136+
if ((energyContainer.get().getEnergyCanBeInserted() >= recipeOutputVoltage || shouldVoidExcessiveEnergy())
137+
&& (metaTileEntity.getOffsetTimer() % 20 == 0 && !isObstructed())) {
118138
energyContainer.get().addEnergy(recipeOutputVoltage);
139+
//If the recipe has finished, mark the machine as needing to be updated
119140
if (--this.recipeDurationLeft == 0) {
120141
this.wasActiveAndNeedsUpdate = true;
121142
}
122143
}
144+
else if(isObstructed()) {
145+
this.recipeDurationLeft = 0;
146+
this.wasActiveAndNeedsUpdate = true;
147+
}
123148
}
124-
if (recipeDurationLeft == 0 && isReadyForRecipes()) {
149+
if (recipeDurationLeft == 0 && isReadyForRecipes() && canWorkWithInputs()) {
125150
tryAcquireNewRecipe();
126151
}
127152
}
@@ -131,24 +156,50 @@ public void update() {
131156
}
132157
}
133158

159+
/**
160+
* Whether the multiblock can begin searching for new recipes once a recipe is completed.
161+
* This is called only when the multiblock begins searching for new recipes, not during the recipe progression.
162+
* This method will also cancel searching for recipes if there are too many maintenance issues.
163+
*
164+
* @return {@code true} if the multiblock should search for a new recipe
165+
*/
134166
protected boolean isReadyForRecipes() {
135-
return true;
167+
if (metaTileEntity instanceof IMaintenance) {
168+
169+
IMaintenance controller = (IMaintenance) metaTileEntity;
170+
171+
// do not run recipes when there are more than 5 maintenance problems
172+
if (controller.hasMaintenanceMechanics() && controller.getNumMaintenanceProblems() > 5) {
173+
return false;
174+
}
175+
}
176+
177+
return !isObstructed();
178+
}
179+
180+
/**
181+
* Whether the multiblock should cancel its recipe for any reason.
182+
* This will be checked every 20 update ticks, unlike {@link FuelRecipeLogic#isReadyForRecipes()}
183+
* Some examples of usage would be if a rotor or air intake is obstructed.
184+
*
185+
* @return {@code true} if the multiblock should cancel its recipe for any reason
186+
*/
187+
protected boolean isObstructed() {
188+
return false;
136189
}
137190

138191
protected boolean shouldVoidExcessiveEnergy() {
139192
return false;
140193
}
141194

195+
/**
196+
* Search the combined Fluid Inventory to find a valid fluid for running the power generation recipe.
197+
*/
142198
private void tryAcquireNewRecipe() {
143-
if (metaTileEntity instanceof MultiblockWithDisplayBase) {
144-
145-
MultiblockWithDisplayBase controller = (MultiblockWithDisplayBase) metaTileEntity;
146-
147-
// do not run recipes when there are more than 5 maintenance problems
148-
if (controller.hasMaintenanceMechanics() && controller.getNumMaintenanceProblems() > 5)
149-
return;
150-
}
151199

200+
// Set this here to avoid it being updated multiple time in the loop through the fluid tanks.
201+
// It will get reset if a valid recipe is found
202+
this.invalidInputsForRecipes = true;
152203
IMultipleTankHandler fluidTanks = this.fluidTank.get();
153204
for (IFluidTank fluidTank : fluidTanks) {
154205
FluidStack tankContents = fluidTank.getFluid();
@@ -164,15 +215,20 @@ private void tryAcquireNewRecipe() {
164215
if (controller.hasMufflerMechanics())
165216
controller.outputRecoveryItems();
166217

167-
// increase total on time
218+
// increase total multiblock active time
168219
controller.calculateMaintenance(previousRecipe.getDuration());
169220
}
170221
}
171222

223+
// If we have successfully found a recipe, update the variable before leaving the loop
224+
this.invalidInputsForRecipes = false;
172225
break; //recipe is found and ready to use
173226
}
174227
}
175228
}
229+
230+
// Clear notified Fluid input list, either after successfully finding a recipe, or failure to find a recipe
231+
metaTileEntity.getNotifiedFluidInputList().clear();
176232
}
177233

178234
public boolean isActive() {
@@ -181,9 +237,9 @@ public boolean isActive() {
181237

182238
private int tryAcquireNewRecipe(FluidStack fluidStack) {
183239
FuelRecipe currentRecipe;
184-
if (previousRecipe != null && previousRecipe.matches(getMaxVoltage(), fluidStack)) {
240+
if (this.previousRecipe != null && this.previousRecipe.matches(getMaxVoltage(), fluidStack)) {
185241
//if previous recipe still matches inputs, try to use it
186-
currentRecipe = previousRecipe;
242+
currentRecipe = this.previousRecipe;
187243
} else {
188244
//else, try searching new recipe for given inputs
189245
currentRecipe = recipeMap.findRecipe(getMaxVoltage(), fluidStack);
@@ -192,9 +248,13 @@ private int tryAcquireNewRecipe(FluidStack fluidStack) {
192248
this.previousRecipe = currentRecipe;
193249
}
194250
}
251+
252+
//Check if we have found a valid recipe
195253
if (currentRecipe != null && checkRecipe(currentRecipe)) {
196254
int fuelAmountToUse = calculateFuelAmount(currentRecipe);
255+
//Check if we have the required amount of fuel, and optionally boosters
197256
if (fluidStack.amount >= fuelAmountToUse) {
257+
//Initialize the required variables. This is basically setupRecipe in AbstractRecipeLogic, just condensed
198258
this.recipeDurationLeft = calculateRecipeDuration(currentRecipe);
199259
this.recipeOutputVoltage = startRecipe(currentRecipe, fuelAmountToUse, recipeDurationLeft);
200260
if (wasActiveAndNeedsUpdate) {

src/main/java/gregtech/api/multiblock/IMaintenance.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,6 @@ public interface IMaintenance {
1111
void setMaintenanceFixed(int index);
1212

1313
void storeTaped(boolean isTaped);
14+
15+
boolean hasMaintenanceMechanics();
1416
}

src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityRotorHolder.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ public boolean isFrontFaceFree() {
108108

109109
private boolean checkTurbineFaceFree() {
110110
EnumFacing facing = getFrontFacing();
111+
//TODO, this also needs to check Y for freedom wrench implementation
111112
boolean permuteXZ = facing.getAxis() == Axis.Z;
112113
BlockPos centerPos = getPos().offset(facing);
113114
for (int x = -1; x < 2; x++) {

src/main/java/gregtech/common/metatileentities/multi/electric/generator/LargeCombustionEngineWorkableHandler.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@
44
import gregtech.api.capability.IMultipleTankHandler;
55
import gregtech.api.capability.impl.FuelRecipeLogic;
66
import gregtech.api.metatileentity.MetaTileEntity;
7+
import gregtech.api.metatileentity.multiblock.MultiblockWithDisplayBase;
78
import gregtech.api.recipes.machines.FuelRecipeMap;
89
import gregtech.api.recipes.recipes.FuelRecipe;
910
import gregtech.api.unification.material.Materials;
11+
import net.minecraft.block.state.IBlockState;
1012
import net.minecraft.nbt.NBTTagCompound;
13+
import net.minecraft.util.EnumFacing;
14+
import net.minecraft.util.math.BlockPos;
1115
import net.minecraftforge.fluids.FluidStack;
1216

1317
import java.util.function.Supplier;
@@ -34,6 +38,7 @@ public FluidStack getFuelStack() {
3438
protected boolean checkRecipe(FuelRecipe recipe) {
3539
FluidStack lubricantStack = Materials.Lubricant.getFluid(2);
3640
FluidStack drainStack = fluidTank.get().drain(lubricantStack, false);
41+
//TODO, shouldn't this be &&?
3742
return (drainStack != null && drainStack.amount >= 2) || currentCycle < maxCycleLength;
3843
}
3944

@@ -71,4 +76,35 @@ public void deserializeNBT(NBTTagCompound compound) {
7176
super.deserializeNBT(compound);
7277
this.currentCycle = compound.getInteger("Cycle");
7378
}
79+
80+
@Override
81+
protected boolean isObstructed() {
82+
return checkIntakesObstructed();
83+
}
84+
85+
private boolean checkIntakesObstructed() {
86+
if(this.metaTileEntity instanceof MultiblockWithDisplayBase) {
87+
MultiblockWithDisplayBase controller = (MultiblockWithDisplayBase) this.metaTileEntity;
88+
89+
EnumFacing facing = controller.getFrontFacing();
90+
//TODO, this also needs to check Y for freedom wrench implementation
91+
boolean permuteXZ = facing.getAxis() == EnumFacing.Axis.Z;
92+
BlockPos centerPos = controller.getPos().offset(facing);
93+
for (int x = -1; x < 2; x++) {
94+
for (int y = -1; y < 2; y++) {
95+
//Skip the controller block itself
96+
if(x == 0 && y == 0) {
97+
continue;
98+
}
99+
BlockPos blockPos = centerPos.add(permuteXZ ? x : 0, y, permuteXZ ? 0 : x);
100+
IBlockState blockState = controller.getWorld().getBlockState(blockPos);
101+
if (!blockState.getBlock().isAir(blockState, controller.getWorld(), blockPos)) {
102+
return true;
103+
}
104+
}
105+
}
106+
}
107+
108+
return false;
109+
}
74110
}

src/main/java/gregtech/common/metatileentities/multi/electric/generator/LargeTurbineWorkableHandler.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public long getMaxVoltage() {
7979
@Override
8080
protected boolean isReadyForRecipes() {
8181
MetaTileEntityRotorHolder rotorHolder = largeTurbine.getAbilities(MultiblockAbility.ABILITY_ROTOR_HOLDER).get(0);
82-
return rotorHolder.isHasRotor();
82+
return rotorHolder.isHasRotor() && super.isReadyForRecipes();
8383
}
8484

8585
@Override
@@ -145,4 +145,9 @@ public void deserializeNBT(NBTTagCompound compound) {
145145
protected boolean shouldVoidExcessiveEnergy() {
146146
return true;
147147
}
148+
149+
@Override
150+
protected boolean isObstructed() {
151+
return !largeTurbine.isRotorFaceFree();
152+
}
148153
}

src/main/java/gregtech/common/metatileentities/multi/electric/generator/MetaTileEntityLargeCombustionEngine.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import gregtech.api.metatileentity.multiblock.IMultiblockPart;
88
import gregtech.api.metatileentity.multiblock.MultiblockAbility;
99
import gregtech.api.multiblock.BlockPattern;
10-
import gregtech.api.multiblock.BlockWorldState;
1110
import gregtech.api.multiblock.FactoryBlockPattern;
1211
import gregtech.api.recipes.RecipeMaps;
1312
import gregtech.api.render.ICubeRenderer;
@@ -21,12 +20,13 @@
2120
import net.minecraft.block.state.IBlockState;
2221
import net.minecraft.util.ResourceLocation;
2322
import net.minecraft.util.text.ITextComponent;
23+
import net.minecraft.util.text.Style;
2424
import net.minecraft.util.text.TextComponentTranslation;
25+
import net.minecraft.util.text.TextFormatting;
2526
import net.minecraftforge.fluids.FluidStack;
2627

2728
import javax.annotation.Nonnull;
2829
import java.util.List;
29-
import java.util.function.Predicate;
3030

3131
public class MetaTileEntityLargeCombustionEngine extends FueledMultiblockController {
3232

@@ -64,20 +64,15 @@ protected void addDisplayText(List<ITextComponent> textList) {
6464
textList.add(new TextComponentTranslation("gregtech.multiblock.large_combustion_engine.fuel_amount", fuelAmount, fuelName));
6565
textList.add(new TextComponentTranslation("gregtech.multiblock.large_combustion_engine.oxygen_amount", oxygenAmount));
6666
textList.add(new TextComponentTranslation(oxygenAmount >= 2 ? "gregtech.multiblock.large_combustion_engine.oxygen_boosted" : "gregtech.multiblock.large_combustion_engine.supply_oxygen_to_boost"));
67+
68+
if(isStructureObstructed()) {
69+
textList.add(new TextComponentTranslation("gregtech.multiblock.turbine.obstructed")
70+
.setStyle(new Style().setColor(TextFormatting.RED)));
71+
}
6772
}
6873
super.addDisplayText(textList);
6974
}
7075

71-
protected Predicate<BlockWorldState> intakeCasingPredicate() {
72-
IBlockState blockState = MetaBlocks.MULTIBLOCK_CASING.getState(MultiblockCasingType.ENGINE_INTAKE_CASING);
73-
return blockWorldState -> {
74-
if (blockWorldState.getBlockState() != blockState)
75-
return false;
76-
IBlockState offsetState = blockWorldState.getOffsetState(getFrontFacing());
77-
return offsetState.getBlock().isAir(offsetState, blockWorldState.getWorld(), blockWorldState.getPos());
78-
};
79-
}
80-
8176
@Override
8277
protected BlockPattern createStructurePattern() {
8378
return FactoryBlockPattern.start()
@@ -89,7 +84,7 @@ protected BlockPattern createStructurePattern() {
8984
.where('G', statePredicate(MetaBlocks.TURBINE_CASING.getState(TurbineCasingType.TITANIUM_GEARBOX)))
9085
.where('C', statePredicate(getCasingState()).or(abilityPartPredicate(ALLOWED_ABILITIES)))
9186
.where('D', abilityPartPredicate(MultiblockAbility.OUTPUT_ENERGY))
92-
.where('A', intakeCasingPredicate())
87+
.where('A', statePredicate(MetaBlocks.MULTIBLOCK_CASING.getState(MultiblockCasingType.ENGINE_INTAKE_CASING)))
9388
.where('Y', selfPredicate())
9489
.build();
9590
}
@@ -113,4 +108,9 @@ protected OrientedOverlayRenderer getFrontOverlay() {
113108
public boolean hasMufflerMechanics() {
114109
return true;
115110
}
111+
112+
@Override
113+
public boolean isStructureObstructed() {
114+
return ((LargeCombustionEngineWorkableHandler) workableHandler).isObstructed();
115+
}
116116
}

src/main/java/gregtech/common/metatileentities/multi/electric/generator/MetaTileEntityLargeTurbine.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,4 +190,9 @@ protected OrientedOverlayRenderer getFrontOverlay() {
190190
public boolean hasMufflerMechanics() {
191191
return turbineType.hasMufflerHatch;
192192
}
193+
194+
@Override
195+
public boolean isStructureObstructed() {
196+
return !isRotorFaceFree();
197+
}
193198
}

src/main/java/gregtech/integration/theoneprobe/provider/MultiblockInfoProvider.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,14 @@ protected Capability<IMultiblockController> getCapability() {
1919
@Override
2020
protected void addProbeInfo(IMultiblockController capability, IProbeInfo probeInfo, TileEntity tileEntity, EnumFacing sideHit) {
2121
IProbeInfo horizontalPane = probeInfo.horizontal(probeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER));
22-
if (capability.isStructureFormed())
22+
if (capability.isStructureFormed()) {
2323
horizontalPane.text(TextStyleClass.INFO + "{*gregtech.top.valid_structure*}");
24+
if(capability.isStructureObstructed()) {
25+
IProbeInfo horizontalPaneObstructed = probeInfo.horizontal(probeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER));
26+
horizontalPaneObstructed.text(TextStyleClass.INFO + "{*gregtech.top.obstructed_structure*}");
27+
}
28+
29+
}
2430
else
2531
horizontalPane.text(TextStyleClass.INFO + "{*gregtech.top.invalid_structure*}");
2632
}

src/main/resources/assets/gregtech/lang/en_us.lang

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ gregtech.top.fuel_none=No fuel
4040

4141
gregtech.top.invalid_structure=§cInvalid Structure
4242
gregtech.top.valid_structure=§aStructure Formed
43+
gregtech.top.obstructed_structure=§cStructure Obstructed
4344

4445
gregtech.multiblock.title=Multiblock Pattern
4546
gregtech.multiblock.primitive_blast_furnace.description=The Primitive Blast Furnace (PBF) is a multiblock structure used for cooking steel in the early game. Although not very fast, it will provide you with steel for your first setups.

0 commit comments

Comments
 (0)