Перезагрузка плагина приводит к отключению клиентов с помощью IndexOutOfBoundsException - PullRequest
1 голос
/ 11 февраля 2020

Общая информация Я работаю над плагином чата для Spigot (сервер Minecraft). Идея состоит в том, чтобы создать систему чата, которая позволяет использовать рабочие вкладки чата:

Example of Minecraft chat plugin

Чтобы выполнить sh, мне нужно использовать NMS (ProtocolLib), поскольку Minecraft использует 3 типа сообщений в чате:

  1. Сообщения чата
  2. Системные сообщения
  3. Сообщения с информацией об игре

Сообщения чата легко доступны, а остальные 2 - нет. Если я не улавливаю эти сообщения, они выводят sh меню вкладок вместо того, чтобы попасть в их собственный канал чата.

Проблема Код (ниже), который я использую для перехвата этих сообщений, вызывает следующее исключение в подключенных клиентах Minecraft и отключает их при перезагрузке игрового плагина через /reload:

DecoderException: java. lang.IndexOutOfBoundsException: readerIndex (0) + длина (1) превышает writerIndex (0) UnpooledSlicedByteBuf (ridx: 0, widx: 0, cap: 0/0, развернутый: PooledUnsafeDirectByteBuf (ridx: 2, widx 6: 6): 6) ) @ io.netty.handler.code c .MessageToMessageDecoder: 98

Соответствующий код

private void initPacketListener(){
    protocolManager.addPacketListener(new PacketAdapter(this, ListenerPriority.NORMAL, new PacketType[] { PacketType.Play.Server.CHAT })
    {
        @SuppressWarnings("unused")
        @Override
        public void onPacketSending(PacketEvent event) {

            if ((event.getPacketType() == PacketType.Play.Server.CHAT)){
                PacketContainer packet = event.getPacket();
                Player player = event.getPlayer();
                String message = "";

                try {
                    String jsonMessage = event.getPacket().getChatComponents().getValues().get(0).getJson();

                    if (jsonMessage!=null&&!jsonMessage.isEmpty()) {
                        message = jsonToString(jsonMessage);

                        if (message.isEmpty()) return;

                        Subscriber subscriber = UMM.plugin.getSubscribers().get(player.getUniqueId());
                        String uuid = player.getUniqueId().toString();
                        Channel messageChannel = UMM.serverChannels.get(uuid);
                        messageChannel.addMessage(message);
                        ChatListener cl = new ChatListener(UMM.plugin);

                        cl.notifyChanges(messageChannel);
                        event.setCancelled(true);
                    } else {
                        System.out.println("Not a system msg");
                    }
                } catch (Throwable e){
                    System.out.println("UMM Packet Error:" + e.getMessage());
                }
            }
        }
    });
}

То, что я попробовал для решения проблемы Я спросил некоторых других разработчиков об этой проблеме, и мне сказали:

Убедитесь, что размер / длина event.getPacket (). GetChatComponents (). GetValues ​​() больше 0, прежде чем сделать # получить вызов.

Итак, я попробовал это:

List<WrappedChatComponent> wrap = event.getPacket().getChatComponents().getValues();

if(wrap.size() > 0) {
    if ((event.getPacketType() == PacketType.Play.Server.CHAT)){
        ...
    }
}

Но это никак не повлияло. Они больше не могли мне помочь, поэтому я надеюсь, что кто-то еще может знать, что происходит и как я могу решить эту проблему.

Обновление Даже после сокращения кода до этой, проблема все еще сохраняется:

private void initPacketListener(){
        protocolManager.addPacketListener(new PacketAdapter(this, ListenerPriority.NORMAL, new PacketType[] { PacketType.Play.Server.CHAT })
        {
            @SuppressWarnings("unused")
            @Override
            public void onPacketSending(PacketEvent event) {
            }
    });
}

«Временное» решение проблемы использует BukkitRunnable для вызова галочки метода 1 после перезагрузки сервера. Единственным недостатком этого является то, что любые сообщения, появляющиеся до первого тика, подталкивают меню вкладок вверх. Плагин исправляет это при следующем событии сообщения.

1 Ответ

0 голосов
/ 13 февраля 2020

Вы никогда не должны использовать команду /reload, смотрите больше здесь, например: https://matthewmiller.dev/blog/problem-with-reload/.

Вы можете реализовать команду перезагрузки в вашем плагине, которая делает то, что вы хотите, если вы нужно это. Возможно, ваша проблема может быть устранена с помощью внутренней команды перезагрузки, потому что это может быть проблема с командой /reload.

...