From 53ef67b88d659f1b82edcb131b1d9206396d7e73 Mon Sep 17 00:00:00 2001 From: Aikar Date: Sun, 31 May 2020 03:20:31 -0400 Subject: [PATCH] Improve Chat Component Legacy Serialization more This brings chat componenent serialization to 100% accuracy so that any text input in the legacy format, converting to comps and then back to legacy will result in identical results. If the user explicitly sets a color as prefix to a string, it is retained, even if that color matches the default. This also helps improve dealing with the empty string wrappers Bukkit creates. A unit test has been added to verify this behavior. --- ...ialization-of-colors-from-components.patch | 94 +++++++++++++++++-- 1 file changed, 86 insertions(+), 8 deletions(-) diff --git a/Spigot-Server-Patches/0534-Fix-serialization-of-colors-from-components.patch b/Spigot-Server-Patches/0534-Fix-serialization-of-colors-from-components.patch index 820ae90b43..0cfae32a75 100644 --- a/Spigot-Server-Patches/0534-Fix-serialization-of-colors-from-components.patch +++ b/Spigot-Server-Patches/0534-Fix-serialization-of-colors-from-components.patch @@ -14,10 +14,19 @@ saving an ItemStack in a Yaml config). Spigot has now made the issue worse and expanded the scope to more places. diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -index 2e162b9ea31c8bf81cfa5282566b37fc29537f51..b67f3ac106e76a5f51a1ec9d8dfd2bfecebaa439 100644 +index 2e162b9ea31c8bf81cfa5282566b37fc29537f51..e2fbbfdd5b678f632ddbd68ec33a7cd9adfd4955 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -@@ -172,9 +172,19 @@ public final class CraftChatMessage { +@@ -67,7 +67,7 @@ public final class CraftChatMessage { + case 1: + EnumChatFormat format = formatMap.get(match.toLowerCase(java.util.Locale.ENGLISH).charAt(1)); + if (format == EnumChatFormat.RESET) { +- modifier = new ChatModifier(); ++ modifier = new ChatModifier().setColor(format); // Paper + } else if (format.isFormat()) { + switch (format) { + case BOLD: +@@ -172,9 +172,26 @@ public final class CraftChatMessage { if (component == null) return ""; StringBuilder out = new StringBuilder(); @@ -26,19 +35,26 @@ index 2e162b9ea31c8bf81cfa5282566b37fc29537f51..b67f3ac106e76a5f51a1ec9d8dfd2bfe for (IChatBaseComponent c : (Iterable) component) { ChatModifier modi = c.getChatModifier(); - out.append(modi.getColor() == null ? defaultColor : modi.getColor()); ++ EnumChatFormat color = modi.getColor(); + if (first) { -+ if (modi.getColor() != null) { -+ out.append(modi.getColor()); ++ if (color != null) { ++ out.append(color); ++ } ++ if (!c.getText().isEmpty() || color != null) { ++ first = false; ++ } ++ } else if (!c.getText().isEmpty() || color != null) { ++ if (color != null) { ++ out.append(color); ++ } else if (defaultColor != null) { ++ out.append(defaultColor); + } -+ first = false; -+ } else { -+ out.append(modi.getColor() == null ? defaultColor : modi.getColor()); + } + // Paper end if (modi.isBold()) { out.append(EnumChatFormat.BOLD); } -@@ -192,7 +202,7 @@ public final class CraftChatMessage { +@@ -192,7 +209,7 @@ public final class CraftChatMessage { } out.append(c.getText()); } @@ -47,3 +63,65 @@ index 2e162b9ea31c8bf81cfa5282566b37fc29537f51..b67f3ac106e76a5f51a1ec9d8dfd2bfe } public static IChatBaseComponent fixComponent(IChatBaseComponent component) { +diff --git a/src/test/java/org/bukkit/craftbukkit/CraftChatMessageTest.java b/src/test/java/org/bukkit/craftbukkit/CraftChatMessageTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4a3b3ef168415ec8813afaa9f0c1657b078f8bf4 +--- /dev/null ++++ b/src/test/java/org/bukkit/craftbukkit/CraftChatMessageTest.java +@@ -0,0 +1,56 @@ ++package org.bukkit.craftbukkit; ++ ++import net.minecraft.server.EnumChatFormat; ++import net.minecraft.server.IChatBaseComponent; ++import org.bukkit.ChatColor; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.support.AbstractTestingBase; ++import org.junit.Test; ++ ++import static org.junit.Assert.assertEquals; ++ ++public class CraftChatMessageTest extends AbstractTestingBase { ++ @Test ++ public void testSimpleStrings() { ++ testString("&fFoo", EnumChatFormat.WHITE); ++ testString("Foo", EnumChatFormat.WHITE); ++ testString("Foo&bBar", EnumChatFormat.WHITE); ++ testString("Foo&bBar", EnumChatFormat.AQUA); ++ testString("&fFoo&bBar", EnumChatFormat.WHITE); ++ testString("&rFoo", EnumChatFormat.WHITE); ++ } ++ ++ @Test ++ public void testComponents() { ++ testComponent("Foo&bBar&fBaz", EnumChatFormat.WHITE, create("Foo", "&bBar", "Baz")); ++ testComponent("&fFoo&bBar&fBaz", EnumChatFormat.WHITE, create("", "&fFoo", "&bBar", "Baz")); ++ testComponent("Foo&bBar&fBaz", EnumChatFormat.WHITE, create("", "Foo", "&bBar", "Baz")); ++ testComponent("&fFoo&bBar&fBaz", EnumChatFormat.WHITE, create("&fFoo", "&bBar", "Baz")); ++ testComponent("F&foo&bBar&fBaz", EnumChatFormat.WHITE, create("F&foo", "&bBar", "Baz")); ++ } ++ ++ private IChatBaseComponent create(String txt, String ...rest) { ++ IChatBaseComponent cmp = toComp(txt); ++ for (String s : rest) { ++ cmp.addSibling(toComp(s)); ++ } ++ ++ return cmp; ++ } ++ ++ private IChatBaseComponent toComp(String txt) { ++ return CraftChatMessage.fromString(ChatColor.translateAlternateColorCodes('&', txt))[0]; ++ } ++ ++ private void testString(String expected, EnumChatFormat defColor) { ++ expected = ChatColor.translateAlternateColorCodes('&', expected); ++ IChatBaseComponent cmp = CraftChatMessage.fromStringOrNull(expected); ++ testComponent(expected, defColor, cmp); ++ } ++ ++ private void testComponent(String expected, EnumChatFormat defColor, IChatBaseComponent components) { ++ expected = ChatColor.translateAlternateColorCodes('&', expected); ++ String actual = CraftChatMessage.fromComponent(components, defColor); ++ assertEquals(expected, actual); ++ } ++}