Packet Normalizers - rodrigoo-r/Harmony GitHub Wiki

Explanation

Harmony includes a class to do some stuff with packets.

I've found out a real problem with SYSTEM_CHAT packets on Paper servers. The problem is that Paper changes the ClientboundSystemChatPacket. This causes the packet strings to be null, because Paper adds more fields to the packet for the Adventure chat components

The way to properly solve this is to include the Adventure API into your project and then get the packet internal structures and cast one of them to an Adventure Component and then serialize it into a JSON, then set to null the Adventure modifier and finally write the JSON into the packet strings.

Harmony has an utility class to do this all without getting any headaches, just calling a method.

This class has some more stuff like sending JSON components to a player, using packets. This can be done with Player.spigot() on modern versions, however, it did not exist on legacy versions.


Usage

You'll need to register a packet listener that listens either for SYSTEM_CHAT or CHAT packets (Play.Server package), and use PacketNormalizeUtil when you receive a packet. (If you're using CHAT packets instead of SYSTEM_CHAT, you'll get the JSON component anyway, but CHAT packets come with ChatComponent instead of Strings, you can easily get them with getChatComponents()).

[!WARNING] SYSTEM_CHAT packets were added on 1.19. If you're running a version under 1.19, you must use CHAT packets instead

public class a extends StandardServerHandler {

    @Override
    public void whenServerHandleSystemChat(PacketEvent event) {
        // Get the JSON component from the chat packet
        // This method will get the adventure modifier if it is present
        // And null it for us, but write the component as a JSON string
        // then return us the JSON string, this way we can modify it
        // and easily manipulate the packet

        final PacketContainer packet = event.getPacket();
        final String JSONString = PacketNormalizeUtil.fromSystemChatPacket(packet);

        // Do some stuff with the JSON Component
        // Write it back
        packet.getStrings().write(0, JSONString);
    }

}

Sending JSON Components

You can send JSON Components to a player using PacketNormalizeUtil. This task can be done with Bungee's TextComponent API, sending TextComponents to a player using Player.spigot().sendMessage(). The big problem with it is that this method isn't available at older versions. Harmony can do this task without compatibility problems, using packets.

You can send plain JSON Components and TextComponents to a player.

Example:

1. Sending TextComponents and BaseComponents

PacketNormalizeUtil.sendComponent(
    TextComponent.fromLegacyText(
        "Hello world"
    ),
    Bukkit.getPlayer("Steve")
);

2. Sending Plain JSON Components

PacketNormalizeUtil.sendComponent(
    "{\"text\":\"Hello World!\"}",
    Bukkit.getPlayer("Steve")
);