WrappedServerPing: Properly translate MotD to components for RGB colors (#1152)

In previous Minecraft versions, using WrappedServerPing.setMotD(String)
behaved exactly like using Bukkit's ServerListPingEvent.setMotd(String).

With the addition of RGB colors in Minecraft 1.16, Spigot's
ServerListPingEvent was patched to translate the MotD string to the
chat component equivalent to make it possible to use RGB colors in MotDs.
In general, using raw legacy color codes (e.g. §c) within a (JSON) text
component tends to cause weird issues on newer Minecraft versions,
so it's better to translate them to the JSON equivalents on the server.

However, the WrappedServerPing implementation in ProtocolLib was never
updated with the same change, which makes it behave differently from
Spigot's ServerListPingEvent now. Using ServerListPingEvent RGB color
codes work, using ProtocolLib they do not work.

To fix this, this commit changes WrappedServerPing.setMotD(String) to
use the same method as Spigot for translating the legacy text to the
JSON/chat component equivalent.

This allows for example ServerListPlus to use Spigot's RGB color codes
(e.g. &x&7&9&b&8&f&fHello) without requiring any changes in ServerListPlus.
This commit is contained in:
Minecrell 2021-05-02 23:43:32 +02:00 committed by GitHub
parent 0c01a11755
commit b3ccf82597
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 18 additions and 3 deletions

View File

@ -50,7 +50,7 @@ public class WrappedChatComponent extends AbstractWrapper implements ClonableWra
} }
// Get a component from a standard Minecraft message // Get a component from a standard Minecraft message
CONSTRUCT_COMPONENT = Accessors.getMethodAccessor(MinecraftReflection.getCraftChatMessage(), "fromString", String.class); CONSTRUCT_COMPONENT = Accessors.getMethodAccessor(MinecraftReflection.getCraftChatMessage(), "fromString", String.class, boolean.class);
// And the component text constructor // And the component text constructor
CONSTRUCT_TEXT_COMPONENT = Accessors.getConstructorAccessor(MinecraftReflection.getChatComponentTextClass(), String.class); CONSTRUCT_TEXT_COMPONENT = Accessors.getConstructorAccessor(MinecraftReflection.getChatComponentTextClass(), String.class);
@ -95,6 +95,9 @@ public class WrappedChatComponent extends AbstractWrapper implements ClonableWra
/** /**
* Construct a wrapper around a new text chat component with the given text. * Construct a wrapper around a new text chat component with the given text.
* <p>
* Note: {@link #fromLegacyText(String)} is preferred for text that contains
* legacy formatting codes since it will translate them to the JSON equivalent.
* @param text - the text of the text chat component. * @param text - the text of the text chat component.
* @return The wrapper around the new chat component. * @return The wrapper around the new chat component.
*/ */
@ -111,7 +114,7 @@ public class WrappedChatComponent extends AbstractWrapper implements ClonableWra
* @return The equivalent chat components. * @return The equivalent chat components.
*/ */
public static WrappedChatComponent[] fromChatMessage(String message) { public static WrappedChatComponent[] fromChatMessage(String message) {
Object[] components = (Object[]) CONSTRUCT_COMPONENT.invoke(null, message); Object[] components = (Object[]) CONSTRUCT_COMPONENT.invoke(null, message, false);
WrappedChatComponent[] result = new WrappedChatComponent[components.length]; WrappedChatComponent[] result = new WrappedChatComponent[components.length];
for (int i = 0; i < components.length; i++) { for (int i = 0; i < components.length; i++) {
@ -120,6 +123,18 @@ public class WrappedChatComponent extends AbstractWrapper implements ClonableWra
return result; return result;
} }
/**
* Construct a single chat component from a standard Minecraft message
* (with legacy formatting codes), preserving multiple lines.
* @param message - the message.
* @return The equivalent chat component.
*/
public static WrappedChatComponent fromLegacyText(String message) {
// With keepNewlines = true (second parameter), only one component is returned
Object[] components = (Object[]) CONSTRUCT_COMPONENT.invoke(null, message, true);
return fromHandle(components[0]);
}
/** /**
* Retrieve a copy of this component as a JSON string. * Retrieve a copy of this component as a JSON string.
* <p> * <p>

View File

@ -161,7 +161,7 @@ public class WrappedServerPing extends AbstractWrapper implements ClonableWrappe
* @param message - the message. * @param message - the message.
*/ */
public void setMotD(String message) { public void setMotD(String message) {
setMotD(WrappedChatComponent.fromText(message)); setMotD(WrappedChatComponent.fromLegacyText(message));
} }
/** /**