⚡ GLOW + TAB | ДЕЛАЕМ ЦВЕТНОЕ СВЕЧЕНИЕ, КОТОРОЕ РЕАЛЬНО РАБОТАЕТ

Руководство ⚡ GLOW + TAB | ДЕЛАЕМ ЦВЕТНОЕ СВЕЧЕНИЕ, КОТОРОЕ РЕАЛЬНО РАБОТАЕТ

Поддерживаемые версии
  1. 1.16


В чём, собственно, боль

Пишу я, значит, модуль кастомизации для своего плагина — цветной глов админам. Команда /myplugin color <цвет> даёт игроку эффект GLOWING, а я через scoreboard-команду (Team.setColor()) крашу его в нужный цвет. В игре всё работает — красный, синий, радужный.

Но захожу на сервер с TAB — и вижу, что глов стал белым. Игрок светится, но дефолтным цветом. Радуга не переливается, красный не красный. Просто белое свечение.

И тут начинается классика: «а давай полезу в API TAB», «а почему TAB перезаписывает мои команды», «а можно как-то заставить его не трогать мои scoreboard-команды»

Спойлер: лезть в API TAB не надо. Официальная документация TAB сама говорит, что делать. Ниже — как я это сделал у себя.



Почему TAB ломает глов (коротко)

Глов в Minecraft — это не «цвет эффекта». Это цвет scoreboard-команды, в которой состоит игрок. Задаёшь команде RED — глов красный. Задаёшь BLUE — синий. Это единственный способ красить свечение в Bukkit/Paper.

Проблема в том, что TAB тоже использует scoreboard-команды — для сортировки игроков в табе, для префиксов, суффиксов и т.д. А Minecraft устроен так, что игрок может быть только в одной команде одновременно.

Что происходит:
  • Твой плагин: добавляет игрока в команду myplugin_red → глов красный.
  • TAB: видит, что игрок не в его команде → выкидывает его из твоей и добавляет в свою → глов становится белым.
  • И так каждый тик. Ты добавляешь — он выкидывает. В итоге побеждает TAB.

Именно поэтому в официальном вики TAB написано: «Only one plugin can handle teams at a time» — только один плагин может управлять командами.



Решение — отдать цвет через PlaceholderAPI

TAB не даёт тебе красить глов напрямую через команды. Но он сам красит глов, если ты скажешь ему цвет — через последний цветовой код в tagprefix.

Как это работает: TAB смотрит на tagprefix игрока, берёт последний цветовой код (§c, §6 и т.д.) и ставит его в свою команду. Этот цвет применяется и к нику, и к глову.

Значит, задача сводится к простому: дать TAB’у плейсхолдер, который возвращает текущий цвет глова.



Шаг 1. Регистрируем expansion для PlaceholderAPI

Java:
package me.jonycape.dev.myplugin.placeholder;

import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import me.jonycape.dev.myplugin.Main;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;

public final class MyExpansion extends PlaceholderExpansion {

    @Override
    public String getIdentifier() {
        return "myplugin";
    }

    @Override
    public String getAuthor() {
        return "jonycape";
    }

    @Override
    public String getVersion() {
        return "1.0.0";
    }

    @Override
    public boolean persist() {
        // без этого expansion слетит при /papi reload
        return true;
    }

    @Override
    public String onPlaceholderRequest(Player player, String params) {
        if (player == null) {
            return "";
        }
        if (!params.equalsIgnoreCase("glowcolor")) {
            return "";
        }
        Main main = Main.getInstance();
        if (main == null || main.getCustomizeService() == null) {
            return "";
        }
        ChatColor color = main.getCustomizeService().currentColor(player);
        // возвращаем legacy-формат §c, §6 и т.д.
        return color == null ? "" : color.toString();
    }
}

Регистрация в onEnable() — с проверкой, что PlaceholderAPI вообще есть:

Java:
private void initPlaceholders() {
    if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") == null) {
        return;
    }
    try {
        new MyExpansion().register();
        getLogger().info("Зарегистрировано расширение PlaceholderAPI 'myplugin'.");
    } catch (Throwable t) {
        getLogger().log(Level.WARNING, "Не удалось зарегистрировать расширение PlaceholderAPI", t);
    }
}



Шаг 2. Вклеиваем плейсхолдер в tab.yml

Важно:
плейсхолдер должен быть в самом конце tagprefix. TAB берёт именно последний цветовой код[citation:1][citation:8].

У меня в tab.yml секция admin выглядит так:

YAML:
admin:
  tabprefix: "%player_world% &8❘ &7[%hsubscribe_vip_check%&7]%luckperms-prefix%"
  tagprefix: "%luckperms-prefix%%myplugin_glowcolor%"
  tabsuffix: "%luckperms-suffix%"
  tagsuffix: "%luckperms-suffix%"

Ключевая строка — tagprefix. Плейсхолдер идёт после %luckperms-prefix%, в самом конце. TAB прочитает цвет из %myplugin_glowcolor% и применит его к глову.

Что было бы без плейсхолдера: TAB брал бы последний цвет из %luckperms-prefix% (если он вообще есть) или ставил бы белый дефолт. Твой глов был бы белым, сколько бы ты ни красил команды в своём плагине.



Шаг 3. Радуга обновляется сама

У меня в CustomizeService есть таск, который тикает раз в N тиков и меняет currentColor для радужного режима:

Java:
private static final ChatColor[] RAINBOW = {
    ChatColor.RED, ChatColor.GOLD, ChatColor.YELLOW,
    ChatColor.GREEN, ChatColor.AQUA, ChatColor.BLUE,
    ChatColor.LIGHT_PURPLE
};

private void tick() {
    // ...
    if (state.isRainbow()) {
        if (rainbowTick) {
            applyRainbow(player, nextRainbow());
        }
    }
    // ...
}

Плейсхолдер %myplugin_glowcolor% при следующем запросе от TAB вернёт новый цвет. TAB обновит tagprefix → обновит team color → глов перекрасится.

Нюанс: TAB опрашивает плейсхолдер не каждый тик, а по своим интервалам. Радуга в глове будет чуть медленнее, чем в твоём таске. У меня выглядит нормально.



Подводные камни

1. Плейсхолдер ТОЛЬКО в конце tagprefix

Официальное требование TAB[citation:1][citation:8]. Если поставить его в середину — TAB возьмёт не тот цвет. Если после него есть текст с цветом — всё сломается.

2. MiniMessage не поймёт §c
Если TAB в MiniMessage-режиме, ChatColor.toString() с §c может не сработать. Либо оставляй legacy-режим в TAB, либо возвращай теги:

Java:
// вместо color.toString()
return "<" + color.name().toLowerCase().replace("_", "") + ">";

Но с legacy надёжнее — TAB его до сих пор поддерживает стабильно[citation:5].

3. PlaceholderAPI обязателен
В plugin.yml:
YAML:
softdepend:
  - PlaceholderAPI
  - TAB

4. Твои scoreboard-команды всё ещё нужны
Да, TAB управляет командами. Но твой applyColorTeam всё равно нужен — для тех случаев, когда TAB не установлен или отключён на сервере. Плейсхолдер — это мост для TAB, а не замена scoreboard-механизма.



Итог

  • Глов в мире — цветной, как задумано, даже с TAB.
  • Радуга работает.
  • Префиксы и сортировка TAB не сломаны.
  • Весь фикс — один класс на 40 строк и одна строка в tab.yml.

Официальная документация TAB сама описывает это решение — я лишь адаптировал его под свой плагин. Если у кого-то похожая задача — не лезьте в API TAB, посмотрите в сторону PlaceholderAPI. В 90% случаев хватает его.



Вопросы по коду — пишите в тему.
Автор
jonycape
Просмотры
122
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок

Поделиться ресурсом

Назад
Сверху Снизу