GUI API
Полное руководство по GUI API 1.0.8: загрузка меню, YAML-контракт, действия, условия, перезагрузка, масштабирование и UX-паттерны.
GUI API
GUI API NextLib — это YAML-driven система инвентарных интерфейсов. Вы храните меню в файлах, а библиотека превращает их в рабочие GUI с обработкой кликов.
1. Ментальная модель GUI API
Система состоит из трёх слоёв:
GuiManager— загрузка/реестр/открытие/refresh.GuiLoader— парсинг YAML вGuiиGuiItem.Actions+Conditions— DSL для поведения и динамики.
Ключевой плюс: контент редактабелен без перекомпиляции плагина.
2. Инициализация и жизненный цикл
GuiManager guiManager = new GuiManager(plugin);
guiManager.loadFromFolder(new File(plugin.getDataFolder(), "menus"));
Что делает loadFromFolder:
- сохраняет директорию меню,
- запускает
reloadAll().
Что делает reloadAll:
- Закрывает открытые GUI игрокам.
- Очищает текущий registry.
- Сканирует
.ymlфайлы. - Создаёт
GuiчерезGuiLoader. - Регистрирует GUI по id (обычно имя файла без
.yml).
Практическое следствие: любые изменения YAML можно подхватить без перезапуска сервера.
3. Полный YAML-контракт
Верхний уровень
title: заголовок инвентаря.size: размер (обычно 9..54, кратно 9).items: словарь элементов.
Item-уровень
materialamountnameloreslotилиslotson_left_clickon_right_clickenchanted_when
Минимальный пример:
title: "&8Главное меню"
size: 27
items:
shop:
material: EMERALD
slot: 11
name: "&aМагазин"
on_left_click:
- "opengui shop"
Важно: runtime использует snake_case ключи. CamelCase-варианты не сработают.
4. Слоты: точка, диапазон, композиция
Один слот
slot: 13
Несколько/диапазоны
slots:
- "0-8"
- "9"
- "17"
- "18-26"
Поведение парсера:
- некорректные значения -> warning в лог,
- слот вне размера меню -> warning и пропуск,
- дубли слотов внутри элемента дедуплицируются.
5. Встроенные actions: полный список
closecommand <cmd>console <cmd>message <text>opengui <id>updateplaysound <SOUND> [volume] [pitch]
Что делает каждый
close
Закрывает текущий инвентарь игрока.
command
Выполняет команду от игрока.
console
Выполняет команду от консоли.
message
Шлёт сообщение игроку через formatter библиотеки.
opengui
Открывает другое меню по id.
update
Вызывает refresh GUI для игрока.
playsound
Воспроизводит звук. Если имя звука неверное, будет warning и no-op.
6. Примеры composable actions
buy:
material: DIAMOND
slot: 13
name: "&bКупить"
lore:
- "&7Цена: &e100"
on_left_click:
- "console eco take %player% 100"
- "message &aПокупка успешна"
- "playsound ENTITY_PLAYER_LEVELUP 1.0 1.0"
- "update"
Практика:
- сначала побочный эффект (команда экономики),
- потом feedback (message/sound),
- затем
updateдля визуальной консистентности.
7. Условия (Conditions)
Из коробки только:
alwaysnever
Всё остальное вы регистрируете сами.
Регистрация кастомного условия
Conditions.registerCondition("has_permission", (manager, args) ->
player -> player.hasPermission(args)
);
YAML:
admin:
material: COMMAND_BLOCK
slot: 10
name: "&cАдминка"
enchanted_when:
- "has_permission myplugin.admin"
8. Кастомные actions
Actions.registerAction("teleport", (manager, args) -> player -> {
String[] parts = args.split(",");
double x = Double.parseDouble(parts[0]);
double y = Double.parseDouble(parts[1]);
double z = Double.parseDouble(parts[2]);
player.teleport(new Location(player.getWorld(), x, y, z));
});
YAML:
spawn:
material: ENDER_PEARL
slot: 15
name: "&bНа спавн"
on_left_click:
- "teleport 0,100,0"
Рекомендация: все кастомные actions/conditions регистрируйте до loadFromFolder.
9. Programmatic GUI (без YAML)
Gui gui = guiManager.createGui("debug", "&8Debug", 27);
GuiItem item = new GuiItem(new ItemStack(Material.PAPER), 13);
item.addLeftClickAction(player -> player.sendMessage("clicked"));
gui.addItem(item);
Используйте этот подход для временных/диагностических меню или динамической сборки из БД.
10. Интеграция с Reload API
context.reload().register(new Reloadable() {
@Override
public String id() { return "gui.menus"; }
@Override
public void reload() {
guiManager.reloadAll();
}
});
Так /reload команды перестают быть опасными и становятся управляемыми.
11. Большие паттерны проектирования GUI
Паттерн A: Main hub
main.ymlтолько навигация.- Бизнес-логика в дочерних меню.
Паттерн B: Domain folders
menus/shop/*.ymlmenus/quests/*.ymlmenus/admin/*.yml
Паттерн C: Action naming policy
Если у вас много кастомных actions, используйте namespace:
shop_buyquest_acceptadmin_reset
12. Производительность
Симптомы:
- лаги при массовом открытии меню,
- задержка кликов,
- частые refresh на каждом тике.
Решения:
- Не делайте дорогие DB-вызовы прямо в click actions без кеша.
- Не спамьте
updateбез необходимости. - Крупные вычисления предварительно кэшируйте.
13. Частые ошибки и диагностика
GUI '<id>' not found!
- меню не загружено,
- id не совпадает с файлом,
- вызов открытия раньше загрузки.
Unknown GUI action ...
- опечатка,
- забыли
Actions.registerAction.
Unknown GUI condition ...
- забыли
Conditions.registerCondition.
Кнопка «есть», но клик пустой
- неверный ключ действия,
- слот вышел за границы и item не создался,
- действие содержит неверные аргументы.
14. UX-рекомендации
- Давайте явные названия кнопок («Купить», «Назад», «Подтвердить»).
- Добавляйте контекст в lore (цена, лимиты, награда).
- После важных действий давайте моментальный feedback (message + playsound).
- На рискованных действиях делайте confirm-экран.
15. Антипаттерны
- Один огромный YAML на всё.
- Дублирование одинаковых блоков без структуры.
- Скрытая бизнес-логика в лоре.
- Непредсказуемый set команд без логирования.
16. Большой FAQ
Можно ли делать пагинацию?
Да. Обычно через несколько меню (shop_page_1, shop_page_2) или динамическую сборку programmatic GUI.
Можно ли работать без PlaceholderAPI?
Базово да, но встроенные action-команды могут использовать PlaceholderAPI для подстановок.
Можно ли condition на основе базы данных?
Да, но лучше читать из кеша/предзагруженной модели, а не делать SQL в каждый рендер/клик.
Если следовать этим правилам, GUI API остаётся стабильным даже на большом количестве меню и игроков.