From 189bc3df87403efa666e03de9fbc7a25fcebb9bb Mon Sep 17 00:00:00 2001 From: lulu2002 Date: Sun, 18 Aug 2024 17:06:35 +0800 Subject: [PATCH 1/3] feat: make LegacyAdventureUtil supports hex color format (ex: &#ffffff) --- .../bukkit/util/LegacyAdventureUtil.java | 109 +++++++++--------- .../bukkit/util/LegacyAdventureUtilTest.java | 37 ++++++ 2 files changed, 90 insertions(+), 56 deletions(-) create mode 100644 framework/platforms/bukkit-platform/src/test/java/io/fairyproject/bukkit/util/LegacyAdventureUtilTest.java diff --git a/framework/platforms/bukkit-platform/src/main/java/io/fairyproject/bukkit/util/LegacyAdventureUtil.java b/framework/platforms/bukkit-platform/src/main/java/io/fairyproject/bukkit/util/LegacyAdventureUtil.java index 13e4e3b8..5948424e 100644 --- a/framework/platforms/bukkit-platform/src/main/java/io/fairyproject/bukkit/util/LegacyAdventureUtil.java +++ b/framework/platforms/bukkit-platform/src/main/java/io/fairyproject/bukkit/util/LegacyAdventureUtil.java @@ -1,22 +1,68 @@ package io.fairyproject.bukkit.util; -import io.fairyproject.mc.MCAdventure; -import lombok.experimental.UtilityClass; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.minimessage.MiniMessage; -import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import org.bukkit.ChatColor; import java.util.HashMap; -import java.util.Locale; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; -@UtilityClass -public class LegacyAdventureUtil { - +public final class LegacyAdventureUtil { private static final Map INDEX = new HashMap<>(); + private static final Pattern HEX_PATTERN = Pattern.compile("&#([A-Fa-f0-9]{6})"); + + public static Component deserialize(String text) { + return MiniMessage.miniMessage().deserialize(fromLegacy(text, '&')); + } + + public static String fromLegacy(String text, char code) { + StringBuilder stringBuilder = new StringBuilder(); + int lastIndex = 0; + + Matcher matcher = HEX_PATTERN.matcher(text); + while (matcher.find()) { + stringBuilder.append(text, lastIndex, matcher.start()); + stringBuilder.append("<#").append(matcher.group(1)).append(">"); + lastIndex = matcher.end(); + } + + if (lastIndex < text.length()) { + stringBuilder.append(text.substring(lastIndex)); + } + + text = stringBuilder.toString(); + stringBuilder.setLength(0); + lastIndex = 0; + + char[] b = text.toCharArray(); + for (int i = 0; i < b.length - 1; ++i) { + if ((b[i] == 167 || b[i] == code) && "0123456789AaBbCcDdEeFfKkLlMmNnOoRrXx".indexOf(b[i + 1]) > -1) { + + if (i > 0) { + stringBuilder.append(text, lastIndex, i); + } + + ChatColor chatColor = ChatColor.getByChar(b[i + 1]); + String s = INDEX.get(chatColor); + stringBuilder.append("<").append(s).append(">"); + lastIndex = i + 2; + } + } + + if (lastIndex < text.length()) { + stringBuilder.append(text.substring(lastIndex)); + } + + return stringBuilder.toString(); + } + + private LegacyAdventureUtil() { + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); + } static { INDEX.put(ChatColor.BLACK, NamedTextColor.BLACK.toString()); @@ -42,53 +88,4 @@ public class LegacyAdventureUtil { INDEX.put(ChatColor.ITALIC, TextDecoration.ITALIC.toString()); INDEX.put(ChatColor.RESET, "reset"); } - - public String decodeAndLegacy(String legacyText) { - return decodeAndLegacy(legacyText, TagResolver.empty()); - } - - public String decodeAndLegacy(String legacyText, TagResolver tagResolver) { - if (legacyText == null || legacyText.isEmpty()) - return ""; - return MCAdventure.asLegacyString( - decode(legacyText, tagResolver), - Locale.ENGLISH - ); - } - - public Component decode(String legacyText) { - return decode(legacyText, TagResolver.empty()); - } - - public Component decode(String legacyText, TagResolver tagResolver) { - if (legacyText == null) - return Component.empty(); - return MiniMessage.miniMessage().deserialize(fromLegacy(legacyText, '&'), tagResolver); - } - - public String fromLegacy(String text, char code) { - if (text == null) - return ""; - StringBuilder stringBuilder = new StringBuilder(); - char[] b = text.toCharArray(); - - int lastIndex = 0; - for(int i = 0; i < b.length - 1; ++i) { - if ((b[i] == 'ยง' || b[i] == code) && "0123456789AaBbCcDdEeFfKkLlMmNnOoRrXx".indexOf(b[i + 1]) > -1) { - if (i > 0) - stringBuilder.append(text, lastIndex, i); - final ChatColor chatColor = ChatColor.getByChar(b[i + 1]); - final String s = INDEX.get(chatColor); - - stringBuilder.append("<").append(s).append(">"); - lastIndex = i + 2; - } - } - - if (lastIndex < text.length()) { - stringBuilder.append(text.substring(lastIndex)); - } - return stringBuilder.toString(); - } - } diff --git a/framework/platforms/bukkit-platform/src/test/java/io/fairyproject/bukkit/util/LegacyAdventureUtilTest.java b/framework/platforms/bukkit-platform/src/test/java/io/fairyproject/bukkit/util/LegacyAdventureUtilTest.java new file mode 100644 index 00000000..055d6e97 --- /dev/null +++ b/framework/platforms/bukkit-platform/src/test/java/io/fairyproject/bukkit/util/LegacyAdventureUtilTest.java @@ -0,0 +1,37 @@ +package io.fairyproject.bukkit.util; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextColor; +import net.kyori.adventure.text.minimessage.MiniMessage; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class LegacyAdventureUtilTest { + + @Test + public void shouldParseLegacyChatColor() { + assertEquals( + LegacyAdventureUtil.deserialize("&6Hello"), + Component.text("Hello").color(NamedTextColor.GOLD) + ); + } + + @Test + public void shouldParseHexColor() { + assertEquals( + LegacyAdventureUtil.deserialize("&#ff0000Hello"), + Component.text("Hello").color(TextColor.color(255, 0, 0)) + ); + } + + @Test + public void complexTestcases() { + assertEquals( + LegacyAdventureUtil.deserialize("&7[&r&#b92b27&lW&#aa235a&lO a1b8d&lRb13c0&lK&7]"), + MiniMessage.miniMessage().deserialize("[<#b92b27>W<#aa235a>O<#9a1b8d>R<#8b13c0>K]") + ); + } +} + From d49d018ff626a1e6e1e55fbc4fc5e977a2db0fbb Mon Sep 17 00:00:00 2001 From: lulu2002 Date: Sun, 18 Aug 2024 17:12:25 +0800 Subject: [PATCH 2/3] fix: add back old methods --- .../bukkit/util/LegacyAdventureUtil.java | 87 ++++++++++++------- .../bukkit/util/LegacyAdventureUtilTest.java | 9 +- 2 files changed, 60 insertions(+), 36 deletions(-) diff --git a/framework/platforms/bukkit-platform/src/main/java/io/fairyproject/bukkit/util/LegacyAdventureUtil.java b/framework/platforms/bukkit-platform/src/main/java/io/fairyproject/bukkit/util/LegacyAdventureUtil.java index 5948424e..08358294 100644 --- a/framework/platforms/bukkit-platform/src/main/java/io/fairyproject/bukkit/util/LegacyAdventureUtil.java +++ b/framework/platforms/bukkit-platform/src/main/java/io/fairyproject/bukkit/util/LegacyAdventureUtil.java @@ -1,29 +1,78 @@ package io.fairyproject.bukkit.util; +import io.fairyproject.mc.MCAdventure; +import lombok.experimental.UtilityClass; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import org.bukkit.ChatColor; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -public final class LegacyAdventureUtil { +@UtilityClass +public class LegacyAdventureUtil { + private static final Map INDEX = new HashMap<>(); - private static final Pattern HEX_PATTERN = Pattern.compile("&#([A-Fa-f0-9]{6})"); - public static Component deserialize(String text) { - return MiniMessage.miniMessage().deserialize(fromLegacy(text, '&')); + static { + INDEX.put(ChatColor.BLACK, NamedTextColor.BLACK.toString()); + INDEX.put(ChatColor.DARK_BLUE, NamedTextColor.DARK_BLUE.toString()); + INDEX.put(ChatColor.DARK_GREEN, NamedTextColor.DARK_GREEN.toString()); + INDEX.put(ChatColor.DARK_AQUA, NamedTextColor.DARK_AQUA.toString()); + INDEX.put(ChatColor.DARK_RED, NamedTextColor.DARK_RED.toString()); + INDEX.put(ChatColor.DARK_PURPLE, NamedTextColor.DARK_PURPLE.toString()); + INDEX.put(ChatColor.GOLD, NamedTextColor.GOLD.toString()); + INDEX.put(ChatColor.GRAY, NamedTextColor.GRAY.toString()); + INDEX.put(ChatColor.DARK_GRAY, NamedTextColor.DARK_GRAY.toString()); + INDEX.put(ChatColor.BLUE, NamedTextColor.BLUE.toString()); + INDEX.put(ChatColor.GREEN, NamedTextColor.GREEN.toString()); + INDEX.put(ChatColor.AQUA, NamedTextColor.AQUA.toString()); + INDEX.put(ChatColor.RED, NamedTextColor.RED.toString()); + INDEX.put(ChatColor.LIGHT_PURPLE, NamedTextColor.LIGHT_PURPLE.toString()); + INDEX.put(ChatColor.YELLOW, NamedTextColor.YELLOW.toString()); + INDEX.put(ChatColor.WHITE, NamedTextColor.WHITE.toString()); + INDEX.put(ChatColor.MAGIC, TextDecoration.OBFUSCATED.toString()); + INDEX.put(ChatColor.BOLD, TextDecoration.BOLD.toString()); + INDEX.put(ChatColor.STRIKETHROUGH, TextDecoration.STRIKETHROUGH.toString()); + INDEX.put(ChatColor.UNDERLINE, TextDecoration.UNDERLINED.toString()); + INDEX.put(ChatColor.ITALIC, TextDecoration.ITALIC.toString()); + INDEX.put(ChatColor.RESET, "reset"); + } + + public String decodeAndLegacy(String legacyText) { + return decodeAndLegacy(legacyText, TagResolver.empty()); + } + + public String decodeAndLegacy(String legacyText, TagResolver tagResolver) { + if (legacyText == null || legacyText.isEmpty()) + return ""; + return MCAdventure.asLegacyString( + decode(legacyText, tagResolver), + Locale.ENGLISH + ); + } + + public Component decode(String legacyText) { + return decode(legacyText, TagResolver.empty()); + } + + public Component decode(String legacyText, TagResolver tagResolver) { + if (legacyText == null) + return Component.empty(); + return MiniMessage.miniMessage().deserialize(fromLegacy(legacyText, '&'), tagResolver); } public static String fromLegacy(String text, char code) { StringBuilder stringBuilder = new StringBuilder(); int lastIndex = 0; - Matcher matcher = HEX_PATTERN.matcher(text); + Matcher matcher = getHexPattern(code).matcher(text); while (matcher.find()) { stringBuilder.append(text, lastIndex, matcher.start()); stringBuilder.append("<#").append(matcher.group(1)).append(">"); @@ -60,32 +109,8 @@ public static String fromLegacy(String text, char code) { return stringBuilder.toString(); } - private LegacyAdventureUtil() { - throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); + private Pattern getHexPattern(char code) { + return Pattern.compile(code + "#([A-Fa-f0-9]{6})"); } - static { - INDEX.put(ChatColor.BLACK, NamedTextColor.BLACK.toString()); - INDEX.put(ChatColor.DARK_BLUE, NamedTextColor.DARK_BLUE.toString()); - INDEX.put(ChatColor.DARK_GREEN, NamedTextColor.DARK_GREEN.toString()); - INDEX.put(ChatColor.DARK_AQUA, NamedTextColor.DARK_AQUA.toString()); - INDEX.put(ChatColor.DARK_RED, NamedTextColor.DARK_RED.toString()); - INDEX.put(ChatColor.DARK_PURPLE, NamedTextColor.DARK_PURPLE.toString()); - INDEX.put(ChatColor.GOLD, NamedTextColor.GOLD.toString()); - INDEX.put(ChatColor.GRAY, NamedTextColor.GRAY.toString()); - INDEX.put(ChatColor.DARK_GRAY, NamedTextColor.DARK_GRAY.toString()); - INDEX.put(ChatColor.BLUE, NamedTextColor.BLUE.toString()); - INDEX.put(ChatColor.GREEN, NamedTextColor.GREEN.toString()); - INDEX.put(ChatColor.AQUA, NamedTextColor.AQUA.toString()); - INDEX.put(ChatColor.RED, NamedTextColor.RED.toString()); - INDEX.put(ChatColor.LIGHT_PURPLE, NamedTextColor.LIGHT_PURPLE.toString()); - INDEX.put(ChatColor.YELLOW, NamedTextColor.YELLOW.toString()); - INDEX.put(ChatColor.WHITE, NamedTextColor.WHITE.toString()); - INDEX.put(ChatColor.MAGIC, TextDecoration.OBFUSCATED.toString()); - INDEX.put(ChatColor.BOLD, TextDecoration.BOLD.toString()); - INDEX.put(ChatColor.STRIKETHROUGH, TextDecoration.STRIKETHROUGH.toString()); - INDEX.put(ChatColor.UNDERLINE, TextDecoration.UNDERLINED.toString()); - INDEX.put(ChatColor.ITALIC, TextDecoration.ITALIC.toString()); - INDEX.put(ChatColor.RESET, "reset"); - } } diff --git a/framework/platforms/bukkit-platform/src/test/java/io/fairyproject/bukkit/util/LegacyAdventureUtilTest.java b/framework/platforms/bukkit-platform/src/test/java/io/fairyproject/bukkit/util/LegacyAdventureUtilTest.java index 055d6e97..09e6ae4e 100644 --- a/framework/platforms/bukkit-platform/src/test/java/io/fairyproject/bukkit/util/LegacyAdventureUtilTest.java +++ b/framework/platforms/bukkit-platform/src/test/java/io/fairyproject/bukkit/util/LegacyAdventureUtilTest.java @@ -13,7 +13,7 @@ public class LegacyAdventureUtilTest { @Test public void shouldParseLegacyChatColor() { assertEquals( - LegacyAdventureUtil.deserialize("&6Hello"), + LegacyAdventureUtil.decode("&6Hello"), Component.text("Hello").color(NamedTextColor.GOLD) ); } @@ -21,7 +21,7 @@ public void shouldParseLegacyChatColor() { @Test public void shouldParseHexColor() { assertEquals( - LegacyAdventureUtil.deserialize("&#ff0000Hello"), + LegacyAdventureUtil.decode("&#ff0000Hello"), Component.text("Hello").color(TextColor.color(255, 0, 0)) ); } @@ -29,9 +29,8 @@ public void shouldParseHexColor() { @Test public void complexTestcases() { assertEquals( - LegacyAdventureUtil.deserialize("&7[&r&#b92b27&lW&#aa235a&lO a1b8d&lRb13c0&lK&7]"), + LegacyAdventureUtil.decode("&7[&r&#b92b27&lW&#aa235a&lO a1b8d&lRb13c0&lK&7]"), MiniMessage.miniMessage().deserialize("[<#b92b27>W<#aa235a>O<#9a1b8d>R<#8b13c0>K]") ); } -} - +} \ No newline at end of file From c1cb9270ff909d8645b7b0b5c912296f61d96437 Mon Sep 17 00:00:00 2001 From: lulu2002 Date: Sun, 18 Aug 2024 17:13:27 +0800 Subject: [PATCH 3/3] chore: remove static keywords for 'fromLegacy' method since it's not neededg --- .../java/io/fairyproject/bukkit/util/LegacyAdventureUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/platforms/bukkit-platform/src/main/java/io/fairyproject/bukkit/util/LegacyAdventureUtil.java b/framework/platforms/bukkit-platform/src/main/java/io/fairyproject/bukkit/util/LegacyAdventureUtil.java index 08358294..5a0da094 100644 --- a/framework/platforms/bukkit-platform/src/main/java/io/fairyproject/bukkit/util/LegacyAdventureUtil.java +++ b/framework/platforms/bukkit-platform/src/main/java/io/fairyproject/bukkit/util/LegacyAdventureUtil.java @@ -68,7 +68,7 @@ public Component decode(String legacyText, TagResolver tagResolver) { return MiniMessage.miniMessage().deserialize(fromLegacy(legacyText, '&'), tagResolver); } - public static String fromLegacy(String text, char code) { + public String fromLegacy(String text, char code) { StringBuilder stringBuilder = new StringBuilder(); int lastIndex = 0;