1. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

Помогите PacketPlayOutChat, компонент всегда null

Тема в разделе "Разработка плагинов для новичков", создана пользователем ReloGGrc, 11 фев 2023.

  1. Автор темы
    ReloGGrc

    ReloGGrc Активный участник Пользователь

    Баллы:
    46
    Имя в Minecraft:
    ALis
    В общем, пишу "ProtocolLib" для своего плагина, и тут возник вопрос, как люди отслеживают сообщение в PacketPlayOutChat если поле IChatBaseComponent там всегда null пока его сам не задашь...
    (Моя рефлексия тут не причем, т.к. даже напрямую NMS использовал, проверял, все равно
    IChatBaseComponent равен нулю)
     
  2. Dymeth

    Dymeth Активный участник Пользователь

    Баллы:
    98
    Имя в Minecraft:
    Dymeth
    Он не может быть нулл. Игрок же как-то сообщения от сервера получает. Показывай, как пытаешься получить содержимое пакета
     
  3. Автор темы
    ReloGGrc

    ReloGGrc Активный участник Пользователь

    Баллы:
    46
    Имя в Minecraft:
    ALis
    Я тоже знаю что он не может быть нуль, но я сейчас проверил с помощью PacketEventsAPI и ProtocolLib'a, тоже самое...

    И еще, у пакета с сообщением 'ALis joined the game!' IChatBaseComponent не null

    Код:
    packet.readObject(0, AdvancedPackets.get().getClassContainer().getIChatBaseComponentClass())
    
    ----
    
    @Override
        public <T> T readObject(int index, Class<?> type) {
            return this.read(index, type);
        }
    
    ---
    
    @Override
        public <T> T read(int index, Class<?> type) {
            try {
                Field field = this.getField(index, type);
                return (T) field.get(this.rawPacket);
            } catch (Exception e) {
                throw new RuntimeException("Field indexed " + index + " not founded!");
            }
        }
    
    ---
    
    public Field getField(int index, Class<?> type) {
            for(FunctionalField field : getFields()) {
                if(field.getIndex() == index && field.getType() == type) {
                    return field.getField();
                }
            }
            return null;
        }
    Это я древо методов расписал, верхний - первый(и есть получение поля с IChatBaseComponent из пакета)
     
  4. Dymeth

    Dymeth Активный участник Пользователь

    Баллы:
    98
    Имя в Minecraft:
    Dymeth
    А версия сервера какая?
     
  5. Автор темы
    ReloGGrc

    ReloGGrc Активный участник Пользователь

    Баллы:
    46
    Имя в Minecraft:
    ALis
  6. Dymeth

    Dymeth Активный участник Пользователь

    Баллы:
    98
    Имя в Minecraft:
    Dymeth
    Только что протестировал на paper 1.17.1 + ProtocolLib 5.0.0:
    PHP:
    player.sendMessage("Message from server");
    player.sendMessage(player.getUniqueId(), "Message from player");
    Обработчик:
    PHP:
    ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(pluginPacketType.Play.Server.CHAT) {
        @
    Override
        
    public void onPacketSending(PacketEvent event) {
            
    Player player event.getPlayer();
            
    WrappedChatComponent message event.getPacket().getChatComponents().read(0);
            
    plugin.getLogger().info(player.getName() + " received message: " message);
        }
    });
    Результат:
    PHP:
    Dymeth received messageWrappedChatComponent[json={"extra":[{"text":"Message from server"}],"text":""}]
    Dymeth received messageWrappedChatComponent[json={"extra":[{"text":"Message from player"}],"text":""}]
     
    Последнее редактирование: 11 фев 2023
  7. Автор темы
    ReloGGrc

    ReloGGrc Активный участник Пользователь

    Баллы:
    46
    Имя в Minecraft:
    ALis
    Странно, Я проверял с написанием сообщения в чат, в игре самой, и если писать в чат из игры, то пакет приходит с пустым IChatBaseComponent, но при том сообщение отправляется. Мда уж..
     
  8. Dymeth

    Dymeth Активный участник Пользователь

    Баллы:
    98
    Имя в Minecraft:
    Dymeth
    Для сообщений, отправленных игроками вручную, чат-компонент реально null. Судя по всему, при добавлении Adventure в ядро в классе пакета появилось новое поле:
    net.kyori.adventure.text.Component adventure$message
    Подозреваю, что его создали с целью оптимизации.

    Если в пакете присутствуют значения обоих в полей - в буфер пишется именно компонент из Adventure.

    Код:
    PHP:
    Player player event.getPlayer();

    WrappedChatComponent componentMessage event.getPacket().getChatComponents().read(0);
    Component adventureMessage event.getPacket().getSpecificModifier(Component.class).read(0);
    plugin.getLogger().info(player.getName() + " received component message: " componentMessage);
    plugin.getLogger().info(player.getName() + " received Adventure message: " adventureMessage);

    event.getPacket().getChatComponents().write(0WrappedChatComponent.fromText("Modified component message"));
    event.getPacket().getSpecificModifier(Component.class).write(0Component.text("Modified Adventure message"));
     
    Последнее редактирование: 11 фев 2023
  9. Автор темы
    ReloGGrc

    ReloGGrc Активный участник Пользователь

    Баллы:
    46
    Имя в Minecraft:
    ALis
    Понял, спасибо большое за помощь!
     
  10. Dymeth

    Dymeth Активный участник Пользователь

    Баллы:
    98
    Имя в Minecraft:
    Dymeth
    Подправил код, всё проще делается.

    Ещё учти, что в 1.19 тоже структура пакетов или сами пакеты поменялись, потому что ввели цифровые подписи сообщений
     
  11. Автор темы
    ReloGGrc

    ReloGGrc Активный участник Пользователь

    Баллы:
    46
    Имя в Minecraft:
    ALis
    Понял, спасибо еще раз!)
     

Поделиться этой страницей