ZLDiscord v1.2 — Документация
Введение
ZLDiscord — универсальный плагин для Paper 1.16.5–1.21.x, интегрирующий Minecraft с Discord. Встроенный шаблонизатор, LongPoll-бот, кастомные команды, голосования, DataStore и полная поддержка PlaceholderAPI.
Установка
- Скопировать
ZoLiryzik.jarвplugins/ - Запустить LongPoll-бота:
node longpoll-server.js & - Перезапустить сервер (stop → start, не /reload)
- Настроить
config.yml: Discord Token, Guild ID, роли - Подключить LongPoll:
/zlongpoll create demo http://localhost:17523/poll secret 25
Команды
/zevent — Голосование
/zevent "Название" "команда" "время" "channel_id"
- Название — заголовок embed (поддерживает
%placeholder%) - команда — Minecraft-команда консоли при победе ✅
- время — длительность:
5s,10m,1h - channel_id — ID текстового канала Discord
После таймера подсчитываются ✅ / ❌. При победе ✅ — выполняется команда.
/zcc — Кастомные команды
/zcc list — список команд
/zcc run <name> — выполнить
/zcc create <name> — создать (\n для новой строки)
/zcc remove <name> — удалить
/zcc reload — перезагрузить
/zlink / /zunlink — Привязка Discord
/zlink — получить код в Minecraft
/unlink — отвязать в Discord (ЛС бота)
/zembed — Embed-сообщение
/zembed "имя" "заголовок" "описание" "channel_id" [картинка] [миниатюра] [футер] [иконка_футера]
Создаёт embed в Discord, сохраняет messageId. PAPI
/zembedmanage — Управление embed
/zembedmanage delete <имя>
/zembedmanage edit_title <имя> "новый заголовок"
/zembedmanage edit_description <имя> "новое описание"
/zattr — DataStore
/zattr get <bot|member|player> <key> [player]
/zattr set <bot|member|player> <key> <value> [player]
/zattr inc|dec <...> <key> <amount> [player]
/zattr list <bot|member|player> [player]
/zlongpoll — LongPoll
/zlongpoll create <name> <url> <key> [wait]
/zlongpoll list
/zlongpoll remove <name>
/zlongpoll reload
Команды в Discord
Prefix Текстовые команды в Discord имеют фиксированный префикс z! (например, z!hello, z!info). Поменять его нельзя.
/zevent— создать голосование (роли embed-creator)!embed— кнопка для создания Embed/link <code>— привязать (ЛС бота)/unlink— отвязать (ЛС бота)- Slash-команды из
custom_commands.ymlрегистрируются автоматически - Текстовые команды из
custom_commands.yml— через префиксz!(например,z!warn,z!report)
Кастомные команды
Файл custom_commands.yml:
commands:
hello:
file: "commands/hello.yml"
description: "Приветствие"
cooldown: 10
enabled: true
scope: all # all / minecraft / discord
permission: zoliryzik.hello
permission-message: "&cНет прав"
command_mc: hello # имя в майнкрафте
command_ds: hello # имя в дискорде (префикс z! — z!hello, изменить нельзя)
aliases_mc: ["h"]
aliases_ds: ["h"]
discord-roles: ["role_id_1", "role_id_2"]
Поддерживается вложенность папок: commands/lp/lp.yml
Пример hello.yml
<~ args[0] ~>, привет с сервера!
Пример fly.yml (условия, аргументы, PAPI)
<set target = args[0]>
<require target != null return "Укажи ник игрока">
<set mode = args[1]>
<if mode == null or mode == "">
<set mode = "toggle">
</if>
<if mode == "on">
<do mc.command("zflytoggle " + target + " on")>
<~ target ~>: полёт &aвключён
<elseif mode == "off">
<do mc.command("zflytoggle " + target + " off")>
<~ target ~>: полёт &cвыключен
<else>
<do mc.command("zflytoggle " + target)>
<~ target ~>: полёт переключён
</if>
Система шаблонов
Переменные
| Переменная | Где | Описание |
|---|---|---|
args | всегда | List аргументов |
_args_raw | всегда | Строка аргументов |
_cmd_name | всегда | Имя команды |
_lang | всегда | Язык: ru/en |
mc_online | всегда | Игроков онлайн |
mc_max_players | всегда | Макс. игроков |
mc_tps | всегда | TPS |
mc_motd | всегда | MOTD |
_player_name | Minecraft | Имя игрока |
_player_uuid | Minecraft | UUID |
_player_world | Minecraft | Мир |
_discord_member_id | Discord | ID участника |
_discord_member_name | Discord | Имя |
_discord_member_nick | Discord | Никнейм |
_discord_channel_id | Discord | ID канала |
_discord_channel_name | Discord | Название канала |
_discord_guild_id | Discord | ID гильдии |
_discord_guild_name | Discord | Название гильдии |
_mentioned_user_id | Discord | ID упомянутого |
_mentioned_user_name | Discord | Имя упомянутого |
Теги
| Тег | Описание |
|---|---|
<~ expr ~> | Вывести значение |
<set var = expr> | Присвоить переменную |
<if cond>...<else>...</if> | Условие |
<for var in list>...</for> | Цикл |
<do action(...)> | Выполнить действие |
<require cond return "msg"> | Проверка с ошибкой |
<return "msg"> | Выход с сообщением |
<global var = expr> | Глобальная переменная |
<# comment #> | Комментарий |
Функции
Строки: lower, upper, capitalize, trim, title, replace(a,b,s), split(sep,s), length, format, after(N)
Проверки: defined, empty, not, number, iterable, even, odd, contains, startsWith, endsWith, typeof
Математика: abs, round, number_format, random(min,max), random_hex, random_uuid
Коллекции: first, last, reverse, slice, sort, shuffle, batch, concat, join, keys, values, default
PAPI: papi("placeholder" [, player])
DataStore: getattribute(key), member.getattribute(key), player.getattribute(key), bot.getattribute(key), find_player_by_session(id)
HTTP: http_get(url), http_post(url, body|key,val...), http_put, http_delete, http_patch, http_code(resp), http_body(resp), http_header(name,val), http_bearer(token), json_parse(str)
Действия (<do>)
| Действие | Описание |
|---|---|
mc.command("cmd") | Выполнить команду (консоль/игрок) |
mc.broadcast("msg") | Отправить в чат (& для цвета) |
mc.give("player","item") | Выдать предмет |
discord.send(channelId,"text") | Сообщение в Discord |
discord.embed(...) | Embed (title, description, color, fields, buttons, reactions) |
discord.role_add/give(memberId, roleId) | Добавить роль |
discord.role_remove/delete(memberId, roleId) | Удалить роль |
bot.setstatus("online/dnd/idle") | Статус бота |
bot.setstatustext("текст") | Текст статуса |
Chain API
guild.getChannel("id").createEmbed().withTitle("...").withColor("#hex").withField("n","v",true).send()
Статус бота
Файл bot_status.yml:
enabled: true
type: "playing" # playing / watching / listening / competing / custom
text: "с сервером"
LongPoll Bot API
Node.js-бот на http://localhost:17523. Аутентификация: Authorization: Bearer secret.
| Метод | Endpoint | Тело |
|---|---|---|
| POST | /event | {"type":"...", ...} |
| POST | /api/config | {"key":"value"} |
| GET | /api/script?type=X | — |
| POST | /api/script?type=X | {"script":"..."} |
LongPoll скрипты
Путь: longpoll/papca/<connection>/<type>.yml
| Переменная | Описание |
|---|---|
_event | Map со всеми полями |
_event.type | Тип события |
_event.player, ... | Поля из JSON |
_conn_name | Имя подключения |
Важно Только <do action(...)>, НЕ <action(...)>.
Пример donate.yml
<if !defined(_event.nickname)>
<do mc.command("say", "Donate: no nickname in event")>
<else>
<set _nick = _event.nickname>
<set _amount = _event.amount>
<do mc.command("give " + _nick + " diamond " + (_amount / 100))>
<if _lang == "ru">
<do mc.broadcast("&a🎉 Игрок " + _nick + " задонатил &e" + _amount + " &aи получил " + (_amount / 100) + " алмазов!")>
<else>
<do mc.broadcast("&a🎉 Player " + _nick + " donated &e" + _amount + " &aand got " + (_amount / 100) + " diamonds!")>
</if>
<do player.getAttribute("donations").increment(_amount)>
</if>
PlaceholderAPI
- Игрок — от имени отправителя
- Консоль — от первого онлайн
- papi("x", "Nick") — для любого игрока
| Плейсхолдер | Описание |
|---|---|
%zoliryzik_in_vc% | Статус в голосовом канале: "В голосовом чате" / "Не в голосовом чате" / "Не привязан" |
%zoliryzik_attr_member_<key>% | Атрибут Discord-участника из DataStore по ключу |
%zoliryzik_attr_player_<key>% | Атрибут игрока из DataStore по ключу |
%zoliryzik_attr_bot_<key>% | Глобальный атрибут бота из DataStore по ключу |
Конфигурация
Загрузка...
Переменные окружения
| Переменная | Описание |
|---|---|
DISCORD_TOKEN | Токен Discord бота |
LONGPOLL_KEY | Ключ API (умолч. secret) |
LONGPOLL_PORT | Порт (умолч. 17523) |
Примеры скриптов
Примеры для отправки событий в LongPoll-бот из внешних скриптов.
Python
import requests, json
URL = "http://localhost:17523/event"
HEADERS = {
"Authorization": "Bearer secret",
"Content-Type": "application/json"
}
# Отправить событие donate
event = {
"type": "donate",
"nickname": "Player123",
"amount": 1500,
"product": "Diamond Pack"
}
r = requests.post(URL, headers=HEADERS, json=event)
print("Status:", r.status_code, r.json())
# Отправить событие kick
event = {
"type": "kick",
"nickname": "Griefer",
"reason": "Spam",
"moderator": "Admin"
}
r = requests.post(URL, headers=HEADERS, json=event)
print("Status:", r.status_code, r.json())
Node.js
const URL = "http://localhost:17523/event";
const HEADERS = {
"Authorization": "Bearer secret",
"Content-Type": "application/json"
};
// Отправить событие donate
fetch(URL, {
method: "POST",
headers: HEADERS,
body: JSON.stringify({
type: "donate",
nickname: "Player123",
amount: 1500,
product: "Diamond Pack"
})
}).then(r => r.json()).then(console.log);
// Отправить событие kick
fetch(URL, {
method: "POST",
headers: HEADERS,
body: JSON.stringify({
type: "kick",
nickname: "Griefer",
reason: "Spam",
moderator: "Admin"
})
}).then(r => r.json()).then(console.log);
curl
curl http://localhost:17523/event -X POST \
-H "Authorization: Bearer secret" \
-H "Content-Type: application/json" \
-d '{"type":"donate","nickname":"Player123","amount":1500}'
curl http://localhost:17523/event -X POST \
-H "Authorization: Bearer secret" \
-H "Content-Type: application/json" \
-d '{"type":"kick","nickname":"Griefer","reason":"Spam","moderator":"Admin"}'
Примеры
LP команда из Minecraft
<set _ = http_header("Authorization", "Bearer secret")>
<set _type = args[0]>
<set _resp = http_post("http://localhost:17523/event",
"type", _type, "player", _player_name, "world", _player_world,
"cmd", _cmd_name, "args", _args_raw)>
<do mc.broadcast("&a[LP] &f" + _type + " &a✓")>
Donate-уведомление
<if _event.amount >= 5000>
<do mc.broadcast("&a&l⭐ Мега-донат от &e" + _event.nickname)>
<else>
<do mc.broadcast("&a❤ " + _event.nickname + " задонатил &e" + _event.amount)>
</if>
Информация об игроке (info.yml)
<set target = args[0]>
<if target == null or target == "">
<set target = _player_name>
</if>
📊 Информация о <~ target ~>
├ Уровень: <~ papi("%level%", target) ~>
├ Здоровье: <~ papi("%player_health%", target) ~>
├ Мир: <~ papi("%player_world%", target) ~>
└ Онлайн: <~ mc_online ~>/<~ mc_max_players ~>
Report (Discord-команда)
<set target = args[0]>
<set reason = after(1)>
<require target != null and reason != "" return "Укажи ID или упоминание нарушителя и причину">
Был отправлен репорт на участника <~ target ~>:
<~ reason ~>
<do discord.send(_discord_channel_id, format("%s, Ваш репорт успешно отправлен!", _discord_member_nick))>
Диагностика
/zdiag (ZDiag) — 12 тестов: бот, каналы, роли, LongPoll, атрибуты, HTTP, шаблоны, PAPI, права.