Shadow Format Is Not Preserved In Components
Describe the bug When changing a chat message via a PacketListener and testing for SYSTEM_CHAT_MESSAGE, the "shadow" format of the text is not preserved. This may also be the case for other packets that use components but in my case, I specifically tested SYSTEM_CHAT_MESSAGE.
Software brand This server is running Paper version 1.21.4-211-main@6ea4202 (2025-03-13T11:49:31Z) (Implementing API version 1.21.4-R0.1-SNAPSHOT) You are running the latest version Previous version: 1.21.4-209-f0388e2 (MC: 1.21.4)
Plugins LibsDisguises, FastAsyncWorldEdit, ProtocolLib, custom plugin
How To Reproduce
- Write a PacketListener that changes a message
@Override
public void onPacketSend(PacketSendEvent event) {
if(event.getPacketType() != PacketType.Play.Server.SYSTEM_CHAT_MESSAGE) return;
WrapperPlayServerSystemChatMessage message = new WrapperPlayServerSystemChatMessage(event);
Component msg = message.getMessage();
msg = msg.replaceText(builder -> builder.matchLiteral("word").replacement("whoop"));
message.setMessage(msg);
}
-
Send a message that changes a text's shadow. In my case, I used: MiniMessage.miniMessage().deserialize("Test"); to attempt to remove the text's shadow.
-
Observe. The shadow format is completely ignored. In the example I used, the shadow still shows up even though it should not.
Expected behavior The shadow format should persist in the message.
Screenshots N/A
Additional context N/A
In this instance, I tested with <red><!shadow>this is a test and when editing the message via the packet listener, the shadow still stays (second image). The first image is how it should look, without the shadow.
Has to be with the adventure patch PE comes with
@KillerCreeper112 I'm confused with your steps to reproduce given this example.
private void test(User user, Player player) {
user.getEventManager().registerListener(new InternalPacketListener() {
@Override
public void onPacketSend(PacketSendEvent event) {
if (event.getPacketType() != PacketType.Play.Server.SYSTEM_CHAT_MESSAGE) {
return;
}
final WrapperPlayServerSystemChatMessage message = new WrapperPlayServerSystemChatMessage(event);
Component msg = message.getMessage();
msg = msg.replaceText(builder -> builder.matchLiteral("word").replacement(MiniMessage.miniMessage().deserialize("<red><!shadow>this is a test")));
message.setMessage(msg);
}
});
player.sendMessage(MiniMessage.miniMessage().deserialize("word"));
}
This should replicate it? I'm confused or you're replacing the whole message with the same message but without shadow?
@KillerCreeper112 I'm confused with your steps to reproduce given this example.
private void test(User user, Player player) { user.getEventManager().registerListener(new InternalPacketListener() { @Override public void onPacketSend(PacketSendEvent event) { if (event.getPacketType() != PacketType.Play.Server.SYSTEM_CHAT_MESSAGE) { return; }
final WrapperPlayServerSystemChatMessage message = new WrapperPlayServerSystemChatMessage(event); Component msg = message.getMessage(); msg = msg.replaceText(builder -> builder.matchLiteral("word").replacement(MiniMessage.miniMessage().deserialize("<red><!shadow>this is a test"))); message.setMessage(msg); } }); player.sendMessage(MiniMessage.miniMessage().deserialize("word")); }This should replicate it? I'm confused or you're replacing the whole message with the same message but without shadow?
Sorry I wasn't more clear. Basically what I did is have the exact PacketListener that I presented up above.
Then you send a message to the player somewhere else. For example, you can broadcast a message Bukkit.broadcast(MiniMessage.miniMessage().deserialize("
However, upon further testing, I found that it doesn't even seem to matter if you change the message or not. The problem seems to be with this specifically: WrapperPlayServerSystemChatMessage message = new WrapperPlayServerSystemChatMessage(event);
Because if I do this logic:
@Override
public void onPacketSend(PacketSendEvent event) {
if(event.getPacketType() != PacketType.Play.Server.SYSTEM_CHAT_MESSAGE) return;
WrapperPlayServerSystemChatMessage message = new WrapperPlayServerSystemChatMessage(event);
}
the issue persists and the shadow format is forgotten.
If I do this logic (added the "if(true) return;" before the wrapping the event, the issue is no longer there.
@Override
public void onPacketSend(PacketSendEvent event) {
if(event.getPacketType() != PacketType.Play.Server.SYSTEM_CHAT_MESSAGE) return;
if(true) return;
WrapperPlayServerSystemChatMessage message = new WrapperPlayServerSystemChatMessage(event);
}
Weird because I can't replicate this
@KillerCreeper112 Are you using the latest packetevents build? The shadow field should be supported properly
@KillerCreeper112 Are you using the latest packetevents build? The shadow field should be supported properly
Yeah, I'm using the latest packetevents and latest Paper. I don't really understand. I return right before:
WrapperPlayServerSystemChatMessage message = new WrapperPlayServerSystemChatMessage(event);
and the issue is no longer present. But then I remove the return before and the issue persists.
@KillerCreeper112 does this issue still occur?