From e5f30f1e717c5ed92dfd591018f46ce7a1ba69e0 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Thu, 30 Jan 2025 00:49:25 +0000 Subject: [PATCH 1/5] Set color codes after newline --- .../translator/text/MessageTranslator.java | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java index 5c3b21b5a8..2c7d66214d 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java @@ -192,7 +192,39 @@ private static String convertMessage(Component message, String locale, boolean a lastFormatReset = next == 'r'; } - return finalLegacy.toString(); + // This needs a better name + String finalFinalLegacy = finalLegacy.toString(); + StringBuilder output = new StringBuilder(); + + // If the message contains \n then go through and re-set the color after each by caching the last color + // Bedrock is dumb and resets the color after a newline + if (finalFinalLegacy.contains("\n")) { + StringBuilder lastColors = new StringBuilder(); + for (int i = 0; i < finalFinalLegacy.length(); i++) { + char c = finalFinalLegacy.charAt(i); + + output.append(c); + + if (c == ChatColor.ESCAPE) { + char newColor = finalFinalLegacy.charAt(i + 1); + if (newColor == 'r') { + lastColors = new StringBuilder(); + } else { + lastColors.append(ChatColor.ESCAPE).append(newColor); + } + } else if (c == '\n' && !lastColors.isEmpty()) { + output.append(lastColors); + } + } + } else { + output.append(finalFinalLegacy); + } + + if (output.isEmpty()) { + GeyserImpl.getInstance().getLogger().debug("A"); + } + + return output.toString(); } catch (Exception e) { GeyserImpl.getInstance().getLogger().debug(GSON_SERIALIZER.serialize(message)); GeyserImpl.getInstance().getLogger().error("Failed to parse message", e); From 82f84fc1f892fdaa73a9f5506a783bc677025503 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Thu, 30 Jan 2025 00:52:27 +0000 Subject: [PATCH 2/5] Cleanup --- .../translator/text/MessageTranslator.java | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java index 2c7d66214d..7f37d38463 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java @@ -193,20 +193,21 @@ private static String convertMessage(Component message, String locale, boolean a } // This needs a better name - String finalFinalLegacy = finalLegacy.toString(); - StringBuilder output = new StringBuilder(); + String finalLegacyString = finalLegacy.toString(); // If the message contains \n then go through and re-set the color after each by caching the last color // Bedrock is dumb and resets the color after a newline - if (finalFinalLegacy.contains("\n")) { + if (finalLegacyString.contains("\n")) { + StringBuilder output = new StringBuilder(); + StringBuilder lastColors = new StringBuilder(); - for (int i = 0; i < finalFinalLegacy.length(); i++) { - char c = finalFinalLegacy.charAt(i); + for (int i = 0; i < finalLegacyString.length(); i++) { + char c = finalLegacyString.charAt(i); output.append(c); if (c == ChatColor.ESCAPE) { - char newColor = finalFinalLegacy.charAt(i + 1); + char newColor = finalLegacyString.charAt(i + 1); if (newColor == 'r') { lastColors = new StringBuilder(); } else { @@ -216,15 +217,11 @@ private static String convertMessage(Component message, String locale, boolean a output.append(lastColors); } } - } else { - output.append(finalFinalLegacy); - } - if (output.isEmpty()) { - GeyserImpl.getInstance().getLogger().debug("A"); + return output.toString(); + } else { + return finalLegacyString; } - - return output.toString(); } catch (Exception e) { GeyserImpl.getInstance().getLogger().debug(GSON_SERIALIZER.serialize(message)); GeyserImpl.getInstance().getLogger().error("Failed to parse message", e); From d9b38a51e5a03e592fc20782f314e253a2c5de48 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Thu, 30 Jan 2025 01:17:22 +0000 Subject: [PATCH 3/5] Fix and add new test --- .../geyser/translator/text/MessageTranslator.java | 6 ++++++ .../network/translators/chat/MessageTranslatorTest.java | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java index 7f37d38463..790050b74f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java @@ -195,6 +195,12 @@ private static String convertMessage(Component message, String locale, boolean a // This needs a better name String finalLegacyString = finalLegacy.toString(); + // Remove duplicate resets and trailing resets + finalLegacyString = finalLegacyString.replaceAll("(" + RESET + "){2,}", RESET); + if (finalLegacyString.endsWith(RESET)) { + finalLegacyString = finalLegacyString.substring(0, finalLegacyString.length() - 2); + } + // If the message contains \n then go through and re-set the color after each by caching the last color // Bedrock is dumb and resets the color after a newline if (finalLegacyString.contains("\n")) { diff --git a/core/src/test/java/org/geysermc/geyser/network/translators/chat/MessageTranslatorTest.java b/core/src/test/java/org/geysermc/geyser/network/translators/chat/MessageTranslatorTest.java index 85d7ffa9ac..8171d3ada0 100644 --- a/core/src/test/java/org/geysermc/geyser/network/translators/chat/MessageTranslatorTest.java +++ b/core/src/test/java/org/geysermc/geyser/network/translators/chat/MessageTranslatorTest.java @@ -49,7 +49,7 @@ public void setUp() throws Exception { "Plugins (3): §r§aWorldEdit§r§f, §r§aViaVersion§r§f, §r§aGeyser-Spigot"); // RGB downgrade test - messages.put("{\"extra\":[{\"text\":\" \"},{\"color\":\"gold\",\"text\":\"The \"},{\"color\":\"#E14248\",\"obfuscated\":true,\"text\":\"||\"},{\"color\":\"#3AA9FF\",\"bold\":true,\"text\":\"CubeCraft\"},{\"color\":\"#E14248\",\"obfuscated\":true,\"text\":\"||\"},{\"color\":\"gold\",\"text\":\" Network \"},{\"color\":\"green\",\"text\":\"[1.8/1.9+]\\n \"},{\"color\":\"#f5e342\",\"text\":\"✦ \"},{\"color\":\"#b042f5\",\"bold\":true,\"text\":\"N\"},{\"color\":\"#c142f5\",\"bold\":true,\"text\":\"E\"},{\"color\":\"#d342f5\",\"bold\":true,\"text\":\"W\"},{\"color\":\"#e442f5\",\"bold\":true,\"text\":\":\"},{\"color\":\"#f542f5\",\"bold\":true,\"text\":\" \"},{\"color\":\"#bcf542\",\"bold\":true,\"text\":\"A\"},{\"color\":\"#acee3f\",\"bold\":true,\"text\":\"M\"},{\"color\":\"#9ce73c\",\"bold\":true,\"text\":\"O\"},{\"color\":\"#8ce039\",\"bold\":true,\"text\":\"N\"},{\"color\":\"#7cd936\",\"bold\":true,\"text\":\"G\"},{\"color\":\"#6cd233\",\"bold\":true,\"text\":\" \"},{\"color\":\"#5ccb30\",\"bold\":true,\"text\":\"S\"},{\"color\":\"#4cc42d\",\"bold\":true,\"text\":\"L\"},{\"color\":\"#3cbd2a\",\"bold\":true,\"text\":\"I\"},{\"color\":\"#2cb627\",\"bold\":true,\"text\":\"M\"},{\"color\":\"#1caf24\",\"bold\":true,\"text\":\"E\"},{\"color\":\"#0ca821\",\"bold\":true,\"text\":\"S\"},{\"color\":\"#f5e342\",\"text\":\" \"},{\"color\":\"#6d7c87\",\"text\":\"(kinda sus) \"},{\"color\":\"#f5e342\",\"text\":\"✦\"}],\"text\":\"\"}"," §r§6The §r§c§k||§r§b§lCubeCraft§r§c§k||§r§6 Network §r§a[1.8/1.9+]\n" + + messages.put("{\"extra\":[{\"text\":\" \"},{\"color\":\"gold\",\"text\":\"The \"},{\"color\":\"#E14248\",\"obfuscated\":true,\"text\":\"||\"},{\"color\":\"#3AA9FF\",\"bold\":true,\"text\":\"CubeCraft\"},{\"color\":\"#E14248\",\"obfuscated\":true,\"text\":\"||\"},{\"color\":\"gold\",\"text\":\" Network \"},{\"color\":\"green\",\"text\":\"[1.8/1.9+]\\n \"},{\"color\":\"#f5e342\",\"text\":\"✦ \"},{\"color\":\"#b042f5\",\"bold\":true,\"text\":\"N\"},{\"color\":\"#c142f5\",\"bold\":true,\"text\":\"E\"},{\"color\":\"#d342f5\",\"bold\":true,\"text\":\"W\"},{\"color\":\"#e442f5\",\"bold\":true,\"text\":\":\"},{\"color\":\"#f542f5\",\"bold\":true,\"text\":\" \"},{\"color\":\"#bcf542\",\"bold\":true,\"text\":\"A\"},{\"color\":\"#acee3f\",\"bold\":true,\"text\":\"M\"},{\"color\":\"#9ce73c\",\"bold\":true,\"text\":\"O\"},{\"color\":\"#8ce039\",\"bold\":true,\"text\":\"N\"},{\"color\":\"#7cd936\",\"bold\":true,\"text\":\"G\"},{\"color\":\"#6cd233\",\"bold\":true,\"text\":\" \"},{\"color\":\"#5ccb30\",\"bold\":true,\"text\":\"S\"},{\"color\":\"#4cc42d\",\"bold\":true,\"text\":\"L\"},{\"color\":\"#3cbd2a\",\"bold\":true,\"text\":\"I\"},{\"color\":\"#2cb627\",\"bold\":true,\"text\":\"M\"},{\"color\":\"#1caf24\",\"bold\":true,\"text\":\"E\"},{\"color\":\"#0ca821\",\"bold\":true,\"text\":\"S\"},{\"color\":\"#f5e342\",\"text\":\" \"},{\"color\":\"#6d7c87\",\"text\":\"(kinda sus) \"},{\"color\":\"#f5e342\",\"text\":\"✦\"}],\"text\":\"\"}"," §r§6The §r§c§k||§r§b§lCubeCraft§r§c§k||§r§6 Network §r§a[1.8/1.9+]\n§a" + " §r§e✦ §r§d§lN§r§d§lE§r§d§lW§r§d§l:§r§d§l §r§e§lA§r§e§lM§r§e§lO§r§a§lN§r§a§lG§r§a§l §r§a§lS§r§2§lL§r§2§lI§r§q§lM§r§q§lE§r§q§lS§r§e §r§t(kinda sus) §r§e✦"); // Color code format resetting @@ -64,6 +64,11 @@ public void setUp() throws Exception { //messages.put("{\"translate\":\"commands.give.success.single\",\"with\":[{\"text\":\"1\"},{\"color\":\"yellow\",\"hoverEvent\":{\"action\":\"show_item\",\"contents\":{\"id\":\"minecraft:player_head\",\"tag\":\"{SkullOwner:\\\"Camotoy\\\"}\"}},\"translate\":\"chat.square_brackets\",\"with\":[{\"extra\":[{\"translate\":\"block.minecraft.player_head.named\",\"with\":[{\"text\":\"Camotoy\"}]}],\"text\":\"\"}]},{\"insertion\":\"DoctorMad9952\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/tell DoctorMad9952 \"},\"hoverEvent\":{\"action\":\"show_entity\",\"contents\":{\"type\":\"minecraft:player\",\"id\":\"8d712993-d208-3dac-b4d8-f2ce7e7d2b75\",\"name\":{\"text\":\"DoctorMad9952\"}}},\"extra\":[{\"text\":\"DoctorMad9952\"}],\"text\":\"\"}]}", // "Gave 1 §r§e[Camotoy's Head]§r to DoctorMad9952"); + // Newline color restore + messages.put("{\"color\":\"#F7DC77\",\"text\":\" Contribute to a weekly community goal.\\n All participants will receive a reward\\n and the top 3 will get extra bonus prizes!\"}", "§r§e Contribute to a weekly community goal.\n" + + "§e All participants will receive a reward\n" + + "§e and the top 3 will get extra bonus prizes!"); + MessageTranslator.init(); } @@ -81,6 +86,7 @@ public void convertMessageLenient() { Assertions.assertEquals("", MessageTranslator.convertMessageLenient(""), "Empty message is not handled properly"); Assertions.assertEquals("§r§eGame Selector", MessageTranslator.convertMessageLenient("§r§eGame Selector"), "Reset before message is not handled properly"); Assertions.assertEquals("Bold Underline", MessageTranslator.convertMessageLenient("§m§nBold Underline"), "Unimplemented formatting chars not stripped"); + Assertions.assertEquals("Duplicate and redundant reset removal", "§r§r§d[Test]§r", "§r§d[Test]"); } @Test From fb5284da2814cc78128154bf40164401c78a659b Mon Sep 17 00:00:00 2001 From: rtm516 Date: Thu, 30 Jan 2025 01:21:22 +0000 Subject: [PATCH 4/5] Update MessageTranslator.java --- .../org/geysermc/geyser/translator/text/MessageTranslator.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java index 790050b74f..b7f066c620 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/text/MessageTranslator.java @@ -192,7 +192,6 @@ private static String convertMessage(Component message, String locale, boolean a lastFormatReset = next == 'r'; } - // This needs a better name String finalLegacyString = finalLegacy.toString(); // Remove duplicate resets and trailing resets From cbc8271fa14c28134a7a10ef2251a86e4af88e99 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Thu, 30 Jan 2025 09:54:03 +0000 Subject: [PATCH 5/5] Correct the asset for test --- .../geyser/network/translators/chat/MessageTranslatorTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/test/java/org/geysermc/geyser/network/translators/chat/MessageTranslatorTest.java b/core/src/test/java/org/geysermc/geyser/network/translators/chat/MessageTranslatorTest.java index 8171d3ada0..1b1ef485ac 100644 --- a/core/src/test/java/org/geysermc/geyser/network/translators/chat/MessageTranslatorTest.java +++ b/core/src/test/java/org/geysermc/geyser/network/translators/chat/MessageTranslatorTest.java @@ -86,7 +86,7 @@ public void convertMessageLenient() { Assertions.assertEquals("", MessageTranslator.convertMessageLenient(""), "Empty message is not handled properly"); Assertions.assertEquals("§r§eGame Selector", MessageTranslator.convertMessageLenient("§r§eGame Selector"), "Reset before message is not handled properly"); Assertions.assertEquals("Bold Underline", MessageTranslator.convertMessageLenient("§m§nBold Underline"), "Unimplemented formatting chars not stripped"); - Assertions.assertEquals("Duplicate and redundant reset removal", "§r§r§d[Test]§r", "§r§d[Test]"); + Assertions.assertEquals("§r§d[Test]", MessageTranslator.convertMessageLenient("§r§r§d[Test]§r"), "Duplicate and redundant reset removal"); } @Test