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

  • Автор темы Автор темы CoolBoy
  • Дата начала Дата начала
Статус
Закрыто для дальнейших ответов.

CoolBoy

Активный участник
Пользователь
Баллы
96
Имя в Minecraft
Xezard
Всем доброго времени суток, уважаемые форумчане.

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

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

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

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

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

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

Код методов, которые я использую:
Utils.class
Java:
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
Java:
@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.
 
Последнее редактирование:
Лучше работать с табом на стороне банжи, там всё легко.
 
Лучше работать с табом на стороне банжи, там всё легко.
Тебе легко это писать. Мне до банжи ещё незнай сколько. Тут либо патчить класс, как это делаю я, либо отправлять пакеты. Насколько я понял.
Check this:
https://hypixel.net/threads/tut-tablist-header-and-footer-nms.373620/

UPD: Прочитал внимательнее.
Отправляй в начале пустой таблист. Может поможет.

p.s. пойду спать, вообще не могу работать.
Уже был там. По моей проблеме там вообще ничего полезного нет.
UP
 
Посмотри как реализовано в других плагинах.
 
Посмотри как реализовано в других плагинах.
Декомпилировал порядка 5 плагинов. Либо там всё в одну строку, как, собственно, у меня, и для переноса используется "\n", либо там работа идёт через пакет. На данный момент идея как это пофиксить есть. Но времени на фикс нет. Если есть толковые идеи - предлагайте, буду рад прочитать.
 
Так и не понял, в чем проблема?
Если строчки спокойно переносятся символом переноса строки(а они переносятся), то проблемы по факту и нет)
Так и не понял, в чем проблема?
Если строчки спокойно переносятся символом переноса строки(а они переносятся), то проблемы по факту и нет)
 
Так и не понял, в чем проблема?
Если строчки спокойно переносятся символом переноса строки(а они переносятся), то проблемы по факту и нет)

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

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

Есть идеи?
 
Последнее редактирование:
Не удобно, да и является по сути - костылём. В ядре (Core) я таким костылём пользоваться не хочу, ибо там у меня всё чисто и аккуратно. К тому же, знаю, что в плагине Tablist поддерживается именно лист из строк, а не строка с \n.
Соответственно мне нужно решение этой проблемы.

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

Есть идеи?
StringJoiner.
 
Не удобно, да и является по сути - костылём. В ядре (Core) я таким костылём пользоваться не хочу, ибо там у меня всё чисто и аккуратно. К тому же, знаю, что в плагине Tablist поддерживается именно лист из строк, а не строка с \n.
Соответственно мне нужно решение этой проблемы.
С каких пор стандартные средства языка являются костылем?))

Глянул этот самый Tablist(хз, тот, не тот):
Java:
  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.
 
С каких пор стандартные средства языка являются костылем?))

Глянул этот самый Tablist(хз, тот, не тот):
Java:
  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.
Да быть не может. Код тот, да. Только он с листом то работает. Да и полно таблистов, которые лист строк читают. Как?
 
Да и полно таблистов, которые лист строк читают.
Ну раз Вы уверены, что такие бывают - смотрите их код.

Я сам с этой фигней раньше не работал. У меня сегодня вообще впервые что-то в nms получилось сделать)
 
Ну раз Вы уверены, что такие бывают - смотрите их код.

Я сам с этой фигней раньше не работал. У меня сегодня вообще впервые что-то в nms получилось сделать)
Порой иногда приятно осознавать, что чего-то в этой жизни ты ещё не умеешь :)

И всё равно хочется своего добиться.
 
Java:
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";
Такое не устроит?
 
Java:
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";
Такое не устроит?
Беспалевный костыль :lol:

Задачка непростая, как я понял :)
Будем гуглить. Кто-то ведь ещё и анимацию в таб-листе делать умудряется.
 
Мой рабочий код. На всякий случай.
Java:
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);
 
\n это не костыль, это спец символ переноса строки, другого не дано.
 
Матерь божья, изучайте java se api, есть же верно работающий StringJoiner.
"А еще всегда используйте уже готовые средства, структуры данных, кодеки. Даже не пытайтесь придумывать что-то свое!".
Если мне надо будет, я напишу свой StringJoiner.
 
"А еще всегда используйте уже готовые средства, структуры данных, кодеки. Даже не пытайтесь придумывать что-то свое!".
Если мне надо будет, я напишу свой StringJoiner.
1) В данном случае - это костыль.
2) Я такого нигде не говорил.
3) Зачем костылять, если есть уже готовое в Java SE? Пиши тогда еще и свою коллекцию.
 
Статус
Закрыто для дальнейших ответов.
Назад
Верх