From 78ce22796e1e6bd0ccc46424f8aaabcc2a1be84d Mon Sep 17 00:00:00 2001 From: DrPerkyLegit <116128211+DrPerkyLegit@users.noreply.github.com> Date: Fri, 26 Jun 2026 17:47:16 -0400 Subject: [PATCH] new color format logic --- Minecraft.Client/ClientConnection.cpp | 2 +- Minecraft.Client/Common/Consoles_App.cpp | 158 +++++++++++------- Minecraft.Client/Common/Consoles_App.h | 2 +- .../Common/UI/UIScene_JoinMenu.cpp | 2 +- 4 files changed, 97 insertions(+), 67 deletions(-) diff --git a/Minecraft.Client/ClientConnection.cpp b/Minecraft.Client/ClientConnection.cpp index dc55cc6a..93e238ae 100644 --- a/Minecraft.Client/ClientConnection.cpp +++ b/Minecraft.Client/ClientConnection.cpp @@ -1637,7 +1637,7 @@ void ClientConnection::handleChat(shared_ptr packet) message = packet->m_stringArgs[0]; message = app.EscapeHTMLString(message); //do this to enforce escaped string - message = app.FormatChatMessage(message); //this needs to be last cause it converts colors to html colors that would have been escaped + message = app.FormatColoredString(message); //this needs to be last cause it converts colors to html colors that would have been escaped } else { message = L""; } diff --git a/Minecraft.Client/Common/Consoles_App.cpp b/Minecraft.Client/Common/Consoles_App.cpp index 717d981b..6c103e53 100644 --- a/Minecraft.Client/Common/Consoles_App.cpp +++ b/Minecraft.Client/Common/Consoles_App.cpp @@ -6901,72 +6901,102 @@ wstring CMinecraftApp::EscapeHTMLString(const wstring& desc) return finalString; } -wstring CMinecraftApp::FormatChatMessage(const wstring& desc, bool applyStyling) -{ - static std::wregex IDS_Pattern(LR"(\{\*IDS_(\d+)\*\})"); //maybe theres a better way to do translateable IDS - static std::wstring_view colorFormatString = L""; - - wstring results = desc; - wchar_t replacements[64]; - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_0), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A70", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_1), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A71", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_2), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A72", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_3), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A73", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_4), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A74", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_5), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A75", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_6), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A76", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_7), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A77", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_8), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A78", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_9), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A79", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_a), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A7a", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_b), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A7b", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_c), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A7c", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_d), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A7d", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_e), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A7e", replacements); - - swprintf(replacements, 64, (applyStyling ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_f), 0xFFFFFFFF); - results = replaceAll(results, L"\u00A7f", replacements); - results = replaceAll(results, L"\u00A7r", replacements); //we only support color so reset is the same as white color - - if (applyStyling) { - std::wsmatch match; - while (std::regex_search(results, match, IDS_Pattern)) { - results = replaceAll(results, match[0], app.GetString(std::stoi(match[1].str()))); - } +eMinecraftColour GetColorFromCode(wchar_t _char) { + switch (_char) { + case L'0': return eHTMLColor_0; + case L'1': return eHTMLColor_1; + case L'2': return eHTMLColor_2; + case L'3': return eHTMLColor_3; + case L'4': return eHTMLColor_4; + case L'5': return eHTMLColor_5; + case L'6': return eHTMLColor_6; + case L'7': return eHTMLColor_7; + case L'8': return eHTMLColor_8; + case L'9': return eHTMLColor_9; + case L'a': return eHTMLColor_a; + case L'b': return eHTMLColor_b; + case L'c': return eHTMLColor_c; + case L'd': return eHTMLColor_d; + case L'e': return eHTMLColor_e; + case L'f': return eHTMLColor_f; + default: return eMinecraftColour_NOT_SET; } - +} - return results; +wstring CMinecraftApp::FormatColoredString(const wstring& string) { + static constexpr std::wstring_view colorFormatString = L""; + + wstring result; + + bool fontOpen = false; + bool italicOpen = false; + + auto CloseItalic = [&]() { + if (italicOpen) { + result += L""; + italicOpen = false; + } + }; + + auto CloseFont = [&]() { + if (fontOpen) { + result += L""; + fontOpen = false; + } + }; + + wchar_t buffer[64]; + + for (size_t i = 0; i < string.length(); ++i) { + if (string[i] == L'\u00A7' && i + 1 < string.length()) { + wchar_t code = towlower(string[i + 1]); + + if (GetColorFromCode(code) != eMinecraftColour_NOT_SET) { + bool restoreItalic = italicOpen; + + CloseItalic(); + CloseFont(); + + swprintf(buffer, _countof(buffer), colorFormatString.data(), GetHTMLColour(GetColorFromCode(code))); + + result += buffer; + fontOpen = true; + + if (restoreItalic) { + result += L""; + italicOpen = true; + } + + ++i; + continue; + } + + if (code == L'o') { + if (!italicOpen) { + result += L""; + italicOpen = true; + } + + ++i; + continue; + } + + if (code == L'r') { + CloseItalic(); + CloseFont(); + + ++i; + continue; + } + } + + result += string[i]; + } + + CloseItalic(); + CloseFont(); + + return result; } wstring CMinecraftApp::GetActionReplacement(int iPad, unsigned char ucAction) diff --git a/Minecraft.Client/Common/Consoles_App.h b/Minecraft.Client/Common/Consoles_App.h index b6fd23d2..7359d700 100644 --- a/Minecraft.Client/Common/Consoles_App.h +++ b/Minecraft.Client/Common/Consoles_App.h @@ -575,7 +575,7 @@ public: int GetHTMLFontSize(EHTMLFontSize size); wstring FormatHTMLString(int iPad, const wstring& desc, int shadowColour = 0xFFFFFFFF, bool override = false); wstring EscapeHTMLString(const wstring &desc); - wstring FormatChatMessage(const wstring& desc, bool applyStyling = true); + wstring FormatColoredString(const wstring& desc); wstring GetActionReplacement(int iPad, unsigned char ucAction); wstring GetVKReplacement(unsigned int uiVKey, bool override = false); wstring GetIconReplacement(unsigned int uiIcon); diff --git a/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp b/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp index 48ee615e..d38d42fc 100644 --- a/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp @@ -374,7 +374,7 @@ void UIScene_JoinMenu::updateServerDescription() { wstring testText = L"\nNothing yet..."; IggyStringUTF16 iggyStr; wstring formattedText = app.EscapeHTMLString(testText); - formattedText = app.FormatChatMessage(formattedText); + formattedText = app.FormatColoredString(formattedText); iggyStr.string = (IggyUTF16*)formattedText.c_str(); iggyStr.length = (unsigned int)formattedText.length();