Логические структуры
Все логические структуры в AbstractMenus устроены как if -> then -> else и могут вкладываться друг в друга.
Блок действий
Заголовок раздела «Блок действий»Блок действий - это сложный объект, в котором лежат правила и другие действия. Реальная структура:
| Параметр | Тип | Назначение |
|---|---|---|
| rules | Блок правил | Обычные правила |
| actions | Блок действий | Выполняются, если игрок прошёл все правила |
| denyActions | Блок действий | Выполняются, если игрок не прошёл хотя бы одно правило |
Блок легко представить как бесконечное дерево, где каждая ветка - правило или блок действий.

Пример блока действий посложнее:
title: "Пример"size: 6openActions { message: "Открываем меню..." rules { permission: "super.admin" } actions { message: "У тебя есть право super.admin!" rules { money: 1000 } actions { takeMoney: 1000 } denyActions { giveMoney: 1000 } }}Что произойдёт при открытии меню, по порядку:
- В чат прилетает “Открываем меню…”.
- Проверяется право “super.admin”.
- Если право есть - выполняется вложенный блок и отправляется “У тебя есть право super.admin!”.
- Проверяется, есть ли на балансе 1000 валюты.
- Если есть - списывается.
- Если нет - выдаётся 1000.
Блок правил
Заголовок раздела «Блок правил»Локальные действия
Заголовок раздела «Локальные действия»Внутри блока правил можно прописать локальные действия. Удобно, когда снаружи actions и denyActions использовать нельзя. Пример:
items: [ { slot: 0 material: STONE rules { permission: "am.admin" actions { message: "Да!" } denyActions { message: "Нет" } } }]Логика стандартная: actions срабатывают, когда игрок прошёл все правила блока rules. denyActions - когда не прошёл хотя бы одно правило текущего блока.
В примере выше “Нет” прилетит игроку без права am.admin. Блок actions, если бы был, отработал бы наоборот - когда игрок правилам соответствует.
Блок правил как список
Заголовок раздела «Блок правил как список»На самом деле любой rules - это список объектов, где каждый объект - блок правил. Раньше мы просто открывали rules и писали внутри:
rules { permission: "super.admin" group: "vip"}Раз блок правил - это список других блоков, можно прописать несколько похожих правил и в каждый добавить свои локальные действия.
click { message: "Ты кликнул по камешку" rules: [ { permission: "my.perm" actions { message: "У тебя есть право" } }, { money: 500 actions { message: "У тебя достаточно денег" } denyActions { message: "У тебя недостаточно денег. Но возьми." giveMoney: 500 } } ] actions { message: "У тебя достаточно денег и нужное право!" }}Здесь блок правил используется как список. По шагам, что происходит при клике:
- Сообщение “Ты кликнул по камешку”.
- Проверяется право “my.perm”.
- Если право есть - “У тебя есть право”.
- Проверяется баланс на 500 валюты.
- Если деньги есть - “У тебя достаточно денег”.
- Если нет - “У тебя недостаточно денег”, плюс игроку выдаётся 500 монет.
- Если обе проверки прошли - “У тебя достаточно денег и нужное право!”.
Инвертирование правила (оператор “NOT”)
Заголовок раздела «Инвертирование правила (оператор “NOT”)»Любое правило можно инвертировать. Поставь перед его именем - - это “NOT”. Если правило возвращало true, теперь вернёт false, и наоборот.
Пример:
rules { -permission: "group.admin"}actions { message: "Ты не Админ :("}denyActions { message: "Ты Админ!"}Здесь actions сработает, если у игрока нет права group.admin - результат правила permission инвертирован.
Эту запись можно навешивать на любое правило, в том числе на логические обёртки. О них дальше.
Логические обёртки правил
Заголовок раздела «Логические обёртки правил»По умолчанию блок rules склеивает правила через “AND” - даже когда задан списком. Логические обёртки нужны для условий посложнее: можно комбинировать and, or и оператор “NOT”. Под капотом обёртка - это просто правило, внутри которого живут другие правила. Поэтому пишутся обёртки внутри rules.
Обёртка “AND”
Заголовок раздела «Обёртка “AND”»rules и так работает по “AND”, поэтому отдельная обёртка and нужна в основном внутри or. Тем не менее, пример с её прямым использованием:
rules { and { permission: "group.vip" gamemode: CREATIVE }}Правило and вернёт true, если у игрока есть право group.vip И режим игры CREATIVE.
Ещё пример - обёртка как список групп правил. Формат похож на описанный выше.
rules { and: [ { permission: "group.vip" gamemode: CREATIVE }, { permission: "group.helper" } ]}Здесь and вернёт true, если у игрока есть group.vip И режим CREATIVE И право group.helper.
Обёртка “OR”
Заголовок раздела «Обёртка “OR”»Возвращает true, если хотя бы одно из вложенных правил вернуло true.
rules { or { permission: "group.vip" gamemode: CREATIVE }}Здесь or вернёт true, если у игрока есть group.vip ИЛИ режим CREATIVE.
С or в виде списка групп правил поведение такое же. Пример:
rules { or: [ { permission: "group.vip" gamemode: CREATIVE }, { permission: "group.helper" } ]}Здесь or вернёт true, если у игрока есть group.vip ИЛИ режим CREATIVE ИЛИ право group.helper.
Обёртка oneof
Заголовок раздела «Обёртка oneof»oneof пригодится, когда правила задаются списком и у каждого свои локальные действия. По логике это and, но с одной важной разницей. Если взять обычный and как список:
rules { and: [ { permission: "perm1" actions { message: "У тебя есть perm1" } }, { permission: "perm2" actions { message: "У тебя есть perm2" } } ]}то даже если у игрока есть право из первого блока (perm1), его локальные действия выполнятся, но дальше всё равно прогоняются остальные правила, и игрок получит лишние сообщения. И в итоге сам and всё равно вернёт false, если хоть одно правило не прошло.
Иногда это не то, что нужно, - тут и спасает oneof. То же самое через oneof:
rules { oneof: [ { permission: "perm1" actions { message: "У тебя есть perm1" } }, { permission: "perm2" actions { message: "У тебя есть perm2" } } ]}то если у игрока есть perm1, локальные действия тоже выполнятся, но oneof сразу остановится и вернёт true. Если ни одно из правил не подошло - вернёт false.
С oneof можно спокойно навешивать локальные действия и быть уверенным, что выполнятся ровно те, что относятся к сработавшему блоку правил. Пример:
rules { oneof: [ { permission: "perm1" actions { message: "У тебя есть perm1" } }, { permission: "perm2" actions { message: "У тебя есть perm2" } } ] denyActions { // Сработает, только если ни одно правило в списке не прошло message: "Ни одно из требуемых правил не выполнено" }}Обёртка playerScope
Заголовок раздела «Обёртка playerScope»Прогоняет вложенные правила в контексте другого игрока. Удобно, когда у тебя есть плейсхолдер, который разворачивается в имя другого игрока (например, цель, выбранная через активатор command), и проверять правила нужно по нему, а не по зрителю меню.
rules { playerScope { name: "%activator_cmd_arg_target%" rules { permission: "myserver.vip" gamemode: SURVIVAL } }}name- игрок, в чей контекст переключаемся. Плейсхолдеры раскрываются.rules- блок правил, который проверяется против этого игрока. Структура - как у обычногоrules.
Если такой игрок не онлайн, обёртка просто вернёт false, без исключения.
Комбинирование логических обёрток
Заголовок раздела «Комбинирование логических обёрток»Обёртки можно вкладывать друг в друга и собирать любые условия. Пример:
rules { or: [ { and { permission: "vip" gamemode: CREATIVE } }, { and { permission: "premium" gamemode: SURVIVAL } } ]}Здесь or вернёт true, если:
у игрока есть vip AND режим CREATIVE
ИЛИ
у игрока есть premium AND режим SURVIVAL.
Использование одинаковых действий и правил в одном блоке
Заголовок раздела «Использование одинаковых действий и правил в одном блоке»Как и многие другие форматы, HOCON не разрешает повторять один и тот же ключ в одном блоке. Например:
click { message: "Привет" // Ок message: "Привет снова" // Ошибка парсинга}упадёт парсер - в одном блоке не может быть нескольких параметров с одним именем. Иногда это мешает: например, когда нужно несколько одинаковых действий подряд. В AbstractMenus есть обёртка bulk, но читается она так себе. Есть способ проще.
Чтобы засунуть несколько одинаковых действий или правил в один блок, добавь к имени параметра префикс _. Например:
click { message: "Привет" _message: "Привет снова" __message: "Привет снова и снова" ___message: "Привет снова и снова и снова"}Парсер на это не ругается - имена у параметров разные. После парсинга, но до десериализации действий и правил, плагин обрезает префиксные _, и имена правил и действий снова становятся корректными.
Через тот же приём можно класть несколько правил в один логический блок. Пример:
rules { or { gamemode: SURVIVAL _gamemode: ADVENTURE __gamemode: SPECTATOR }}Обёртка or вернёт true, если хотя бы одно из правил подходит игроку.
Эта запись с префиксами эквивалентна такой:
rules { or: [ { gamemode: SURVIVAL }, { gamemode: ADVENTURE }, { gamemode: SPECTATOR } ]}То есть, используя префикс _ для правил, мы избегаем шаблонного кода.