Хостинг серверов Minecraft playvds.com
  1. Вы находитесь в русском сообществе Bukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на русский язык плагины наших собратьев из других стран.
    Dismiss Notice

[Решено] Multiple lines in tablist

Discussion in 'Разработка плагинов для новичков' started by CoolBoy, Jun 4, 2016.

Thread Status:
Not open for further replies.
  1. Автор темы
    CoolBoy

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

    Trophy Points:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Всем доброго времени суток, уважаемые форумчане.

    Во время написания плагина для заказчика столкнулся с некоторой проблемой.

    Так как у SpigotAPI ещё нет метода взаимодействия с "таб-листом" приходится немного костылить.

    После прочтения некоторой документации и декомпиляции парочки плагинов на "таб-лист", я таки написал свой плагин.

    Но возникла небольшая проблема.

    Дело в том, что и Header и Footer плагин успешно устанавливает игрокам. Но как только я пытаюсь выставить в "таб-лист" несколько строк - он выводит только первые.

    Вопрос:
    Каким образом можно выставить в "таб-лист" несколько строк с текстом?
    И в footer, и header.

    Код методов, которые я использую:
    Utils.class
    Code:
    public static void sendTablist(Player player, String string, String string_2, Main plugin)
        {
            try
            {
                if (Utils.getServerVersion().equalsIgnoreCase("v1_9_R1") || Utils.getServerVersion().equalsIgnoreCase("v1_9_R2"))
                {
                    Object header = Utils.getNmsClass("ChatComponentText").getConstructor(String.class).newInstance(string);
                    Object footer = Utils.getNmsClass("ChatComponentText").getConstructor(String.class).newInstance(string_2);
                    Object util = Utils.getNmsClass("PacketPlayOutPlayerListHeaderFooter").getConstructor(Utils.getNmsClass("IChatBaseComponent")).newInstance(header);
                    Field field = util.getClass().getDeclaredField("b");
                    field.setAccessible(true);
                    field.set(util, footer);
                    Object nmsp = player.getClass().getMethod("getHandle", new Class[0]).invoke(player, new Object[0]);
                    Object pcon = nmsp.getClass().getField("playerConnection").get(nmsp);
                    pcon.getClass().getMethod("sendPacket", Utils.getNmsClass("Packet")).invoke(pcon, util);
                 }
            } catch (ClassNotFoundException | IllegalAccessException | IllegalArgumentException |
    InstantiationException | NoSuchFieldException | NoSuchMethodException |
    SecurityException | InvocationTargetException exception)
            {
                exception.printStackTrace();
            }
        }
    }
    
    private static String getServerVersion()
    {
        return Bukkit.getServer().getClass().getPackage().getName().substring(23);
    }
    
    private static Class<?> getNmsClass(String string) throws ClassNotFoundException
    {
        return Class.forName("net.minecraft.server." + Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3] + "." + string);
    }
    
    Listeners.class
    Code:
    @EventHandler
    public void onJoin(PlayerJoinEvent event)
    {
        for (Player players : Bukkit.getOnlinePlayers())
        {
            Utils.sendTablist(players, Utils.colorMessage(header), Utils.colorMessage(footer), this.plugin);
        }
    }
    
    Что я делал:
    Создавал HashMap, брал из конфига лист строк, с помощью цикла помещал в хэшмап. Также циклом проходился по хешмапу и выставлял всем игрокам tablist. Но получалось так, что, зайдя на сервер первый раз, у меня и в Header, и в Footer были первые строки. Зайдя во второй - вторые. Каким образом я могу выставить их обе сразу?

    P.S на данный момент, в качестве костыля, просто беру строку, в которой для переноса строк используется \n.
     
    Last edited: Jun 4, 2016
  2. Хостинг MineCraft
    <
  3. Larin

    Larin Старожил Пользователь

    Trophy Points:
    103
  4. MrTrojan

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

    Trophy Points:
    98
    Skype:
    mrtrojan.ru
    Имя в Minecraft:
    MrTrojan
    Лучше работать с табом на стороне банжи, там всё легко.
     
  5. Автор темы
    CoolBoy

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

    Trophy Points:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Тебе легко это писать. Мне до банжи ещё незнай сколько. Тут либо патчить класс, как это делаю я, либо отправлять пакеты. Насколько я понял.[DOUBLEPOST=1465022084,1465021749][/DOUBLEPOST]
    Уже был там. По моей проблеме там вообще ничего полезного нет.[DOUBLEPOST=1465034824][/DOUBLEPOST]UP
     
  6. MrTrojan

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

    Trophy Points:
    98
    Skype:
    mrtrojan.ru
    Имя в Minecraft:
    MrTrojan
    Посмотри как реализовано в других плагинах.
     
  7. Автор темы
    CoolBoy

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

    Trophy Points:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Декомпилировал порядка 5 плагинов. Либо там всё в одну строку, как, собственно, у меня, и для переноса используется "\n", либо там работа идёт через пакет. На данный момент идея как это пофиксить есть. Но времени на фикс нет. Если есть толковые идеи - предлагайте, буду рад прочитать.
     
  8. fall.us

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

    Trophy Points:
    76
    Имя в Minecraft:
    fallus
    Так и не понял, в чем проблема?
    Если строчки спокойно переносятся символом переноса строки(а они переносятся), то проблемы по факту и нет)[DOUBLEPOST=1465931756,1465931253][/DOUBLEPOST]
    [​IMG]
     
  9. Автор темы
    CoolBoy

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

    Trophy Points:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Неудобно, да и является по сути - костылём. В ядре (Core) я таким костылём пользоваться не хочу, ибо там у меня всё чисто и аккуратно. К тому же, знаю, что в плагине Tablist поддерживается именно лист из строк, а не строка с \n.
    Соответственно мне нужно решение этой проблемы.

    Ах да, декомпилировал я этот Tablist (и ещё кучу других) дабы посмотреть как там всё устроено. Очень долго возился с решением, но так ничего и не придумал. Даже скопированный код из Tablist'а на моём плагине работал некорректно :confused:

    Есть идеи?
     
    Last edited: Jun 14, 2016
  10. Larin

    Larin Старожил Пользователь

    Trophy Points:
    103
    StringJoiner.
     
  11. fall.us

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

    Trophy Points:
    76
    Имя в Minecraft:
    fallus
    С каких пор стандартные средства языка являются костылем?))

    Глянул этот самый Tablist(хз, тот, не тот):
    Code:
      public static void loadMessages(tablist plugin)
      {
        vars.auto_HeaderMessages.clear();
        vars.auto_FooterMessages.clear();
      
        List<String> headerList = theConfig.getAnnouncerHeaders(plugin);
        List<String> footerList = theConfig.getAnnouncerFooters(plugin);
        for (int i = 0; i < headerList.size(); i++)
        {
          String header = (String)headerList.get(i);
          String footer;
          String footer;
          if (footerList.size() > i) {
            footer = (String)footerList.get(i);
          } else {
            footer = "";
          }
          vars.auto_HeaderMessages.add(ChatColor.translateAlternateColorCodes('&', header));
          vars.auto_FooterMessages.add(ChatColor.translateAlternateColorCodes('&', footer));
        }
      }
    
      public static void start(tablist plugin)
      {
        loadMessages(plugin);
        vars.auto = Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable()
        {
          public void run()
          {
            int num = vars.auto_messagenumber;
            for (Player op : Bukkit.getOnlinePlayers())
            {
              String header = (String)vars.auto_HeaderMessages.get(num);
              String footer = (String)vars.auto_FooterMessages.get(num);
            
              theTablist.sendTablist(op, header, footer, tablist.getPlugin(), true);
            }
            if (vars.auto_messagenumber < vars.auto_HeaderMessages.size() - 1) {
              vars.auto_messagenumber += 1;
            } else {
              vars.auto_messagenumber = 0;
            }
          }
        }, 0L, theConfig.getAnnouncerTime(plugin) + 1);
      }
    Из списка достается только одна строка и подставляется в футер или в хедер.

    Попробовал зафигачить список строк в json - сервер не может десериализовать его. Так что только \n.
     
  12. Автор темы
    CoolBoy

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

    Trophy Points:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Да быть не может. Код тот, да. Только он с листом то работает. Да и полно таблистов, которые лист строк читают. Как?
     
  13. fall.us

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

    Trophy Points:
    76
    Имя в Minecraft:
    fallus
    Ну раз Вы уверены, что такие бывают - смотрите их код.

    Я сам с этой фигней раньше не работал. У меня сегодня вообще впервые что-то в nms получилось сделать)
     
  14. Автор темы
    CoolBoy

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

    Trophy Points:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Порой иногда приятно осознавать, что чего-то в этой жизни ты ещё не умеешь :)

    И всё равно хочется своего добиться.
     
  15. fall.us

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

    Trophy Points:
    76
    Имя в Minecraft:
    fallus
    Code:
    String buf = "";
    
    for(int i = 0; i < list.size(); i++)
        if(i == list.size() - 1)
            buf += (String)list.get(i);
        else
            buf += (String)list.get(i) + "\n";
    Такое не устроит?
     
  16. Автор темы
    CoolBoy

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

    Trophy Points:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Беспалевный костыль :lol:

    Задачка непростая, как я понял :)
    Будем гуглить. Кто-то ведь ещё и анимацию в таб-листе делать умудряется.
     
  17. fall.us

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

    Trophy Points:
    76
    Имя в Minecraft:
    fallus
    Мой рабочий код. На всякий случай.
    Code:
    PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter();
    
    String sheader = "§6This is test header§r\n§9HelloWorld§r\n§eLine #3";
    String sfooter = "footer";
    
    IChatBaseComponent header = new ChatComponentText(sheader);
    IChatBaseComponent footer = new ChatComponentText(sfooter);
    
    Field packet_header = null, packet_footer = null;
    
    try
    {
        //хедер
        packet_header = packet.getClass().getDeclaredField("a");
    
        packet_header.setAccessible(true);
        packet_header.set(packet, header);
    
        //футер
        packet_footer = packet.getClass().getDeclaredField("b");
    
        packet_footer.setAccessible(true);
        packet_footer.set(packet, footer);
    }
    catch(Exception e1)
    {
        e1.printStackTrace();
    }
    
    ((CraftPlayer) e.getPlayer()).getHandle().playerConnection.sendPacket(packet);
    
     
  18. alexandrage

    alexandrage Администратор

    Trophy Points:
    173
    Skype:
    alexandr0116
    \n это не костыль, это спец символ переноса строки, другого не дано.
     
  19. Larin

    Larin Старожил Пользователь

    Trophy Points:
    103
    Матерь божья, изучайте java se api, есть же верно работающий StringJoiner.
     
  20. fall.us

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

    Trophy Points:
    76
    Имя в Minecraft:
    fallus
    "А еще всегда используйте уже готовые средства, структуры данных, кодеки. Даже не пытайтесь придумывать что-то свое!".
    Если мне надо будет, я напишу свой StringJoiner.
     
  21. Larin

    Larin Старожил Пользователь

    Trophy Points:
    103
    1) В данном случае - это костыль.
    2) Я такого нигде не говорил.
    3) Зачем костылять, если есть уже готовое в Java SE? Пиши тогда еще и свою коллекцию.
     
Thread Status:
Not open for further replies.

Share This Page