From ce30c2bf64e656c4a3e3673e5eaa43c8326977e4 Mon Sep 17 00:00:00 2001 From: Anthony Hilyard Date: Mon, 6 Dec 2021 14:40:08 -0800 Subject: Added support for ItemEdit-specified item color names. Fixed tooltip rect calculation. --- gradle.properties | 2 +- .../com/anthonyhilyard/iceberg/util/ItemColor.java | 33 ++++++++- .../com/anthonyhilyard/iceberg/util/Tooltips.java | 80 +++++++++++++++++++++- 3 files changed, 109 insertions(+), 6 deletions(-) diff --git a/gradle.properties b/gradle.properties index 1fcdaec..a371b32 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,6 +6,6 @@ org.gradle.daemon=false name=${rootProject.name} group=com.anthonyhilyard.${name.toLowerCase()} author=anthonyhilyard -version=1.0.29 +version=1.0.30 mcVersion=1.18 forgeVersion=38.0.12 diff --git a/src/main/java/com/anthonyhilyard/iceberg/util/ItemColor.java b/src/main/java/com/anthonyhilyard/iceberg/util/ItemColor.java index 6f8de4e..3714681 100644 --- a/src/main/java/com/anthonyhilyard/iceberg/util/ItemColor.java +++ b/src/main/java/com/anthonyhilyard/iceberg/util/ItemColor.java @@ -1,12 +1,32 @@ package com.anthonyhilyard.iceberg.util; import net.minecraft.world.item.ItemStack; +import net.minecraft.util.FormattedCharSink; import net.minecraft.network.chat.TextColor; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.Style; import net.minecraft.ChatFormatting; public class ItemColor { + private static class ColorCollector implements FormattedCharSink + { + private TextColor color = null; + + @Override + public boolean accept(int index, Style style, int codePoint) + { + if (style.getColor() != null) + { + color = style.getColor(); + return false; + } + return true; + } + + public TextColor getColor() { return color; } + } + public static TextColor findFirstColorCode(Component textComponent) { // This function finds the first specified color code in the given text component. @@ -36,6 +56,7 @@ public class ItemColor return null; } } + return null; } @@ -61,13 +82,21 @@ public class ItemColor result = item.getHoverName().getStyle().getColor(); } - // Finally if there is a color code specified for the item name, use that. - TextColor formattingColor = findFirstColorCode(item.getItem().getName(item)); + // If there is a color code specified for the item name, use that. + TextColor formattingColor = findFirstColorCode(item.getHoverName()); if (formattingColor != null) { result = formattingColor; } + // Finally, if there is a color style stored per-character, use the first one found. + ColorCollector colorCollector = new ColorCollector(); + item.getHoverName().getVisualOrderText().accept(colorCollector); + if (colorCollector.getColor() != null) + { + result = colorCollector.getColor(); + } + // Fallback to the default TextColor if we somehow haven't found a single valid TextColor. if (result == null) { diff --git a/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java b/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java index b3ab741..1673815 100644 --- a/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java +++ b/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java @@ -2,8 +2,13 @@ package com.anthonyhilyard.iceberg.util; import java.util.ArrayList; import java.util.List; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import com.anthonyhilyard.iceberg.events.RenderTooltipExtEvent; import com.mojang.blaze3d.vertex.PoseStack; @@ -15,10 +20,18 @@ import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.Rect2i; import net.minecraft.client.renderer.MultiBufferSource.BufferSource; import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.locale.Language; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.FormattedText; import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.datafixers.util.Either; + +import net.minecraft.world.inventory.tooltip.TooltipComponent; import net.minecraft.world.item.ItemStack; import com.mojang.math.Matrix4f; + +import net.minecraftforge.client.ForgeHooksClient; import net.minecraftforge.client.event.RenderTooltipEvent; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.client.gui.GuiUtils; @@ -98,8 +111,8 @@ public class Tooltips itemRenderer = Minecraft.getInstance().getItemRenderer(); } - int rectX = rect.getX() - 8; - int rectY = rect.getY() + 18; + int rectX = rect.getX() + 4; + int rectY = rect.getY() + 4; RenderTooltipExtEvent.Pre preEvent = new RenderTooltipExtEvent.Pre(stack, poseStack, rectX, rectY, screenWidth, screenHeight, info.getFont(), info.getComponents(), comparison); if (MinecraftForge.EVENT_BUS.post(preEvent)) @@ -167,6 +180,67 @@ public class Tooltips MinecraftForge.EVENT_BUS.post(postEvent); } + public static List gatherTooltipComponents(ItemStack stack, List textElements, Optional itemComponent, + int mouseX, int screenWidth, int screenHeight, @Nullable Font forcedFont, Font fallbackFont, int maxWidth) + { + Font font = ForgeHooksClient.getTooltipFont(forcedFont, stack, fallbackFont); + List> elements = textElements.stream() + .map((Function>) Either::left) + .collect(Collectors.toCollection(ArrayList::new)); + + itemComponent.ifPresent(c -> elements.add(1, Either.right(c))); + + var event = new RenderTooltipEvent.GatherComponents(stack, screenWidth, screenHeight, elements, maxWidth); + if (MinecraftForge.EVENT_BUS.post(event)) + { + return List.of(); + } + + int tooltipTextWidth = event.getTooltipElements().stream() + .mapToInt(either -> either.map(font::width, component -> 0)) + .max() + .orElse(0); + + boolean needsWrap = false; + + int tooltipX = mouseX + 12; + if (tooltipX + tooltipTextWidth + 4 > screenWidth) + { + tooltipX = mouseX - 16 - tooltipTextWidth; + if (tooltipX < 4) // if the tooltip doesn't fit on the screen + { + if (mouseX > screenWidth / 2) + tooltipTextWidth = mouseX - 12 - 8; + else + tooltipTextWidth = screenWidth - 16 - mouseX; + needsWrap = true; + } + } + + if (event.getMaxWidth() > 0 && tooltipTextWidth > event.getMaxWidth()) + { + tooltipTextWidth = event.getMaxWidth(); + needsWrap = true; + } + + final int tooltipTextWidthFinal = tooltipTextWidth; + if (needsWrap) + { + return event.getTooltipElements().stream() + .flatMap(either -> either.map( + text -> font.split(text, tooltipTextWidthFinal).stream().map(ClientTooltipComponent::create), + component -> Stream.of(ClientTooltipComponent.create(component)) + )) + .toList(); + } + return event.getTooltipElements().stream() + .map(either -> either.map( + text -> ClientTooltipComponent.create(text instanceof Component ? ((Component) text).getVisualOrderText() : Language.getInstance().getVisualOrder(text)), + ClientTooltipComponent::create + )) + .toList(); + } + public static Rect2i calculateRect(final ItemStack stack, PoseStack poseStack, List components, int mouseX, int mouseY,int screenWidth, int screenHeight, int maxTextWidth, Font font) { @@ -215,7 +289,7 @@ public class Tooltips tooltipY = screenHeight - tooltipHeight - 6; } - rect = new Rect2i(tooltipX - 4, tooltipY - 4, tooltipTextWidth + 8, tooltipHeight + 8); + rect = new Rect2i(tooltipX - 2, tooltipY - 4, tooltipTextWidth, tooltipHeight); return rect; } } -- cgit