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.
This commit is contained in:
Aikar 2020-05-31 03:20:31 -04:00
parent afc1fcfc2e
commit 53ef67b88d
No known key found for this signature in database
GPG Key ID: 401ADFC9891FAAFE

View File

@ -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. 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 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 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java
+++ b/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 ""; if (component == null) return "";
StringBuilder out = new StringBuilder(); StringBuilder out = new StringBuilder();
@ -26,19 +35,26 @@ index 2e162b9ea31c8bf81cfa5282566b37fc29537f51..b67f3ac106e76a5f51a1ec9d8dfd2bfe
for (IChatBaseComponent c : (Iterable<IChatBaseComponent>) component) { for (IChatBaseComponent c : (Iterable<IChatBaseComponent>) component) {
ChatModifier modi = c.getChatModifier(); ChatModifier modi = c.getChatModifier();
- out.append(modi.getColor() == null ? defaultColor : modi.getColor()); - out.append(modi.getColor() == null ? defaultColor : modi.getColor());
+ EnumChatFormat color = modi.getColor();
+ if (first) { + if (first) {
+ if (modi.getColor() != null) { + if (color != null) {
+ out.append(modi.getColor()); + 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 + // Paper end
if (modi.isBold()) { if (modi.isBold()) {
out.append(EnumChatFormat.BOLD); out.append(EnumChatFormat.BOLD);
} }
@@ -192,7 +202,7 @@ public final class CraftChatMessage { @@ -192,7 +209,7 @@ public final class CraftChatMessage {
} }
out.append(c.getText()); out.append(c.getText());
} }
@ -47,3 +63,65 @@ index 2e162b9ea31c8bf81cfa5282566b37fc29537f51..b67f3ac106e76a5f51a1ec9d8dfd2bfe
} }
public static IChatBaseComponent fixComponent(IChatBaseComponent component) { 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);
+ }
+}