Merge pull request #196 from Daniel366Cobra/qol-tweaks-blast-furnace

Blast furnace QoL tweak
This commit is contained in:
DrMangoTea
2025-07-02 20:34:19 +02:00
committed by GitHub
4 changed files with 133 additions and 15 deletions

View File

@@ -465,6 +465,9 @@
"create.fe": "%1$s :ƎℲ",
"create.goggles.ammeter": ":ɹǝʇǝɯɯⱯ",
"create.goggles.ammeter.amps": "Λ %1$s :sdɯⱯ pǝɹnsɐǝW ",
"create.goggles.blast_furnace.batch_header": ":oıʇɐᴚ ɥɔʇɐᗺ ʇןǝɯS",
"create.goggles.blast_furnace.batch_ratio": ")xnןℲ:ǝɹO:ןǝnℲ( %s:%s:%s",
"create.goggles.blast_furnace.batch_warning": "˙ǝzıs ɥɔʇɐq ǝbɹɐꞀ :buıuɹɐM",
"create.goggles.blast_furnace.fuel_amount": "%1$s : ןǝnℲ ",
"create.goggles.blast_furnace.height": "%1$s :ʇɥbıǝH ",
"create.goggles.blast_furnace.modifier": "%1$s :ǝɯı⟘ uoıʇɔnpoɹԀ",
@@ -1062,4 +1065,4 @@
"tfmg.ponder.tag.oil_processing.description": "ןıo buıuıɯ puɐ buıuıɟǝɹ ɹoɟ pǝsn ʞɔoןᗺ",
"tfmg.subtitle.diesel_engine_sounds": "spunoS ǝuıbuƎ ןǝsǝıᗡ",
"tfmg.subtitle.engine_sounds": "spunoS ǝuıbuƎ"
}
}

View File

@@ -465,6 +465,9 @@
"create.fe": "FE: %1$s",
"create.goggles.ammeter": "Ammeter:",
"create.goggles.ammeter.amps": " Measured Amps: %1$s V",
"create.goggles.blast_furnace.batch_header": "Smelt Batch Ratio:",
"create.goggles.blast_furnace.batch_ratio": "%s:%s:%s (Fuel:Ore:Flux)",
"create.goggles.blast_furnace.batch_warning": "Warning: Large batch size.",
"create.goggles.blast_furnace.fuel_amount": " Fuel : %1$s",
"create.goggles.blast_furnace.height": " Height: %1$s",
"create.goggles.blast_furnace.modifier": "Production Time: %1$s",
@@ -1062,4 +1065,4 @@
"tfmg.ponder.tag.oil_processing.description": "Block used for refining and mining oil",
"tfmg.subtitle.diesel_engine_sounds": "Diesel Engine Sounds",
"tfmg.subtitle.engine_sounds": "Engine Sounds"
}
}

View File

@@ -52,6 +52,7 @@ public class BlastFurnaceOutputBlockEntity extends SmartBlockEntity implements I
public SmartInventory inputInventory;
public SmartInventory fluxInventory;
public SmartInventory fuelInventory;
public FluidTank primaryTank;
public FluidTank secondaryTank;
protected LazyOptional<IFluidHandler> fluidCapability;
@@ -79,12 +80,16 @@ public class BlastFurnaceOutputBlockEntity extends SmartBlockEntity implements I
.forbidExtraction()
.withMaxStackSize(64).whenContentsChanged(i -> this.onContentsChanged());
fuelInventory = new SmartInventory(1, this)
.forbidInsertion()
.withMaxStackSize(64).whenContentsChanged(i -> this.onContentsChanged());
primaryTank = new SmartFluidTank(4000, this::onFluidChanged);
secondaryTank = new SmartFluidTank(4000, this::onFluidChanged);
itemCapability = LazyOptional.of(() -> new CombinedInvWrapper(inputInventory, fluxInventory));
itemCapability = LazyOptional.of(() -> new CombinedInvWrapper(inputInventory, fluxInventory, fuelInventory));
fluidCapability = LazyOptional.of(() -> new CombinedTankWrapper(primaryTank, secondaryTank));
}
@@ -107,6 +112,51 @@ public class BlastFurnaceOutputBlockEntity extends SmartBlockEntity implements I
}
}
public static int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
private int calculateProcessingTime(IndustrialBlastingRecipe recipe) {
int baseDuration = recipe.getProcessingDuration() * 20;
double timeModifier = TFMGConfigs.common().machines.blastFurnaceMaxHeight.get() /
((baseDuration / 2) * TFMGConfigs.common().machines.blastFurnaceHeightSpeedModifier.get());
int actualTicks = (int)(baseDuration - (getSize() / timeModifier));
return isReinforced ? actualTicks / 2 : actualTicks;
}
private int[] findCleanRatio(IndustrialBlastingRecipe recipe) {
// Get all values from config
int ticksPerFuel = TFMGConfigs.common().machines.blastFurnaceFuelConsumption.get();
int actualTicks = calculateProcessingTime(recipe);
// Calculate the exact decimal ratio
float exactRatio = (float)ticksPerFuel / actualTicks;
// Find the smallest integer ratio that approximates this
int maxIterations = 1000; // Prevents infinite loops
float tolerance = 0.0001f; // How close we need to be
int a = 1, b = 1;
float currentError = Math.abs(exactRatio - ((float)a/b));
// Farey sequence approximation
for (int i = 0; i < maxIterations && currentError > tolerance; i++) {
if ((float)a/b < exactRatio) {
a++;
} else {
b++;
}
currentError = Math.abs(exactRatio - ((float)a/b));
}
// Check if recipe needs flux
boolean needsFlux = recipe.getIngredients().size() > 1;
// Return as [fuel, ore, flux]
return new int[]{b, a, needsFlux ? a : 0};
}
@Override
public boolean addToGoggleTooltip(List<Component> tooltip, boolean isPlayerSneaking) {
@@ -130,11 +180,37 @@ public class BlastFurnaceOutputBlockEntity extends SmartBlockEntity implements I
.style(ChatFormatting.GREEN)
.forGoggles(tooltip);
// Dynamic batch ratio calculation for current input
if (!inputInventory.isEmpty()) {
Optional<IndustrialBlastingRecipe> recipeOpt = TFMGRecipeTypes.INDUSTRIAL_BLASTING
.find(new RecipeWrapper(inputInventory), level);
if (recipeOpt.isPresent()) {
IndustrialBlastingRecipe recipe = recipeOpt.get();
int[] batch = findCleanRatio(recipe); // Uses the corrected method
CreateLang.translate("goggles.blast_furnace.batch_header")
.style(ChatFormatting.GRAY)
.forGoggles(tooltip);
CreateLang.translate("goggles.blast_furnace.batch_ratio",
batch[0], batch[1], batch[2])
.style(ChatFormatting.AQUA)
.forGoggles(tooltip);
if (batch[1] > 64) {
CreateLang.translate("goggles.blast_furnace.batch_warning")
.style(ChatFormatting.YELLOW)
.forGoggles(tooltip);
}
}
}
TFMGUtils.createFluidTooltip(this, tooltip);
TFMGUtils.createItemTooltip(this, tooltip);
return true;
}
public void executeRecipe() {
@@ -178,6 +254,17 @@ public class BlastFurnaceOutputBlockEntity extends SmartBlockEntity implements I
if (getSize() < 3)
return;
if (fuel <= 0 && !fuelInventory.getItem(0).isEmpty()) {
ItemStack fuelStack = fuelInventory.getItem(0);
if (fuelStack.is(TFMGTags.TFMGItemTags.BLAST_FURNACE_FUEL.tag)) {
int fuelValue = 1;
int toConsume = Math.min(fuelStack.getCount(), STORAGE_SPACE - fuel);
fuel += toConsume * fuelValue;
fuelStack.shrink(toConsume);
setChanged();
}
}
if (fuelConsumeTimer >= TFMGConfigs.common().machines.blastFurnaceFuelConsumption.get() && fuel > 0) {
fuelConsumeTimer = 0;
fuel--;
@@ -232,8 +319,8 @@ public class BlastFurnaceOutputBlockEntity extends SmartBlockEntity implements I
tuyereBE.tank.getFluidInTank(0).setAmount(Math.max(tuyereBE.tank.getFluidInTank(0).getAmount() - recipe.hotAirUsage, 0));
if (!recipe.getGasByproduct().isEmpty()) {
if (level.getBlockEntity(getBlockPos().relative(getBlockState().getValue(FACING).getOpposite()).above(getSize())) instanceof BlastFurnaceHatchBlockEntity be) {
be.tank.fill(recipe.getGasByproduct(), IFluidHandler.FluidAction.EXECUTE);
if (level.getBlockEntity(getBlockPos().relative(getBlockState().getValue(FACING).getOpposite()).above(getSize())) instanceof BlastFurnaceHatchBlockEntity chargeHatchBE) {
chargeHatchBE.tank.fill(recipe.getGasByproduct(), IFluidHandler.FluidAction.EXECUTE);
}
}
if (level.isClientSide())
@@ -261,8 +348,8 @@ public class BlastFurnaceOutputBlockEntity extends SmartBlockEntity implements I
}
private boolean canProcess(IndustrialBlastingRecipe recipe) {
if (fuel == 0)
return false;
//if (fuel == 0)
// return false;
if (!primaryTank.getFluid().isEmpty() && !primaryTank.getFluid().getFluid().isSame(recipe.getPrimaryResult().getFluid()))
return false;
@@ -312,12 +399,32 @@ public class BlastFurnaceOutputBlockEntity extends SmartBlockEntity implements I
if (itemStack.isEmpty())
return;
if (itemStack.is(TFMGTags.TFMGItemTags.BLAST_FURNACE_FUEL.tag) && fuel < STORAGE_SPACE) {
if (itemStack.is(TFMGTags.TFMGItemTags.BLAST_FURNACE_FUEL.tag)) {
// If fuel storage is full, try to add to fuel inventory slot
if (fuel >= STORAGE_SPACE) {
if (fuelInventory.getItem(0).isEmpty() ||
(fuelInventory.getItem(0).is(itemStack.getItem()) &&
fuelInventory.getItem(0).getCount() < fuelInventory.getItem(0).getMaxStackSize())) {
fuel++;
itemStack.shrink(1);
continue;
int added = Math.min(itemStack.getCount(),
fuelInventory.getItem(0).getMaxStackSize() - fuelInventory.getItem(0).getCount());
if (fuelInventory.getItem(0).isEmpty()) {
fuelInventory.setItem(0, new ItemStack(itemStack.getItem(), added));
} else {
fuelInventory.getItem(0).grow(added);
}
itemStack.shrink(added);
continue;
}
} else {
// Add to fuel storage if not full
int toAdd = Math.min(itemStack.getCount(), STORAGE_SPACE - fuel);
fuel += toAdd;
itemStack.shrink(toAdd);
continue;
}
}
if (itemStack.is(TFMGTags.TFMGItemTags.FLUX.tag) && fluxInventory.getItem(0).getCount() < itemStack.getMaxStackSize()) {
if (fluxInventory.isEmpty() || fluxInventory.getItem(0).is(itemStack.getItem())) {
fluxInventory.setItem(0, new ItemStack(itemStack.getItem(), fluxInventory.getItem(0).getCount() + 1));
@@ -329,7 +436,6 @@ public class BlastFurnaceOutputBlockEntity extends SmartBlockEntity implements I
if (inputInventory.isEmpty() || inputInventory.getItem(0).is(itemStack.getItem())) {
inputInventory.setItem(0, new ItemStack(itemStack.getItem(), inputInventory.getItem(0).getCount() + 1));
itemStack.shrink(1);
continue;
}
}
}
@@ -341,6 +447,7 @@ public class BlastFurnaceOutputBlockEntity extends SmartBlockEntity implements I
isReinforced = compound.getBoolean("IsReinforce");
inputInventory.deserializeNBT(compound.getCompound("InputItems"));
fluxInventory.deserializeNBT(compound.getCompound("Flux"));
fuelInventory.deserializeNBT(compound.getCompound("FuelItems"));
timer = compound.getInt("Timer");
fuel = compound.getInt("Fuel");
fuelConsumeTimer = compound.getInt("FuelConsumeTimer");
@@ -354,6 +461,7 @@ public class BlastFurnaceOutputBlockEntity extends SmartBlockEntity implements I
compound.putBoolean("IsReinforce", isReinforced);
compound.put("InputItems", inputInventory.serializeNBT());
compound.put("Flux", fluxInventory.serializeNBT());
compound.put("FuelItems", fuelInventory.serializeNBT());
compound.putInt("Timer", timer);
compound.putInt("Fuel", fuel);
compound.putInt("FuelConsumeTimer", fuelConsumeTimer);
@@ -366,6 +474,7 @@ public class BlastFurnaceOutputBlockEntity extends SmartBlockEntity implements I
super.destroy();
ItemHelper.dropContents(level, worldPosition, inputInventory);
ItemHelper.dropContents(level, worldPosition, fluxInventory);
ItemHelper.dropContents(level, worldPosition, fuelInventory);
}
public int getSize() {
@@ -382,7 +491,7 @@ public class BlastFurnaceOutputBlockEntity extends SmartBlockEntity implements I
int normalAmount = 0;
int reinforcedAmount = 0;
for (int i = 0; i < TFMGConfigs.common().machines.blastFurnaceMaxHeight.get(); i++) {
for (int i = 0; i <= TFMGConfigs.common().machines.blastFurnaceMaxHeight.get(); i++) {
BlockPos checkedPos = middlePos.above(i).east().south();
@@ -470,4 +579,4 @@ public class BlastFurnaceOutputBlockEntity extends SmartBlockEntity implements I
REINFORCED
}
}
}

View File

@@ -23,6 +23,9 @@
"create.goggles.blast_furnace.reinforced": "Reinforced",
"create.goggles.blast_furnace.timer": "Time Left: %1$s",
"create.goggles.blast_furnace.modifier": "Production Time: %1$s",
"create.goggles.blast_furnace.batch_header": "Smelt Batch Ratio:",
"create.goggles.blast_furnace.batch_ratio": "%s:%s:%s (Fuel:Ore:Flux)",
"create.goggles.blast_furnace.batch_warning": "Warning: Large batch size.",
"create.goggles.blast_stove.header": "Blast Stove: ",
"create.goggles.blast_stove.tank1": "Input Tank 1: ",