How to set content in ClientboundSystemChatPacket?
kangarko opened this issue · 5 comments
Make sure you're doing the following
- You're using the latest build for your server version
- This isn't an issue caused by another plugin
- You've checked for duplicate issues
- You didn't use
/reload
Do ProtocolLib provide wrapper for setting content of the chat message in the ClientboundSystemChatPacket? I spent countless time trying to figure out to no avail, looks really complex since they introduced their Adventure library. Thanks for the help.
Hello @kangarko did you find a solution? I have the exactly same problem and I am stuck with no options
Got more information about this at a Paper issue. Do you know how to replace the chat packet? We have a large consumer base using packet integration with the chat packet to replace system chat messages, I'd appreciate your help in this!
Yes and no, I tried just sending a new packet and cancelling the old one but it seemed to cause a race condition and we need further investigation: kangarko/Foundation@8374209
For plain Spigot, the correct way to modify the content would be the following which just replaces the JSON encoded chat component that is stored in a String
Reading:
WrappedChatComponent message = WrappedChatComponent.fromJson(packetContainer().getStrings().read(0));
Writing:
packetContainer().getStrings().write(0, WrappedChatComponent.fromText("Test").getJson());
However, if you are using Paper, this could potentially break as they introduced another field that takes an Advanture Chat Component as a content. If this field is non-null, the JSON encoded message mentioned above will be completely ignored.
The way for accessing the Advanture component would be container.getSpecificModifier(net.kyori.adventure.text.Component.class).read(0)
resp. container.getSpecificModifier(net.kyori.adventure.text.Component.class).write(1)
. However, this requires that you have Adventure in your Classpath and you are using Paper. I'd suggest doing something like this for the best compatability:
@Override
public void onPacketSending(PacketEvent event) {
PacketContainer container = event.getPacket();
WrappedChatComponent component = null;
try {
StructureModifier<Object> adventureModifier = container.getModifier().withType(AdventureComponentConverter.getComponentClass());
if(!adventureModifier.getFields().isEmpty()) { // Only true on Paper
net.kyori.adventure.text.Component comp = (net.kyori.adventure.text.Component) adventureModifier.read(0);
if(comp != null) {
component = AdventureComponentConverter.fromComponent(comp);
adventureModifier.write(0, null); // Reset to null - the JSON message will be set instead
}
}
} catch (Throwable ignored) {} // Ignore if paper is unavailable
if(component == null) {
component = WrappedChatComponent.fromJson(container.getStrings().read(0));
}
// Modify component here
container.getStrings().write(0, component.getJson());
}
Please not that this code is untested
@lukalt love it, thanks! Got it working WITHOUT importing Adventure at all, if anyone needs the code here it is: kangarko/Foundation@9ed1a29