fix: Support hex RGB colors (#RRGGBB) in chat messages (fixes #2054)

Minecraft 1.16+ servers can send custom hex colors in JSON text
components ("color": "#RRGGBB"). MCC's ChatParser.Color2tag() only
recognized the 16 named colors, silently dropping hex values and
leaving gradient/custom-colored chat as uncolored plain text.

- ChatParser: recognize hex color values and emit internal §#rrggbb
  encoding; extend ColorCodeRegex to match the new format
- ClassicConsoleBackend: resolve §#rrggbb to ANSI escape codes via
  ColorHelper before passing to ConsoleInteractive (adapts to the
  configured ConsoleColorMode: 24-bit, 8-bit, 4-bit, or disable)
- McColorParser (TUI): parse §#rrggbb into exact SolidColorBrush
  for full RGB fidelity in Avalonia
- ChatBot.GetVerbatim(): skip the full 8-char §#rrggbb sequence
  instead of only 2 chars, preventing hex digits from leaking into
  stripped text

Made-with: Cursor
This commit is contained in:
BruceChen 2026-04-06 01:18:05 +08:00
parent 914c56fc6e
commit 7fd70ccf38
4 changed files with 80 additions and 6 deletions

View file

@ -200,7 +200,12 @@ namespace MinecraftClient.Protocol.Message
/// <returns>Color code</returns>
private static string Color2tag(string colorname)
{
return colorname.ToLower() switch
string lower = colorname.ToLower();
if (lower.Length == 7 && lower[0] == '#' && IsHexColor(lower))
return "§" + lower;
return lower switch
{
#pragma warning disable format // @formatter:off
@ -227,6 +232,17 @@ namespace MinecraftClient.Protocol.Message
};
}
private static bool IsHexColor(string s)
{
for (int i = 1; i < s.Length; i++)
{
char c = s[i];
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')))
return false;
}
return true;
}
/// <summary>
/// Specify whether translation rules have been loaded
/// </summary>
@ -443,8 +459,8 @@ namespace MinecraftClient.Protocol.Message
{ "italic", "o" },
};
/// <summary>Matches a single color code (§0§9, §a§f). Used to strip color when replacing.</summary>
private static readonly Regex ColorCodeRegex = new(@"§[0-9a-f]", RegexOptions.Compiled);
/// <summary>Matches a single color code (§0-§9, §a-§f) or a hex color (§#rrggbb). Used to strip color when replacing.</summary>
private static readonly Regex ColorCodeRegex = new(@"§(?:[0-9a-f]|#[0-9a-f]{6})", RegexOptions.Compiled);
/// <summary>
/// Use a JSON Object to build the corresponding string