diff --git a/src/generated/resources/assets/gtceu/lang/en_ud.json b/src/generated/resources/assets/gtceu/lang/en_ud.json index a0ddc38c98..0768d0203f 100644 --- a/src/generated/resources/assets/gtceu/lang/en_ud.json +++ b/src/generated/resources/assets/gtceu/lang/en_ud.json @@ -3711,6 +3711,10 @@ "gtceu.multiblock.ore_rig.drilled_ore_entry": "%s - ", "gtceu.multiblock.ore_rig.drilled_ores_list": ":sǝɹO", "gtceu.multiblock.ore_rig.ore_amount": "%s :ǝʇɐᴚ buıןןıɹᗡ", + "gtceu.multiblock.output_line.0": ")ɐǝ/%ss( ɹ§%sǝ§ x %s", + "gtceu.multiblock.output_line.1": ")s/%s( ɹ§%sǝ§ x %s", + "gtceu.multiblock.output_line.2": ")ɐǝ/%ss( ɹ§%sǝ§ ≈ %s", + "gtceu.multiblock.output_line.3": ")s/%s( ɹ§%sǝ§ ≈ %s", "gtceu.multiblock.page_switcher.io.both": "sʇndʇnO + sʇnduI pǝuıqɯoƆϛ§", "gtceu.multiblock.page_switcher.io.export": "sʇndʇnOㄣ§", "gtceu.multiblock.page_switcher.io.import": "sʇnduIᄅ§", @@ -3767,7 +3771,7 @@ "gtceu.multiblock.primitive_water_pump.extra2.3": "xㄣ :ɥɔʇɐH ʇndʇnO ΛꞀ ", "gtceu.multiblock.primitive_water_pump.extra2.4": "", "gtceu.multiblock.primitive_water_pump.extra2.5": "˙%%0ϛ ʎq pǝsɐǝɹɔuı ǝq ןןıʍ uoıʇɔnpoɹd ɹǝʇɐʍ ןɐʇoʇ ǝɥʇ 'ǝɯoıᗺ s,dɯnԀ ǝɥʇ uı buıuıɐɹ ǝןıɥM", - "gtceu.multiblock.progress": "%s%% :ssǝɹboɹԀ", + "gtceu.multiblock.progress": ")%s%%( %ss / %ss :ssǝɹboɹԀ", "gtceu.multiblock.pyrolyse_oven.description": "˙ןıO ʎʌɐǝH puɐ ɥsⱯ ɹo 'ןıO ǝʇosoǝɹƆ puɐ ןɐoɔɹɐɥƆ oʇuı sboꞀ buıuɹnʇ ɹoɟ pǝsn ǝɹnʇɔnɹʇs ʞɔoןqıʇןnɯ ɐ sı uǝʌO ǝsʎןoɹʎԀ ǝɥ⟘", "gtceu.multiblock.pyrolyse_oven.speed": "%s%% :pǝǝdS buıssǝɔoɹԀ", "gtceu.multiblock.require_steam_parts": "¡sǝsnᗺ puɐ sǝɥɔʇɐH ɯɐǝʇS sǝɹınbǝᴚ", diff --git a/src/generated/resources/assets/gtceu/lang/en_us.json b/src/generated/resources/assets/gtceu/lang/en_us.json index a885320d34..cb22554531 100644 --- a/src/generated/resources/assets/gtceu/lang/en_us.json +++ b/src/generated/resources/assets/gtceu/lang/en_us.json @@ -3711,6 +3711,10 @@ "gtceu.multiblock.ore_rig.drilled_ore_entry": " - %s", "gtceu.multiblock.ore_rig.drilled_ores_list": "Ores:", "gtceu.multiblock.ore_rig.ore_amount": "Drilling Rate: %s", + "gtceu.multiblock.output_line.0": "%s x §e%s§r (%ss/ea)", + "gtceu.multiblock.output_line.1": "%s x §e%s§r (%s/s)", + "gtceu.multiblock.output_line.2": "%s ≈ §e%s§r (%ss/ea)", + "gtceu.multiblock.output_line.3": "%s ≈ §e%s§r (%s/s)", "gtceu.multiblock.page_switcher.io.both": "§5Combined Inputs + Outputs", "gtceu.multiblock.page_switcher.io.export": "§4Outputs", "gtceu.multiblock.page_switcher.io.import": "§2Inputs", @@ -3767,7 +3771,7 @@ "gtceu.multiblock.primitive_water_pump.extra2.3": " LV Output Hatch: 4x", "gtceu.multiblock.primitive_water_pump.extra2.4": "", "gtceu.multiblock.primitive_water_pump.extra2.5": "While raining in the Pump's Biome, the total water production will be increased by 50%%.", - "gtceu.multiblock.progress": "Progress: %s%%", + "gtceu.multiblock.progress": "Progress: %ss / %ss (%s%%)", "gtceu.multiblock.pyrolyse_oven.description": "The Pyrolyse Oven is a multiblock structure used for turning Logs into Charcoal and Creosote Oil, or Ash and Heavy Oil.", "gtceu.multiblock.pyrolyse_oven.speed": "Processing Speed: %s%%", "gtceu.multiblock.require_steam_parts": "Requires Steam Hatches and Buses!", diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IDisplayUIMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IDisplayUIMachine.java index 4ea74e60c9..365106eca2 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IDisplayUIMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/feature/multiblock/IDisplayUIMachine.java @@ -42,7 +42,7 @@ default ModularUI createUI(Player entityPlayer) { screen.addWidget(new ComponentPanelWidget(4, 17, this::addDisplayText) .textSupplier(this.self().getLevel().isClientSide ? null : this::addDisplayText) .setMaxWidthLimit(150) - .clickHandler(this::handleDisplayClick)); + .clickHandler(this::handleDisplayClick)).setSizeHeight(8); return new ModularUI(176, 216, this, entityPlayer) .background(GuiTextures.BACKGROUND) .widget(screen) diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockDisplayText.java b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockDisplayText.java index d229164d60..cd2637cb83 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockDisplayText.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/MultiblockDisplayText.java @@ -2,7 +2,11 @@ import com.gregtechceu.gtceu.api.GTValues; import com.gregtechceu.gtceu.api.capability.IEnergyContainer; +import com.gregtechceu.gtceu.api.capability.recipe.FluidRecipeCapability; +import com.gregtechceu.gtceu.api.capability.recipe.ItemRecipeCapability; +import com.gregtechceu.gtceu.api.recipe.GTRecipe; import com.gregtechceu.gtceu.api.recipe.GTRecipeType; +import com.gregtechceu.gtceu.api.recipe.RecipeHelper; import com.gregtechceu.gtceu.config.ConfigHolder; import com.gregtechceu.gtceu.utils.FormattingUtil; import com.gregtechceu.gtceu.utils.GTUtil; @@ -299,27 +303,100 @@ public Builder addIdlingLine(boolean checkState) { } /** - * Adds a simple progress line that displays progress as a percentage. + * Adds a simple progress line that displays the current time of a recipe and its progress as a percentage. *
* Added if structure is formed and the machine is active. * + * @param currentDuration The current duration of the recipe in ticks + * @param maxDuration The max duration of the recipe in ticks * @param progressPercent Progress formatted as a range of [0,1] representing the progress of the recipe. */ - public Builder addProgressLine(double progressPercent) { // todo + public Builder addProgressLine(double currentDuration, double maxDuration, double progressPercent) { if (!isStructureFormed || !isActive) return this; int currentProgress = (int) (progressPercent * 100); - textList.add(Component.translatable("gtceu.multiblock.progress", currentProgress)); + double currentInSec = currentDuration / 20.0; + double maxInSec = maxDuration / 20.0; + textList.add(Component.translatable("gtceu.multiblock.progress", + String.format("%.2f", (float) currentInSec), + String.format("%.2f", (float) maxInSec), currentProgress)); + return this; + } + + public Builder addOutputLines(GTRecipe recipe, int chanceTier) { + if (!isStructureFormed || !isActive) + return this; + if (recipe != null) { + var function = recipe.getType().getChanceFunction(); + double maxDurationSec = (double) recipe.duration / 20.0; + var itemOutputs = recipe.getOutputContents(ItemRecipeCapability.CAP); + var fluidOutputs = recipe.getOutputContents(FluidRecipeCapability.CAP); + + for (var item : itemOutputs) { + var stack = (ItemRecipeCapability.CAP.of(item.content).getItems()[0]); + if (stack.getCount() < maxDurationSec) { + if (item.chance < item.maxChance) { + double averageDurationforRoll = (double) item.maxChance / (double) function + .getBoostedChance(item, RecipeHelper.getPreOCRecipeEuTier(recipe), chanceTier); + textList.add(Component.translatable("gtceu.multiblock.output_line.2", stack.getHoverName(), + stack.getCount(), + FormattingUtil.formatNumber2Places(averageDurationforRoll * maxDurationSec))); + } else { + textList.add(Component.translatable("gtceu.multiblock.output_line.0", stack.getHoverName(), + stack.getCount(), maxDurationSec)); + } + } else { + double countPerSec = (double) stack.getCount() / maxDurationSec; + if (item.chance < item.maxChance) { + double averageDurationforRoll = (double) item.maxChance / (double) function + .getBoostedChance(item, RecipeHelper.getPreOCRecipeEuTier(recipe), chanceTier); + textList.add(Component.translatable("gtceu.multiblock.output_line.3", + stack.getHoverName(), stack.getCount(), + FormattingUtil.formatNumber2Places(averageDurationforRoll * countPerSec))); + } else { + textList.add(Component.translatable("gtceu.multiblock.output_line.1", + stack.getHoverName(), stack.getCount(), countPerSec)); + } + } + } + for (var fluid : fluidOutputs) { + var stack = (FluidRecipeCapability.CAP.of(fluid.content).getStacks()[0]); + if (stack.getAmount() < maxDurationSec) { + if (fluid.chance < fluid.maxChance) { + double averageDurationforRoll = (double) fluid.maxChance / (double) function + .getBoostedChance(fluid, RecipeHelper.getPreOCRecipeEuTier(recipe), chanceTier); + textList.add(Component.translatable("gtceu.multiblock.output_line.2", + stack.getDisplayName(), stack.getAmount(), + FormattingUtil.formatNumber2Places(averageDurationforRoll * maxDurationSec))); + } else { + textList.add(Component.translatable("gtceu.multiblock.output_line.0", + stack.getDisplayName(), stack.getAmount(), + FormattingUtil.formatNumber2Places(maxDurationSec))); + } + } else { + double countPerSec = (double) stack.getAmount() / maxDurationSec; + if (fluid.chance < fluid.maxChance) { + double averageDurationforRoll = (double) fluid.maxChance / (double) function + .getBoostedChance(fluid, RecipeHelper.getPreOCRecipeEuTier(recipe), chanceTier); + textList.add(Component.translatable("gtceu.multiblock.output_line.3", + stack.getDisplayName(), stack.getAmount(), + FormattingUtil.formatNumber2Places(averageDurationforRoll * countPerSec))); + } else { + textList.add(Component.translatable("gtceu.multiblock.output_line.1", + stack.getDisplayName(), stack.getAmount(), + FormattingUtil.formatNumber2Places(countPerSec))); + } + } + } + } return this; } /** - * Adds a line indicating how many parallels this multi can potentially perform. - *
- * Added if structure is formed and the number of parallels is greater than one. + * Adds a line indicating the current mode of the multi */ - public Builder addMachineModeLine(GTRecipeType recipeType) { - if (!isStructureFormed) + public Builder addMachineModeLine(GTRecipeType recipeType, boolean hasMultipleModes) { + if (!isStructureFormed || !hasMultipleModes) return this; textList.add(Component .translatable("gtceu.gui.machinemode", diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/WorkableElectricMultiblockMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/WorkableElectricMultiblockMachine.java index e518d25895..3462a2b0b7 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/WorkableElectricMultiblockMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/multiblock/WorkableElectricMultiblockMachine.java @@ -95,10 +95,12 @@ public void addDisplayText(List textList) { .setWorkingStatus(recipeLogic.isWorkingEnabled(), recipeLogic.isActive()) .addEnergyUsageLine(energyContainer) .addEnergyTierLine(tier) - .addMachineModeLine(getRecipeType()) + .addMachineModeLine(getRecipeType(), getRecipeTypes().length > 1) .addParallelsLine(numParallels) .addWorkingStatusLine() - .addProgressLine(recipeLogic.getProgressPercent()); + .addProgressLine(recipeLogic.getProgress(), recipeLogic.getMaxProgress(), + recipeLogic.getProgressPercent()) + .addOutputLines(recipeLogic.getLastRecipe(), this.getChanceTier()); getDefinition().getAdditionalDisplay().accept(this, textList); IDisplayUIMachine.super.addDisplayText(textList); } @@ -110,7 +112,7 @@ public Widget createUIWidget() { .addWidget(new LabelWidget(4, 5, self().getBlockState().getBlock().getDescriptionId())) .addWidget(new ComponentPanelWidget(4, 17, this::addDisplayText) .textSupplier(this.getLevel().isClientSide ? null : this::addDisplayText) - .setMaxWidthLimit(150) + .setMaxWidthLimit(200) .clickHandler(this::handleDisplayClick))); group.setBackground(GuiTextures.BACKGROUND_INVERSE); return group; diff --git a/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java b/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java index 3350d6555c..84a39d84d5 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java @@ -1067,7 +1067,11 @@ public static void init(RegistrateLangProvider provider) { provider.add("gtceu.multiblock.not_enough_energy", "WARNING: Machine needs more energy."); provider.add("gtceu.multiblock.not_enough_energy_output", "WARNING: Energy Dynamo Tier Too Low!"); provider.add("gtceu.multiblock.waiting", "WARNING: Machine is waiting."); - provider.add("gtceu.multiblock.progress", "Progress: %s%%"); + provider.add("gtceu.multiblock.progress", "Progress: %ss / %ss (%s%%)"); + provider.add("gtceu.multiblock.output_line.0", "%s x §e%s§r (%ss/ea)"); + provider.add("gtceu.multiblock.output_line.1", "%s x §e%s§r (%s/s)"); + provider.add("gtceu.multiblock.output_line.2", "%s ≈ §e%s§r (%ss/ea)"); + provider.add("gtceu.multiblock.output_line.3", "%s ≈ §e%s§r (%s/s)"); provider.add("gtceu.multiblock.invalid_structure", "Invalid structure."); provider.add("gtceu.multiblock.invalid_structure.tooltip", "This block is a controller of the multiblock structure. For building help, see structure template in JEI."); diff --git a/src/main/java/com/gregtechceu/gtceu/utils/FormattingUtil.java b/src/main/java/com/gregtechceu/gtceu/utils/FormattingUtil.java index 95d3974d75..3d4320f6d7 100644 --- a/src/main/java/com/gregtechceu/gtceu/utils/FormattingUtil.java +++ b/src/main/java/com/gregtechceu/gtceu/utils/FormattingUtil.java @@ -179,6 +179,11 @@ public static String formatNumber2Places(float number) { return DECIMAL_FORMAT_2F.format(number); } + @NotNull + public static String formatNumber2Places(double number) { + return DECIMAL_FORMAT_2F.format(number); + } + public static Component formatPercentage2Places(String langKey, float percentage) { return Component.translatable(langKey, formatNumber2Places(percentage)).withStyle(YELLOW); }