From fae7ebe7fa51f9064faa55d873cf0d51709d32ec Mon Sep 17 00:00:00 2001 From: Sally Knight Date: Sun, 15 Mar 2026 18:29:09 +0300 Subject: [PATCH] feat(jui): new multiline container item tooltips Backported from Java Edition 1.3.x This replaces the old non-functional tooltips --- .../UI/Screens/AbstractContainerScreen.cpp | 145 ++++++++++++++++-- 1 file changed, 133 insertions(+), 12 deletions(-) diff --git a/Minecraft.Client/UI/Screens/AbstractContainerScreen.cpp b/Minecraft.Client/UI/Screens/AbstractContainerScreen.cpp index 13376b7d7..b88d66eb9 100644 --- a/Minecraft.Client/UI/Screens/AbstractContainerScreen.cpp +++ b/Minecraft.Client/UI/Screens/AbstractContainerScreen.cpp @@ -93,22 +93,143 @@ void AbstractContainerScreen::render(int xm, int ym, float a) renderLabels(); - if (inventory->getCarried() == NULL && hoveredSlot != NULL && hoveredSlot->hasItem()) - { + // 4jcraft: newer tooltips backported from java edition 1.3.x (MCP 7.x) + if (inventory->getCarried() == NULL && hoveredSlot != NULL && + hoveredSlot->hasItem()) { + std::shared_ptr item = hoveredSlot->getItem(); - // std::wstring elementName = trimString(Language::getInstance()->getElementName(hoveredSlot->getItem()->getDescriptionId())); - std::wstring elementName = L""; + // std::wstring elementName = + // trimString(Language::getInstance()->getElementName(hoveredSlot->getItem()->getDescriptionId())); + std::vector elementName; + std::vector* tooltipLines = + item->getHoverText(minecraft->player, false, elementName); - if (elementName.length() > 0) - { - int x = xm - xo + 12; - int y = ym - yo - 12; - int width = font->width(elementName); - fillGradient(x - 3, y - 3, x + width + 3, y + 8 + 3, 0xc0000000, 0xc0000000); + if (tooltipLines != NULL && tooltipLines->size() > 0) { + int tooltipWidth = 0; + std::vector cleanedLines; + std::vector lineColors; - font->drawShadow(elementName, x, y, 0xffffffff); + for (int lineIndex = 0; lineIndex < (int)tooltipLines->size(); + ++lineIndex) { + std::wstring rawLine = (*tooltipLines)[lineIndex]; + std::wstring clean = L""; + int lineColor = 0xffffffff; + + // 4jcraft: LCE is using HTML font elements for its tooltip + // colors, so make sure to parse them for parity w iggy UI + // + // examples would be enchantment books, potions and music + // discs + size_t fontPos = rawLine.find(L"') { + inTag = false; + } else if (!inTag) { + clean += currentChar; + } + } + + cleanedLines.push_back(clean); + lineColors.push_back(lineColor); + + int lineWidth = font->width(clean); + if (lineWidth > tooltipWidth) { + tooltipWidth = lineWidth; + } + } + + int tooltipX = xm - xo + 12; + int tooltipY = ym - yo - 12; + + int tooltipHeight = 8; + + if (tooltipLines->size() > 1) { + tooltipHeight += 2 + (tooltipLines->size() - 1) * 10; + } + + int bgColor = 0xf0100010; + fillGradient(tooltipX - 3, tooltipY - 4, + tooltipX + tooltipWidth + 3, tooltipY - 3, bgColor, + bgColor); + fillGradient(tooltipX - 3, tooltipY + tooltipHeight + 3, + tooltipX + tooltipWidth + 3, + tooltipY + tooltipHeight + 4, bgColor, bgColor); + fillGradient(tooltipX - 3, tooltipY - 3, + tooltipX + tooltipWidth + 3, + tooltipY + tooltipHeight + 3, bgColor, bgColor); + fillGradient(tooltipX - 4, tooltipY - 3, tooltipX - 3, + tooltipY + tooltipHeight + 3, bgColor, bgColor); + fillGradient(tooltipX + tooltipWidth + 3, tooltipY - 3, + tooltipX + tooltipWidth + 4, + tooltipY + tooltipHeight + 3, bgColor, bgColor); + + int borderStart = 0x505000ff; + int borderFinish = + (borderStart & 0xfefefe) >> 1 | borderStart & 0xff000000; + fillGradient(tooltipX - 3, (tooltipY - 3) + 1, (tooltipX - 3) + 1, + (tooltipY + tooltipHeight + 3) - 1, borderStart, + borderFinish); + fillGradient(tooltipX + tooltipWidth + 2, (tooltipY - 3) + 1, + tooltipX + tooltipWidth + 3, + (tooltipY + tooltipHeight + 3) - 1, borderStart, + borderFinish); + fillGradient(tooltipX - 3, tooltipY - 3, + tooltipX + tooltipWidth + 3, (tooltipY - 3) + 1, + borderStart, borderStart); + fillGradient(tooltipX - 3, tooltipY + tooltipHeight + 2, + tooltipX + tooltipWidth + 3, + tooltipY + tooltipHeight + 3, borderFinish, + borderFinish); + + int currentY = tooltipY; + for (int lineIndex = 0; lineIndex < (int)tooltipLines->size(); + ++lineIndex) { + std::wstring& currentLine = cleanedLines[lineIndex]; + int textColor; + + if (lineIndex == 0) { + textColor = app.GetHTMLColour(item->getRarity()->color); + } else { + textColor = (lineColors[lineIndex] != 0xffffffff) + ? lineColors[lineIndex] + : 0xffaaaaaa; + } + + font->drawShadow(currentLine, tooltipX, currentY, textColor); + + if (lineIndex == 0) { + currentY += 2; + } + + currentY += 10; + } } - } glPopMatrix();