From 1bb634aee18d1a075a1147dadeb38fa925027e08 Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 30 Jun 2025 03:32:22 +0300 Subject: [PATCH] Blast furnace QoL tweak - add perfect smelt batch ratio display in tooltip - fix undersmelting at perfect ratios - fix height 10 reinforcement not being detected --- .../resources/assets/tfmg/lang/en_ud.json | 5 +- .../resources/assets/tfmg/lang/en_us.json | 5 +- .../BlastFurnaceOutputBlockEntity.java | 135 ++++++++++++++++-- .../assets/tfmg/lang/default/interface.json | 3 + 4 files changed, 133 insertions(+), 15 deletions(-) diff --git a/src/generated/resources/assets/tfmg/lang/en_ud.json b/src/generated/resources/assets/tfmg/lang/en_ud.json index 2c72fccc..efd19056 100644 --- a/src/generated/resources/assets/tfmg/lang/en_ud.json +++ b/src/generated/resources/assets/tfmg/lang/en_ud.json @@ -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Ǝ" -} \ No newline at end of file +} diff --git a/src/generated/resources/assets/tfmg/lang/en_us.json b/src/generated/resources/assets/tfmg/lang/en_us.json index 6e9fd3f4..3fc4748c 100644 --- a/src/generated/resources/assets/tfmg/lang/en_us.json +++ b/src/generated/resources/assets/tfmg/lang/en_us.json @@ -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" -} \ No newline at end of file +} diff --git a/src/main/java/com/drmangotea/tfmg/content/machinery/metallurgy/blast_furnace/BlastFurnaceOutputBlockEntity.java b/src/main/java/com/drmangotea/tfmg/content/machinery/metallurgy/blast_furnace/BlastFurnaceOutputBlockEntity.java index b16d9c8e..9c77eeac 100644 --- a/src/main/java/com/drmangotea/tfmg/content/machinery/metallurgy/blast_furnace/BlastFurnaceOutputBlockEntity.java +++ b/src/main/java/com/drmangotea/tfmg/content/machinery/metallurgy/blast_furnace/BlastFurnaceOutputBlockEntity.java @@ -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 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 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 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 } -} \ No newline at end of file +} diff --git a/src/main/resources/assets/tfmg/lang/default/interface.json b/src/main/resources/assets/tfmg/lang/default/interface.json index 67720954..d8be800e 100644 --- a/src/main/resources/assets/tfmg/lang/default/interface.json +++ b/src/main/resources/assets/tfmg/lang/default/interface.json @@ -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: ",