diff --git a/docs/content/Modpacks/Changes/v7.5.0.md b/docs/content/Modpacks/Changes/v7.5.0.md index b5c8cf0110e..840f6f4d50d 100644 --- a/docs/content/Modpacks/Changes/v7.5.0.md +++ b/docs/content/Modpacks/Changes/v7.5.0.md @@ -75,6 +75,31 @@ Previously, lamps were not useable with the terminal in multiblocks. There are n The predicate to use all lamps is: `Predicates.anyLamp()` The predicate to use a specific color is: `Predicates.lampsByColor(DyeColor.DYE_COLOR)`. Where DYE_COLOR is the name of the color you want. +## Machine Recipe Failure Diagnostics +Machines now provide detailed diagnostics explaining why recipes fail to start. + +Failure reasons are displayed in: +- the sidebar of simple machines +- the UI of multiblock machines +- the Jade tooltip for all machines + +You are supposed to replace `ModifierFunction.NULL` with `ModifierFunction.cancel(reason)` to tell the machine why the recipe fails to start. +```patch +- return ModifierFunction.NULL; ++ return ModifierFunction.cancel(Component.translatable("gtceu.recipe_modifier.xxx")); +``` + +Also, if you cancel a recipe in `IRecipeLogicMachine#beforeWorking()`, you are supposed to add some custom reason info like: +``` +@Override +public boolean beforeWorking(@Nullable GTRecipe recipe) { + if(xxx){ + RecipeLogic.putFailureReason(this, recipe, Component.literal("Machine spirit is displeased")); + return false + } + return true; +} +``` ## Painted Output Buses/Hatches For some time, Spray Paint cans could be used to paint Input and Output Buses/Hatches on multiblock machines. Version 7.0.0 added the feature that Painted Input Buses/Hatches of different colors would not share their ingredients with diff --git a/src/generated/resources/assets/gtceu/lang/en_ud.json b/src/generated/resources/assets/gtceu/lang/en_ud.json index f51d500f0c5..5662e6a4f60 100644 --- a/src/generated/resources/assets/gtceu/lang/en_ud.json +++ b/src/generated/resources/assets/gtceu/lang/en_ud.json @@ -1760,6 +1760,7 @@ "config.gtceu.option.casingsPerCraft": "ʇɟɐɹƆɹǝԀsbuısɐɔ", "config.gtceu.option.cleanMultiblocks": "sʞɔoןqıʇןnWuɐǝןɔ", "config.gtceu.option.client": "ʇuǝıןɔ", + "config.gtceu.option.coloredMaterialBlockOutline": "ǝuıןʇnOʞɔoןᗺןɐıɹǝʇɐWpǝɹoןoɔ", "config.gtceu.option.coloredTieredMachineOutline": "ǝuıןʇnOǝuıɥɔɐWpǝɹǝı⟘pǝɹoןoɔ", "config.gtceu.option.coloredWireOutline": "ǝuıןʇnOǝɹıMpǝɹoןoɔ", "config.gtceu.option.compat": "ʇɐdɯoɔ", @@ -3762,8 +3763,14 @@ "gtceu.recipe_logic.insufficient_out": "sʇndʇnO ʇuǝıɔıɟɟnsuI", "gtceu.recipe_logic.no_capabilities": "sǝıʇıןıqɐdɐƆ ou sɐɥ ǝuıɥɔɐW", "gtceu.recipe_logic.no_contents": "sʇuǝʇuoƆ ou sɐɥ ǝdıɔǝᴚ", + "gtceu.recipe_logic.recipe_waiting": " :buıʇıɐM ǝdıɔǝᴚ", + "gtceu.recipe_logic.setup_fail": " :ǝdıɔǝɹ dnʇǝs oʇ ןıɐℲ", "gtceu.recipe_memory_widget.tooltip.0": "pıɹb buıʇɟɐɹɔ ǝɥʇ oʇuı ǝdıɔǝɹ sıɥʇ ʇnduı ʎןןɐɔıʇɐɯoʇnɐ oʇ ʞɔıןɔ ʇɟǝꞀㄥ§", "gtceu.recipe_memory_widget.tooltip.1": "ǝdıɔǝɹ sıɥʇ ʞɔoןun/ʞɔoן oʇ ʞɔıןɔ ʇɟıɥSㄥ§", + "gtceu.recipe_modifier.coil_temperature_too_low": "ʍoꞀ oo⟘ ǝɹnʇɐɹǝdɯǝ⟘ ןıoƆ", + "gtceu.recipe_modifier.default_fail": "ןıɐℲ ɹǝıɟıpoW ǝdıɔǝᴚ", + "gtceu.recipe_modifier.insufficient_eu_to_start_fusion": "uoıʇɔɐǝᴚ uoısnℲ ǝʇɐıʇıuI oʇ ʎbɹǝuƎ ʇuǝıɔıɟɟnsuI", + "gtceu.recipe_modifier.insufficient_voltage": "ʍoꞀ oo⟘ ɹǝı⟘ ǝbɐʇןoΛ", "gtceu.recipe_type.show_recipes": "sǝdıɔǝᴚ ʍoɥS", "gtceu.rei.group.potion_fluids": "spınןℲ uoıʇoԀ", "gtceu.research_station": "uoıʇɐʇS ɥɔɹɐǝsǝᴚ", diff --git a/src/generated/resources/assets/gtceu/lang/en_us.json b/src/generated/resources/assets/gtceu/lang/en_us.json index 3ceb805dee1..8396c85fe46 100644 --- a/src/generated/resources/assets/gtceu/lang/en_us.json +++ b/src/generated/resources/assets/gtceu/lang/en_us.json @@ -1760,6 +1760,7 @@ "config.gtceu.option.casingsPerCraft": "casingsPerCraft", "config.gtceu.option.cleanMultiblocks": "cleanMultiblocks", "config.gtceu.option.client": "client", + "config.gtceu.option.coloredMaterialBlockOutline": "coloredMaterialBlockOutline", "config.gtceu.option.coloredTieredMachineOutline": "coloredTieredMachineOutline", "config.gtceu.option.coloredWireOutline": "coloredWireOutline", "config.gtceu.option.compat": "compat", @@ -3762,8 +3763,14 @@ "gtceu.recipe_logic.insufficient_out": "Insufficient Outputs", "gtceu.recipe_logic.no_capabilities": "Machine has no Capabilities", "gtceu.recipe_logic.no_contents": "Recipe has no Contents", + "gtceu.recipe_logic.recipe_waiting": "Recipe Waiting: ", + "gtceu.recipe_logic.setup_fail": "Fail to setup recipe: ", "gtceu.recipe_memory_widget.tooltip.0": "§7Left click to automatically input this recipe into the crafting grid", "gtceu.recipe_memory_widget.tooltip.1": "§7Shift click to lock/unlock this recipe", + "gtceu.recipe_modifier.coil_temperature_too_low": "Coil Temperature Too Low", + "gtceu.recipe_modifier.default_fail": "Recipe Modifier Fail", + "gtceu.recipe_modifier.insufficient_eu_to_start_fusion": "Insufficient Energy to Initiate Fusion Reaction", + "gtceu.recipe_modifier.insufficient_voltage": "Voltage Tier Too Low", "gtceu.recipe_type.show_recipes": "Show Recipes", "gtceu.rei.group.potion_fluids": "Potion Fluids", "gtceu.research_station": "Research Station", 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 b0270cb6d9e..1b9abeb2afa 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 @@ -372,6 +372,19 @@ public Builder addCustomProgressLine(RecipeLogic recipeLogic) { return this; } + public Builder addRecipeFailReasonLine(RecipeLogic recipeLogic) { + if (!isStructureFormed || !recipeLogic.isIdle()) + return this; + var reasons = recipeLogic.getFailureReasons(); + if (!reasons.isEmpty()) { + textList.add(Component.translatable("gtceu.recipe_logic.setup_fail").withStyle(ChatFormatting.RED)); + for (var reason : reasons) { + textList.add(Component.literal(" - ").append(reason)); + } + } + return this; + } + public Builder addBatchModeLine(boolean batchEnabled, int batchAmount) { if (batchEnabled && batchAmount > 0) { Component runs = Component.literal(FormattingUtil.formatNumbers(batchAmount)) 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 f05177efe83..1273ced2670 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 @@ -128,6 +128,7 @@ public void addDisplayText(List textList) { .addBatchModeLine(isBatchEnabled(), batchParallels) .addWorkingStatusLine() .addProgressLine(recipeLogic) + .addRecipeFailReasonLine(recipeLogic) .addOutputLines(recipeLogic.getLastRecipe()); getDefinition().getAdditionalDisplay().accept(this, textList); IDisplayUIMachine.super.addDisplayText(textList); diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/RecipeLogic.java b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/RecipeLogic.java index 1483937c722..8c5598cb3a0 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/trait/RecipeLogic.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/trait/RecipeLogic.java @@ -15,6 +15,7 @@ import com.gregtechceu.gtceu.api.recipe.ActionResult; import com.gregtechceu.gtceu.api.recipe.GTRecipe; import com.gregtechceu.gtceu.api.recipe.RecipeHelper; +import com.gregtechceu.gtceu.api.recipe.modifier.ModifierFunction; import com.gregtechceu.gtceu.api.registry.GTRegistries; import com.gregtechceu.gtceu.api.sound.AutoReleasedSound; import com.gregtechceu.gtceu.common.cover.MachineControllerCover; @@ -80,10 +81,18 @@ public enum Status implements StringRepresentable { @UpdateListener(methodName = "onActiveSynced") protected boolean isActive; + @Getter @Nullable @Persisted @DescSynced private Component waitingReason = null; + + @Getter + @DescSynced + protected final List failureReasons = new ArrayList<>(); + + @Getter + protected final Map failureReasonMap = new HashMap<>(); /** * unsafe, it may not be found from {@link RecipeManager}. Do not index it. */ @@ -158,6 +167,8 @@ public void resetRecipeLogic() { duration = 0; isActive = false; lastFailedMatches = null; + waitingReason = null; + failureReasons.clear(); if (status != Status.SUSPEND) { setStatus(Status.IDLE); } @@ -225,7 +236,10 @@ public void serverTick() { // No recipes available and the machine wants to unsubscribe until notified unsubscribe = true; } - + if (isIdle()) { + failureReasons.clear(); + failureReasons.addAll(failureReasonMap.values()); + } if (unsubscribe && subscription != null) { subscription.unsubscribe(); subscription = null; @@ -249,6 +263,8 @@ public boolean checkMatchedRecipeAvailable(GTRecipe match) { var recipeMatch = checkRecipe(modified); if (recipeMatch.isSuccess()) { setupRecipe(modified); + } else { + putFailureReason(this, match, recipeMatch.reason()); } if (lastRecipe != null && getStatus() == Status.WORKING) { lastOriginRecipe = match; @@ -321,13 +337,16 @@ protected void regressRecipe() { public void findAndHandleRecipe() { lastFailedMatches = null; + // try to execute last recipe if possible if (!recipeDirty && lastRecipe != null && checkRecipe(lastRecipe).isSuccess()) { GTRecipe recipe = lastRecipe; lastRecipe = null; lastOriginRecipe = null; setupRecipe(recipe); - } else { // try to find and handle a new recipe + } else { + // try to find and handle a new recipe + failureReasonMap.clear(); lastRecipe = null; lastOriginRecipe = null; handleSearchingRecipes(searchRecipe()); @@ -383,6 +402,7 @@ public void setupRecipe(GTRecipe recipe) { if (lastRecipe != null && !recipe.equals(lastRecipe)) { chanceCaches.clear(); } + failureReasonMap.clear(); recipeDirty = false; lastRecipe = recipe; setStatus(Status.WORKING); @@ -522,9 +542,6 @@ public void onRecipeFinish() { setupRecipe(lastRecipe); } else { setStatus(Status.IDLE); - if (recipeCheck.io() != IO.IN || recipeCheck.capability() == EURecipeCapability.CAP) { - waitingReason = recipeCheck.reason(); - } consecutiveRecipes = 0; progress = 0; duration = 0; @@ -590,7 +607,7 @@ public void updateSound() { @Override public IGuiTexture getFancyTooltipIcon() { - if (waitingReason != null) { + if (showFancyTooltip()) { return GuiTextures.INSUFFICIENT_INPUT; } return IGuiTexture.EMPTY; @@ -598,15 +615,18 @@ public IGuiTexture getFancyTooltipIcon() { @Override public List getFancyTooltip() { - if (waitingReason != null) { + if (isWaiting() && waitingReason != null) { return List.of(waitingReason); } + if (isIdle() && !failureReasons.isEmpty()) { + return failureReasons; + } return Collections.emptyList(); } @Override public boolean showFancyTooltip() { - return waitingReason != null; + return waitingReason != null || !failureReasons.isEmpty(); } protected Map, Object2IntMap> makeChanceCaches() { @@ -667,4 +687,21 @@ public void loadCustomPersistedData(@NotNull CompoundTag tag) { }); tag.put("chance_cache", chanceCache); } + + public static void putFailureReason(Object machine, GTRecipe recipe, Component reason) { + if (machine instanceof IRecipeLogicMachine rlm) { + putFailureReason(rlm.getRecipeLogic(), recipe, reason); + } + } + + public static void putFailureReason(RecipeLogic logic, GTRecipe recipe, Component reason) { + var map = logic.getFailureReasonMap(); + if (map.containsKey(recipe)) { + if (reason != ModifierFunction.DEFAULT_FAILURE) { + map.put(recipe, reason); + } + } else { + map.put(recipe, reason); + } + } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/RecipeRunner.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/RecipeRunner.java index 5627b677728..d23fc3b5501 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/recipe/RecipeRunner.java +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/RecipeRunner.java @@ -11,6 +11,8 @@ import com.gregtechceu.gtceu.api.recipe.chance.logic.ChanceLogic; import com.gregtechceu.gtceu.api.recipe.content.Content; +import net.minecraft.network.chat.Component; + import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; import lombok.Getter; @@ -119,7 +121,11 @@ private void fillContentMatchList(Map, List> entrie private ActionResult handleContents() { if (recipeContents.isEmpty()) return ActionResult.SUCCESS; if (!capabilityProxies.containsKey(io)) { - return ActionResult.FAIL_NO_CAPABILITIES; + return ActionResult.fail( + Component.translatable("gtceu.recipe_logic.no_capabilities") + .append(Component.literal(": ")) + .append(Component.translatable(io.tooltip)), + null, io); } List handlers = capabilityProxies.getOrDefault(io, Collections.emptyList()); diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/ModifierFunction.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/ModifierFunction.java index ff19a84f8b2..35067a36053 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/ModifierFunction.java +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/ModifierFunction.java @@ -9,6 +9,8 @@ import com.gregtechceu.gtceu.api.recipe.content.ContentModifier; import com.gregtechceu.gtceu.api.recipe.ingredient.EnergyStack; +import net.minecraft.network.chat.Component; + import lombok.Setter; import lombok.experimental.Accessors; import org.jetbrains.annotations.Contract; @@ -35,6 +37,7 @@ @FunctionalInterface public interface ModifierFunction { + // TODO: Add reasons for any NULL ModifierFunction (replace them with cancel) /** * Use this static to denote that the recipe should be cancelled */ @@ -44,6 +47,21 @@ public interface ModifierFunction { */ ModifierFunction IDENTITY = ModifierFunction.builder().build(); + static ModifierFunction cancel(Component reason) { + return new ModifierFunction() { + + @Override + public @Nullable GTRecipe apply(@NotNull GTRecipe recipe) { + return null; + } + + @Override + public Component getFailReason() { + return reason; + } + }; + } + /** * Applies this modifier to the passed recipe * @@ -79,6 +97,12 @@ private GTRecipe applySafe(@Nullable GTRecipe recipe) { return apply(recipe); } + static final Component DEFAULT_FAILURE = Component.translatable("gtceu.recipe_modifier.default_fail"); + + default Component getFailReason() { + return DEFAULT_FAILURE; + } + /** * Creates a FunctionBuilder to easily build a ModifierFunction that modifies parts of a recipe. *

diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/ParallelLogic.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/ParallelLogic.java index b8a65588451..a1e903a2883 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/ParallelLogic.java +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/ParallelLogic.java @@ -3,11 +3,13 @@ import com.gregtechceu.gtceu.api.capability.recipe.*; import com.gregtechceu.gtceu.api.machine.MetaMachine; import com.gregtechceu.gtceu.api.machine.feature.IRecipeLogicMachine; +import com.gregtechceu.gtceu.api.machine.trait.RecipeLogic; import com.gregtechceu.gtceu.api.recipe.GTRecipe; import com.gregtechceu.gtceu.api.recipe.RecipeHelper; import com.gregtechceu.gtceu.api.recipe.content.ContentModifier; import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; @@ -57,7 +59,15 @@ public static int getMaxByInput(IRecipeCapabilityHolder holder, GTRecipe recipe, for (RecipeCapability cap : recipe.inputs.keySet()) { if (cap.doMatchInRecipe() && !capsToSkip.contains(cap)) { // Find the maximum number of recipes that can be performed from the contents of the input inventories - minimum = Math.min(minimum, cap.getMaxParallelByInput(holder, recipe, parallelLimit, false)); + var capParallel = cap.getMaxParallelByInput(holder, recipe, parallelLimit, false); + if (capParallel == 0) { + Component reason = Component.translatable("gtceu.recipe_logic.insufficient_in") + .append(": ") + .append(cap.getName()); + RecipeLogic.putFailureReason(holder, recipe, reason); + return 0; + } + minimum = Math.min(minimum, capParallel); } } @@ -65,10 +75,24 @@ public static int getMaxByInput(IRecipeCapabilityHolder holder, GTRecipe recipe, for (RecipeCapability cap : recipe.tickInputs.keySet()) { if (cap.doMatchInRecipe() && !capsToSkip.contains(cap)) { // Find the maximum number of recipes that can be performed from the contents of the input inventories - minimum = Math.min(minimum, cap.getMaxParallelByInput(holder, recipe, parallelLimit, true)); + var capParallel = cap.getMaxParallelByInput(holder, recipe, parallelLimit, true); + if (capParallel == 0) { + Component reason = Component.translatable("gtceu.recipe_logic.insufficient_in") + .append(": ") + .append(cap.getName()); + RecipeLogic.putFailureReason(holder, recipe, reason); + return 0; + } + minimum = Math.min(minimum, capParallel); } } - if (minimum == Integer.MAX_VALUE) return 0; + if (minimum == Integer.MAX_VALUE) { + Component reason = Component.translatable("gtceu.recipe_logic.no_capabilities") + .append(Component.literal(": ")) + .append(Component.translatable(IO.IN.tooltip)); + RecipeLogic.putFailureReason(holder, recipe, reason); + return 0; + } return minimum; } @@ -93,6 +117,10 @@ public static int limitByOutputMerging(IRecipeCapabilityHolder holder, GTRecipe int limit = cap.limitMaxParallelByOutput(holder, recipe, parallelLimit, false); // If we are not voiding, and cannot fit any items, return 0 if (limit == 0) { + Component reason = Component.translatable("gtceu.recipe_logic.insufficient_out") + .append(": ") + .append(cap.getName()); + RecipeLogic.putFailureReason(holder, recipe, reason); return 0; } max = Math.min(max, limit); @@ -107,6 +135,10 @@ public static int limitByOutputMerging(IRecipeCapabilityHolder holder, GTRecipe int limit = cap.limitMaxParallelByOutput(holder, recipe, parallelLimit, true); // If we are not voiding, and cannot fit any items, return 0 if (limit == 0) { + Component reason = Component.translatable("gtceu.recipe_logic.insufficient_out") + .append(": ") + .append(cap.getName()); + RecipeLogic.putFailureReason(holder, recipe, reason); return 0; } max = Math.min(max, limit); diff --git a/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/RecipeModifierList.java b/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/RecipeModifierList.java index 020ce9e4f10..533b131e481 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/RecipeModifierList.java +++ b/src/main/java/com/gregtechceu/gtceu/api/recipe/modifier/RecipeModifierList.java @@ -1,6 +1,7 @@ package com.gregtechceu.gtceu.api.recipe.modifier; import com.gregtechceu.gtceu.api.machine.MetaMachine; +import com.gregtechceu.gtceu.api.machine.trait.RecipeLogic; import com.gregtechceu.gtceu.api.recipe.GTRecipe; import lombok.Getter; @@ -37,7 +38,10 @@ public RecipeModifierList(RecipeModifier... modifiers) { for (RecipeModifier modifier : modifiers) { var func = modifier.getModifier(machine, runningRecipe); runningRecipe = func.apply(runningRecipe); - if (runningRecipe == null) return ModifierFunction.NULL; + if (runningRecipe == null) { + RecipeLogic.putFailureReason(machine, recipe, func.getFailReason()); + return ModifierFunction.NULL; + } result = func.compose(result); } return result; diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeModifiers.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeModifiers.java index ba1fa7bba54..0bbf5f33ac0 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeModifiers.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeModifiers.java @@ -20,6 +20,7 @@ import net.minecraft.Util; import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import org.jetbrains.annotations.NotNull; @@ -38,7 +39,8 @@ public class GTRecipeModifiers { .memoize(logic -> (machine, recipe) -> { if (!(machine instanceof IOverclockMachine overclockMachine)) return ModifierFunction.IDENTITY; if (RecipeHelper.getRecipeEUtTier(recipe) > overclockMachine.getMaxOverclockTier()) { - return ModifierFunction.NULL; + return ModifierFunction + .cancel(Component.translatable("gtceu.recipe_modifier.insufficient_voltage")); } return logic.getModifier(machine, recipe, overclockMachine.getOverclockVoltage()); }); @@ -174,11 +176,11 @@ public class GTRecipeModifiers { (100 * Math.max(0, coilMachine.getTier() - GTValues.MV)); int recipeTemp = recipe.data.getInt("ebf_temp"); if (!recipe.data.contains("ebf_temp") || recipeTemp > blastFurnaceTemperature) { - return ModifierFunction.NULL; + return ModifierFunction.cancel(Component.translatable("gtceu.recipe_modifier.coil_temperature_too_low")); } if (RecipeHelper.getRecipeEUtTier(recipe) > coilMachine.getTier()) { - return ModifierFunction.NULL; + return ModifierFunction.cancel(Component.translatable("gtceu.recipe_modifier.insufficient_voltage")); } var discount = ModifierFunction.builder() diff --git a/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/FusionReactorMachine.java b/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/FusionReactorMachine.java index 3b14be3ad8b..f1409069226 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/FusionReactorMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/common/machine/multiblock/electric/FusionReactorMachine.java @@ -185,7 +185,8 @@ public static ModifierFunction recipeModifier(@NotNull MetaMachine machine, @Not if (RecipeHelper.getRecipeEUtTier(recipe) > fusionReactorMachine.getTier() || !recipe.data.contains("eu_to_start") || recipe.data.getLong("eu_to_start") > fusionReactorMachine.energyContainer.getEnergyCapacity()) { - return ModifierFunction.NULL; + return ModifierFunction + .cancel(Component.translatable("gtceu.recipe_modifier.insufficient_eu_to_start_fusion")); } long heatDiff = recipe.data.getLong("eu_to_start") - fusionReactorMachine.heat; @@ -195,7 +196,9 @@ public static ModifierFunction recipeModifier(@NotNull MetaMachine machine, @Not return FUSION_OC.getModifier(machine, recipe, fusionReactorMachine.getMaxVoltage(), false); } // if the remaining energy needed is more than stored, do not run - if (fusionReactorMachine.energyContainer.getEnergyStored() < heatDiff) return ModifierFunction.NULL; + if (fusionReactorMachine.energyContainer.getEnergyStored() < heatDiff) + return ModifierFunction + .cancel(Component.translatable("gtceu.recipe_modifier.insufficient_eu_to_start_fusion")); // remove the energy needed fusionReactorMachine.energyContainer.removeEnergy(heatDiff); diff --git a/src/main/java/com/gregtechceu/gtceu/common/recipe/condition/AdjacentFluidCondition.java b/src/main/java/com/gregtechceu/gtceu/common/recipe/condition/AdjacentFluidCondition.java index 01bd029cca2..ab88dd84729 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/recipe/condition/AdjacentFluidCondition.java +++ b/src/main/java/com/gregtechceu/gtceu/common/recipe/condition/AdjacentFluidCondition.java @@ -93,7 +93,12 @@ public RecipeConditionType getType() { @Override public Component getTooltips() { - return Component.translatable("recipe.condition.adjacent_fluid.tooltip"); + var tooltips = Component.translatable("recipe.condition.adjacent_fluid.tooltip"); + fluids.forEach(set -> { + var id = set.get().get(0).get().getFluidType().getDescription(); + tooltips.append(" ").append(id); + }); + return tooltips; } @Override 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 e515846b6cf..3850fc67e8c 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java @@ -28,6 +28,7 @@ public static void init(RegistrateLangProvider provider) { MachineLang.init(provider); ToolLang.init(provider); ConfigurationLang.init(provider); + RecipeLogicLang.init(provider); provider.add("gtceu.gui.editor.tips.citation", "Number of citations"); provider.add("gtceu.gui.editor.group.recipe_type", "cap"); @@ -1263,12 +1264,7 @@ public static void init(RegistrateLangProvider provider) { provider.add("gtceu.button.hide_depleted", "Hide Depleted Veins"); provider.add("gtceu.button.show_depleted", "Show Depleted Veins"); provider.add("gtceu.recipe_type.show_recipes", "Show Recipes"); - provider.add("gtceu.recipe_logic.insufficient_fuel", "Insufficient Fuel"); - provider.add("gtceu.recipe_logic.insufficient_in", "Insufficient Inputs"); - provider.add("gtceu.recipe_logic.insufficient_out", "Insufficient Outputs"); - provider.add("gtceu.recipe_logic.condition_fails", "Condition Fails"); - provider.add("gtceu.recipe_logic.no_contents", "Recipe has no Contents"); - provider.add("gtceu.recipe_logic.no_capabilities", "Machine has no Capabilities"); + provider.add("gtceu.gui.cover_setting.title", "Cover Settings"); provider.add("gtceu.gui.output_setting.title", "Output Settings"); provider.add("gtceu.gui.circuit.title", "Circuit Settings"); diff --git a/src/main/java/com/gregtechceu/gtceu/data/lang/RecipeLogicLang.java b/src/main/java/com/gregtechceu/gtceu/data/lang/RecipeLogicLang.java new file mode 100644 index 00000000000..3146df4ba7b --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/data/lang/RecipeLogicLang.java @@ -0,0 +1,31 @@ +package com.gregtechceu.gtceu.data.lang; + +import com.tterrag.registrate.providers.RegistrateLangProvider; + +public class RecipeLogicLang { + + public static void init(RegistrateLangProvider provider) { + initGenericLang(provider); + initModifierLang(provider); + } + + private static void initGenericLang(RegistrateLangProvider provider) { + provider.add("gtceu.recipe_logic.setup_fail", "Fail to setup recipe: "); + provider.add("gtceu.recipe_logic.recipe_waiting", "Recipe Waiting: "); + + provider.add("gtceu.recipe_logic.insufficient_fuel", "Insufficient Fuel"); + provider.add("gtceu.recipe_logic.insufficient_in", "Insufficient Inputs"); + provider.add("gtceu.recipe_logic.insufficient_out", "Insufficient Outputs"); + provider.add("gtceu.recipe_logic.condition_fails", "Condition Fails"); + provider.add("gtceu.recipe_logic.no_contents", "Recipe has no Contents"); + provider.add("gtceu.recipe_logic.no_capabilities", "Machine has no Capabilities"); + } + + private static void initModifierLang(RegistrateLangProvider provider) { + provider.add("gtceu.recipe_modifier.default_fail", "Recipe Modifier Fail"); + provider.add("gtceu.recipe_modifier.insufficient_voltage", "Voltage Tier Too Low"); + provider.add("gtceu.recipe_modifier.insufficient_eu_to_start_fusion", + "Insufficient Energy to Initiate Fusion Reaction"); + provider.add("gtceu.recipe_modifier.coil_temperature_too_low", "Coil Temperature Too Low"); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/integration/jade/provider/RecipeLogicProvider.java b/src/main/java/com/gregtechceu/gtceu/integration/jade/provider/RecipeLogicProvider.java index f3541c0813a..021fa0bef86 100644 --- a/src/main/java/com/gregtechceu/gtceu/integration/jade/provider/RecipeLogicProvider.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/jade/provider/RecipeLogicProvider.java @@ -4,6 +4,7 @@ import com.gregtechceu.gtceu.api.GTValues; import com.gregtechceu.gtceu.api.blockentity.MetaMachineBlockEntity; import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper; +import com.gregtechceu.gtceu.api.machine.feature.IRecipeLogicMachine; import com.gregtechceu.gtceu.api.machine.steam.SimpleSteamMachine; import com.gregtechceu.gtceu.api.machine.trait.RecipeLogic; import com.gregtechceu.gtceu.api.recipe.RecipeHelper; @@ -127,6 +128,20 @@ protected void addTooltip(CompoundTag capData, ITooltip tooltip, Player player, } } } + } else { + if (blockEntity instanceof MetaMachineBlockEntity mbe && + mbe.metaMachine instanceof IRecipeLogicMachine rlm) { + var logic = rlm.getRecipeLogic(); + + if (logic.showFancyTooltip() && logic.isWorkingEnabled()) { + Component status = logic.isWaiting() ? + Component.translatable("gtceu.recipe_logic.recipe_waiting") + .withStyle(ChatFormatting.YELLOW) : + Component.translatable("gtceu.recipe_logic.setup_fail").withStyle(ChatFormatting.RED); + tooltip.add(status); + logic.getFancyTooltip().forEach(tooltip::add); + } + } } } }