@@ -98,6 +98,13 @@ public class Util {
9898 */
9999 private static final Pattern LEGACY_HEX_CODE_PATTERN = Pattern .compile ("&#[0-9a-fA-F]{3,6}|\u00A7 x(\u00A7 [0-9a-fA-F]){6}" );
100100
101+ /**
102+ * Pattern to match the BungeeCord/Spigot {@code &x&R&R&G&G&B&B} hex format
103+ * (after {@code §} has been normalised to {@code &}).
104+ * Produced by {@link LegacyComponentSerializer} with {@code useUnusualXRepeatedCharacterHexFormat()}.
105+ */
106+ private static final Pattern BUNGEE_HEX_PATTERN = Pattern .compile ("&x(&[0-9a-fA-F]){6}" );
107+
101108 /**
102109 * MiniMessage instance for parsing MiniMessage-formatted strings.
103110 */
@@ -1047,6 +1054,10 @@ public static String legacyToMiniMessage(@NonNull String legacy) {
10471054 // First, normalize § to & for uniform processing
10481055 String text = legacy .replace ('\u00A7' , '&' );
10491056
1057+ // Convert BungeeCord/Spigot §x§R§R§G§G§B§B hex format (now &x&R&R...) to &#RRGGBB
1058+ // so the HEX_PATTERN step below handles all hex input uniformly.
1059+ text = normalizeBungeeHex (text );
1060+
10501061 // Convert hex codes &#RRGGBB → <color:#RRGGBB>
10511062 Matcher hexMatcher = HEX_PATTERN .matcher (text );
10521063 StringBuilder sb = new StringBuilder ();
@@ -1211,6 +1222,8 @@ public static String legacyToMiniMessage(@NonNull String legacy) {
12111222 public static String replaceLegacyCodesInline (@ NonNull String text ) {
12121223 // Normalize § to &
12131224 text = text .replace ('\u00A7' , '&' );
1225+ // Convert BungeeCord/Spigot &x&R&R&G&G&B&B hex format to &#RRGGBB (see legacyToMiniMessage)
1226+ text = normalizeBungeeHex (text );
12141227 // Replace hex codes &#RRGGBB → <color:#RRGGBB>
12151228 Matcher hexMatcher = HEX_PATTERN .matcher (text );
12161229 StringBuilder sb = new StringBuilder ();
@@ -1532,6 +1545,30 @@ private static String legacyColorCode(TextColor color) {
15321545 return COLOR_CHAR + Character .toString (code );
15331546 }
15341547
1548+ /**
1549+ * Converts the BungeeCord/Spigot {@code &x&R&R&G&G&B&B} repeated-character hex format
1550+ * (produced after {@code §} → {@code &} normalisation) to the {@code &#RRGGBB} form
1551+ * that {@link #HEX_PATTERN} understands.
1552+ *
1553+ * @param text input string with {@code &} normalised from {@code §}
1554+ * @return string with {@code &x&R&R&G&G&B&B} sequences replaced by {@code &#RRGGBB}
1555+ */
1556+ private static String normalizeBungeeHex (@ NonNull String text ) {
1557+ Matcher m = BUNGEE_HEX_PATTERN .matcher (text );
1558+ if (!m .find ()) {
1559+ return text ;
1560+ }
1561+ StringBuilder sb = new StringBuilder ();
1562+ m .reset ();
1563+ while (m .find ()) {
1564+ // "&x&2&3&8&a&f&0" → strip "&x" prefix and remaining "&" chars → "238af0"
1565+ String digits = m .group (0 ).substring (2 ).replace ("&" , "" );
1566+ m .appendReplacement (sb , "&#" + digits );
1567+ }
1568+ m .appendTail (sb );
1569+ return sb .toString ();
1570+ }
1571+
15351572 /**
15361573 * Serializes an Adventure Component to plain text with no formatting.
15371574 *
0 commit comments