diff --git a/Common/src/main/java/mezz/jei/common/Internal.java b/Common/src/main/java/mezz/jei/common/Internal.java index 899081082..b729226f1 100644 --- a/Common/src/main/java/mezz/jei/common/Internal.java +++ b/Common/src/main/java/mezz/jei/common/Internal.java @@ -1,6 +1,7 @@ package mezz.jei.common; import com.google.common.base.Preconditions; +import mezz.jei.api.runtime.IIngredientManager; import mezz.jei.common.config.WorldConfig; import mezz.jei.common.gui.textures.Textures; import mezz.jei.common.input.IInternalKeyMappings; @@ -20,6 +21,8 @@ public final class Internal { private static IInternalKeyMappings keyMappings; @Nullable private static IWorldConfig worldConfig; + @Nullable + private static IIngredientManager ingredientManager; private Internal() { @@ -58,4 +61,13 @@ public static IWorldConfig getWorldConfig() { } return worldConfig; } + + public static void setIngredientManager(IIngredientManager ingredientManager) { + Internal.ingredientManager = ingredientManager; + } + + public static IIngredientManager getIngredientManager() { + Preconditions.checkState(ingredientManager != null, "Ingredient Manager has not been created yet."); + return ingredientManager; + } } diff --git a/Common/src/main/java/mezz/jei/common/gui/TooltipRenderer.java b/Common/src/main/java/mezz/jei/common/gui/TooltipRenderer.java index cfc0ddaea..faee7ee62 100644 --- a/Common/src/main/java/mezz/jei/common/gui/TooltipRenderer.java +++ b/Common/src/main/java/mezz/jei/common/gui/TooltipRenderer.java @@ -5,51 +5,91 @@ import mezz.jei.api.ingredients.IIngredientType; import mezz.jei.api.ingredients.ITypedIngredient; import mezz.jei.api.runtime.IIngredientManager; +import mezz.jei.common.Internal; import mezz.jei.common.platform.IPlatformRenderHelper; import mezz.jei.common.platform.Services; +import mezz.jei.common.util.ErrorUtil; +import mezz.jei.core.util.LimitedLogger; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.inventory.tooltip.TooltipComponent; import net.minecraft.world.item.ItemStack; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import java.time.Duration; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; public final class TooltipRenderer { + private static final Logger LOGGER = LogManager.getLogger(); + private static final LimitedLogger LIMITED_LOGGER = new LimitedLogger(LOGGER, Duration.ofSeconds(30)); + private TooltipRenderer() { } public static void drawHoveringText(PoseStack poseStack, List textLines, int x, int y) { Minecraft minecraft = Minecraft.getInstance(); + Screen screen = minecraft.screen; + if (screen == null) { + return; + } Font font = minecraft.font; - drawHoveringText(poseStack, textLines, x, y, ItemStack.EMPTY, font); + IPlatformRenderHelper renderHelper = Services.PLATFORM.getRenderHelper(); + try { + renderHelper.renderTooltip(screen, poseStack, textLines, Optional.empty(), x, y, font, ItemStack.EMPTY); + } catch (RuntimeException e) { + String stringTooltip = getTooltipDebugString(textLines, "\n"); + String message = "Failed to render tooltip:\n" + stringTooltip; + LIMITED_LOGGER.log(Level.ERROR, message, message, stringTooltip, e); + } } public static void drawHoveringText(PoseStack poseStack, List textLines, int x, int y, ITypedIngredient typedIngredient, IIngredientManager ingredientManager) { IIngredientType ingredientType = typedIngredient.getType(); - T ingredient = typedIngredient.getIngredient(); IIngredientRenderer ingredientRenderer = ingredientManager.getIngredientRenderer(ingredientType); - drawHoveringText(poseStack, textLines, x, y, ingredient, ingredientRenderer); + drawHoveringText(poseStack, textLines, x, y, typedIngredient, ingredientRenderer); } - public static void drawHoveringText(PoseStack poseStack, List textLines, int x, int y, T ingredient, IIngredientRenderer ingredientRenderer) { + public static void drawHoveringText(PoseStack poseStack, List textLines, int x, int y, ITypedIngredient typedIngredient, IIngredientRenderer ingredientRenderer) { Minecraft minecraft = Minecraft.getInstance(); + T ingredient = typedIngredient.getIngredient(); Font font = ingredientRenderer.getFontRenderer(minecraft, ingredient); - ItemStack itemStack = ingredient instanceof ItemStack ? (ItemStack) ingredient : ItemStack.EMPTY; - drawHoveringText(poseStack, textLines, x, y, itemStack, font); + drawHoveringText(poseStack, textLines, x, y, typedIngredient, font); } - private static void drawHoveringText(PoseStack poseStack, List textLines, int x, int y, ItemStack itemStack, Font font) { + private static void drawHoveringText(PoseStack poseStack, List textLines, int x, int y, ITypedIngredient typedIngredient, Font font) { Minecraft minecraft = Minecraft.getInstance(); Screen screen = minecraft.screen; if (screen == null) { return; } - Optional tooltipImage = itemStack.getTooltipImage(); + ItemStack itemStack = typedIngredient.getItemStack().orElse(ItemStack.EMPTY); IPlatformRenderHelper renderHelper = Services.PLATFORM.getRenderHelper(); - renderHelper.renderTooltip(screen, poseStack, textLines, tooltipImage, x, y, font, itemStack); + try { + Optional tooltipImage = itemStack.getTooltipImage(); + renderHelper.renderTooltip(screen, poseStack, textLines, tooltipImage, x, y, font, itemStack); + } catch (RuntimeException e) { + T ingredient = typedIngredient.getIngredient(); + IIngredientType type = typedIngredient.getType(); + IIngredientManager ingredientManager = Internal.getIngredientManager(); + String ingredientInfo = ErrorUtil.getIngredientInfo(ingredient, type, ingredientManager); + String stringTooltip = getTooltipDebugString(textLines, "\n"); + String message = String.format("Failed to render tooltip for ingredient %s:\n%s", ingredientInfo, stringTooltip); + LIMITED_LOGGER.log(Level.ERROR, message, message, e); + } + } + + private static String getTooltipDebugString(List textLines, String joinDelimiter) { + return textLines.stream() + .map(Component::plainCopy) + .map(MutableComponent::toString) + .collect(Collectors.joining(joinDelimiter)); } } diff --git a/Gui/src/main/java/mezz/jei/gui/overlay/IngredientGridTooltipHelper.java b/Gui/src/main/java/mezz/jei/gui/overlay/IngredientGridTooltipHelper.java index 352203a50..6e21f0886 100644 --- a/Gui/src/main/java/mezz/jei/gui/overlay/IngredientGridTooltipHelper.java +++ b/Gui/src/main/java/mezz/jei/gui/overlay/IngredientGridTooltipHelper.java @@ -46,17 +46,17 @@ public IngredientGridTooltipHelper( this.colorHelper = colorHelper; } - public void drawTooltip(PoseStack poseStack, int mouseX, int mouseY, ITypedIngredient value) { - IIngredientType ingredientType = value.getType(); - T ingredient = value.getIngredient(); + public void drawTooltip(PoseStack poseStack, int mouseX, int mouseY, ITypedIngredient typedIngredient) { + IIngredientType ingredientType = typedIngredient.getType(); IIngredientRenderer ingredientRenderer = ingredientManager.getIngredientRenderer(ingredientType); IIngredientHelper ingredientHelper = ingredientManager.getIngredientHelper(ingredientType); - List tooltip = getTooltip(ingredient, ingredientRenderer, ingredientHelper); - TooltipRenderer.drawHoveringText(poseStack, tooltip, mouseX, mouseY, ingredient, ingredientRenderer); + List tooltip = getTooltip(typedIngredient, ingredientRenderer, ingredientHelper); + TooltipRenderer.drawHoveringText(poseStack, tooltip, mouseX, mouseY, typedIngredient, ingredientRenderer); } - public List getTooltip(T ingredient, IIngredientRenderer ingredientRenderer, IIngredientHelper ingredientHelper) { + public List getTooltip(ITypedIngredient typedIngredient, IIngredientRenderer ingredientRenderer, IIngredientHelper ingredientHelper) { + T ingredient = typedIngredient.getIngredient(); List ingredientTooltipSafe = IngredientTooltipHelper.getMutableIngredientTooltipSafe(ingredient, ingredientRenderer); List tooltip = modIdHelper.addModNameToIngredientTooltip(ingredientTooltipSafe, ingredient, ingredientHelper); diff --git a/Library/src/main/java/mezz/jei/library/load/PluginLoader.java b/Library/src/main/java/mezz/jei/library/load/PluginLoader.java index 9b12c9137..1012da03c 100644 --- a/Library/src/main/java/mezz/jei/library/load/PluginLoader.java +++ b/Library/src/main/java/mezz/jei/library/load/PluginLoader.java @@ -16,6 +16,7 @@ import mezz.jei.api.runtime.IIngredientManager; import mezz.jei.api.runtime.IIngredientVisibility; import mezz.jei.api.runtime.IScreenHelper; +import mezz.jei.common.Internal; import mezz.jei.common.gui.textures.Textures; import mezz.jei.common.platform.IPlatformFluidHelperInternal; import mezz.jei.common.platform.Services; @@ -74,6 +75,7 @@ public PluginLoader(StartData data, IModIdFormatConfig modIdFormatConfig, IColor IngredientManagerBuilder ingredientManagerBuilder = new IngredientManagerBuilder(subtypeManager, colorHelper); PluginCaller.callOnPlugins("Registering ingredients", plugins, p -> p.registerIngredients(ingredientManagerBuilder)); this.ingredientManager = ingredientManagerBuilder.build(); + Internal.setIngredientManager(ingredientManager); StackHelper stackHelper = new StackHelper(subtypeManager); GuiHelper guiHelper = new GuiHelper(ingredientManager, data.textures());