GeyserMC / MCProtocolLib

A library for communication with a Minecraft client/server.
MIT License
721 stars 202 forks source link

Is there anyway to get raw chat messages? #372

Closed TrevorCow closed 6 years ago

TrevorCow commented 6 years ago

There isn't a lot of documentation on how chat messages work under different circumstances in different server implementations. Is there a way to get the raw message across all types of servers?

For example, vanilla Minecraft uses the default translation keys, which is easy to decode using translation message. However, hypixel (and other implementations of servers) use custom JSON to send messages.

I've tried to loop through extras but different servers use different formats so that breaks.

Any ideas?

TrevorCow commented 6 years ago

Ok thanks, i assumed it was a Minecraft thing. I wrote something that works so far for anyone looking to do it.

@Override
public void onChat(ServerChatPacket packet) {
    Message m = packet.getMessage();

    String chat = null;

    String sender = null;
    String message = null;
    String tranlationType = null;

    if (m instanceof TranslationMessage) { // This SHOULD only fire if it's mostly vanilla
        TranslationMessage tm = (TranslationMessage) m;
        sender = tm.getTranslationParams()[0].getFullText();
        message = tm.getTranslationParams()[1].getFullText();
        chat = "<" + sender + "> " + message; // Constructs the message to look like '<Username> Message from username'
        tranlationType = tm.getTranslationKey(); // Used if you want to figure out what type of message (chat, announcement, server, etc...)
    } else { // This SHOULD fire for all custom JSON messages from 3rd party servers.
        JsonObject jmessage = m.toJson().getAsJsonObject();
        if (jmessage.has("extra")) {
            StringBuilder sb = new StringBuilder();
            parseExtra(jmessage.get("extra").getAsJsonArray(), sb); // Recursively filter out 'extra' text from the JSON message.
            chat = sb.toString();
        }
    }

    // System.out.println(sender + " said(" + tranlationType + "): " + message); // This can be used to get the info for vanilla chat messages
    if (chat == null) { // Can be used for debugging. This should never fire
        System.err.println("Chat was null");
    } else {
        chat = chat.trim();
        if (!chat.equalsIgnoreCase("")) { // Some servers send blank chat messages (For detecting hacked clients and stuff) so you can just ignore them
            System.err.println(trimColorCodes(chat));
        }
    }
}

public void parseExtra(JsonArray jo, StringBuilder chat) {
    for (JsonElement ex : jo) {
        if (ex.isJsonObject()) {
            if (ex.getAsJsonObject().has("extra"))
                parseExtra(ex.getAsJsonObject().get("extra").getAsJsonArray(), chat);
        }
        chat.append(ex.getAsJsonObject().get("text").getAsString());
    }
}

public String trimColorCodes(String trim) {
    StringBuilder trimed = new StringBuilder();
    for (int i = 0; i < trim.toCharArray().length; i++) {
        if (trim.charAt(i) == '\u00A7') {
            i += 1;
        } else {
            trimed.append(trim.charAt(i));
        }
    }
    return trimed.toString();
}