BetonQuest: настройка квестов на Minecraft сервере (гайд 2026)

BetonQuest: настройка квестов на Minecraft сервере (гайд 2026)

Если в RPG-проекте нужны не "убей 10 зомби", а полноценные ветки диалогов с NPC, условиями и наградами, BetonQuest закрывает эту задачу декларативным YAML без единой строки кода. Ниже разберём установку, формат пакетов 2.x, работу objectives и conditions, интеграцию с Citizens и DecentHolograms, миграцию со старой версии и узкие места по производительности.

Что такое BetonQuest и зачем декларативные квесты

BetonQuest - это плагин для Bukkit-совместимых ядер, который описывает квесты через текстовые YAML-файлы. Никаких скриптов, никаких компиляторов: пишешь конфиг, перезагружаешь плагин, квест работает. Исходники и документация лежат на github.com/BetonQuest/BetonQuest и docs.betonquest.org.

Философия плагина простая: квест - это связка из четырёх элементов.

  • Objectives - задачи, которые игрок выполняет (убить моба, скрафтить предмет, дойти до точки)
  • Conditions - условия, которые проверяются (есть ли тег, какой класс, какой уровень)
  • Events - действия, которые сервер выполняет в ответ (выдать предмет, телепортнуть, поставить тег)
  • Conversations - дерево диалогов с NPC, в узлах которого живут условия и события

В сумме получается граф состояний игрока, где переходы между нодами управляются тегами и поинтами. Никакого жёсткого кода для веток "если игрок спас принцессу, то деревенский кузнец даёт скидку" не нужно: всё описывается условиями tag и событиями tag add.

Альтернативы есть. Quests Plugin проще для старта, но потолок у него низкий: сложные ветки и условия туда не вписать. ZNPCsPlus + ZSkriptCore работают, но требуют Skript-кода. Если нужен взрослый RPG-сервер с сотнями нод диалогов и сейв-системой между сессиями - BetonQuest стоит брать сразу.

Установка и зависимости

BetonQuest 2.x работает на Paper 1.21+ и требует Java 21. Старые ядра (1.16-1.20) поддерживает ветка 1.x, но новые фичи туда уже не бэкпортируются.

cd plugins/
wget -O BetonQuest.jar https://github.com/BetonQuest/BetonQuest/releases/latest/download/BetonQuest.jar
# либо качай с hangar.papermc.io/BetonQuest/BetonQuest

После старта сервера появится папка plugins/BetonQuest/ со структурой:

plugins/BetonQuest/
├── config.yml
├── messages.yml
├── menuConfig.yml
├── lang/
└── QuestPackages/
    └── default/
        ├── package.yml
        ├── events.yml
        ├── conditions.yml
        ├── objectives.yml
        ├── conversations/
        └── journal.yml

Опциональные интеграции, которые ставят почти все:

  • Citizens - чтобы привязывать диалоги к видимым NPC, а не к стоящим скелетам
  • DecentHolograms - голограммы над NPC и в точках интереса
  • LuckPerms - выдача прав через события permission
  • PlaceholderAPI - подстановка %betonquest_*% в чат, сайдбар, голограммы
  • MythicMobs - спавн боссов событиями BetonQuest и условия по убитому MythicMob
  • ProtocolLib - нужен для нескольких подсистем, ставится почти всегда

После любых правок YAML вызывайте /q reload. Это перечитывает все пакеты без рестарта сервера. Если в чате появилось красное сообщение про ошибку парсинга - открывайте logs/latest.log, BetonQuest пишет туда полный путь к проблемной строке.

Package layout в 2.x: главное отличие от 1.x

В версии 2.x пакеты стали полноценными директориями. Раньше один файл package.yml хранил всё: события, условия, objectives, диалоги. Теперь наоборот - всё разнесено по подпапкам, и любой файл внутри пакета автоматически собирается в общую конфигурацию.

QuestPackages/
└── city_quests/
    ├── package.yml          # метаданные пакета
    ├── events/
    │   ├── reward.yml
    │   └── teleport.yml
    ├── conditions/
    │   └── access.yml
    ├── objectives/
    │   └── main_chain.yml
    ├── conversations/
    │   ├── innkeeper.yml
    │   └── blacksmith.yml
    └── journal.yml

Это сильно облегчает жизнь, когда квестов 50+. Можно держать каждый сюжетный блок в своём файле, а саб-пакеты делать через вложенные папки: QuestPackages/main/chapter_one/ и QuestPackages/main/chapter_two/ будут двумя отдельными пакетами с именами main-chapter_one и main-chapter_two.

Файл package.yml минимально выглядит так:

package:
  enabled: true
  priority: 0
variables:
  city_name: "Нортхэвен"
  reward_amount: 200

Переменные из variables: дальше доступны как %city_name% в любом тексте диалога или сообщения.

Первый диалог: пример conversation YAML

Создадим файл QuestPackages/city_quests/conversations/innkeeper.yml. Это диалог с трактирщиком, который даёт квест на крыс в подвале.

conversations:
  innkeeper:
    quester: "&6Трактирщик"
    first: greeting
    NPC_options:
      greeting:
        text: "Странные звуки из подвала... Не глянешь, что там?"
        conditions: "!quest_started,!quest_done"
        pointers: accept,ask_reward,decline
      already_started:
        text: "Ну как, разобрался с крысами?"
        conditions: "quest_started,!rats_killed"
        pointers: still_busy,decline
      give_reward:
        text: "Спасибо, держи! За мной не заржавеет."
        conditions: "rats_killed,!quest_done"
        events: pay_reward,close_quest
      after_done:
        text: "Заходи ещё, путник."
        conditions: "quest_done"
    player_options:
      accept:
        text: "Гляну. Где вход?"
        events: start_quest,give_torch
        pointer: accepted
      ask_reward:
        text: "А что за это будет?"
        pointer: reward_info
      decline:
        text: "Не сейчас."
      still_busy:
        text: "Ещё ищу их."
      reward_info:
        text: "200 монет и ужин за счёт заведения."
        pointer: greeting

Что тут происходит:

  • quester - имя, которое игрок видит в окне диалога
  • first - стартовый узел NPC, с которого начинается разговор
  • NPC_options - реплики NPC. У каждой свои условия и список указателей на варианты игрока
  • player_options - реплики игрока. Каждая может запускать события и переходить дальше по pointer
  • conditions - какие условия должны выполниться, чтобы реплика показалась. Префикс ! инвертирует
  • events - срабатывают, когда реплика выбрана

Пока не описали accept, quest_started, pay_reward - сервер ругнётся при /q reload. Двигаемся к objectives и events.

Objectives и conditions: задачи и проверки

Объектива в QuestPackages/city_quests/objectives/main_chain.yml:

objectives:
  hunt_rats:
    type: mobkill
    conditions: ""
    events: rats_done
    instruction: mobkill RAT 5 events:rats_done notify
  reach_cellar:
    type: location
    instruction: location 100;64;200;world 3 events:cellar_reached
  craft_torch:
    type: craft
    instruction: craft TORCH 4

Тип mobkill использует MythicMob с id RAT, поэтому в этом примере нужен MythicMobs. Если хочется ванильного зомби - заменяйте на mobkill ZOMBIE 5. Параметр notify показывает игроку прогресс через ActionBar.

Условия в conditions.yml:

conditions:
  quest_started:
    type: tag
    instruction: tag rats_quest_started
  rats_killed:
    type: objective
    instruction: objective hunt_rats
  quest_done:
    type: tag
    instruction: tag rats_quest_done
  has_torch:
    type: item
    instruction: item torch:1
  is_warrior:
    type: variable
    instruction: variable %class% warrior

Условия читаются как "проверка сервера в момент клика". Если игрок выбирает реплику accept, BetonQuest проверяет все условия родительского узла NPC, и только при их выполнении реплика отрисуется.

Events и tags: что плагин делает в ответ

События - это то, что сервер запускает на действие игрока или по таймеру. Файл events.yml:

events:
  start_quest:
    type: tag
    instruction: tag add rats_quest_started
  pay_reward:
    type: give
    instruction: give emerald:5,gold_ingot:10
  close_quest:
    type: folder
    instruction: folder mark_done,remove_objective,journal_finished
  mark_done:
    type: tag
    instruction: tag add rats_quest_done
  remove_objective:
    type: objective
    instruction: objective remove hunt_rats
  give_torch:
    type: give
    instruction: give torch:4
  journal_finished:
    type: journal
    instruction: journal add rats_finished
  teleport_cellar:
    type: teleport
    instruction: teleport 100;64;200;world
  rats_done:
    type: notify
    instruction: notify {en}Rats cleared!{ru}Крысы уничтожены! io:Title

Хитрость с folder - это контейнер из нескольких событий, которые отрабатывают по очереди. Используется, чтобы не дублировать вызовы в каждой ветке диалога.

Теги (tag) - это самый надёжный способ запоминать состояние квеста. Они хранятся в БД плагина (SQLite по умолчанию или MySQL, если переключили в config.yml) и переживают рестарт сервера. На активном проекте обязательно переключайте storage на MySQL, чтобы не терять прогресс игроков при крашах SQLite.

Интеграция с Citizens и DecentHolograms

Чтобы привязать диалог к Citizens NPC, в package.yml добавляется блок npcs:. ID NPC берётся командой /npc select -> /npc info.

npcs:
  "12": innkeeper
  "13": blacksmith
  "14": village_elder

Теперь по правому клику на NPC с ID 12 откроется диалог innkeeper. Никакого npc.yml отдельно не нужно, всё лежит в пакете.

DecentHolograms ставит голограммы условно, например иконку "?" над NPC, который выдаёт квест:

events:
  show_marker:
    type: hologram
    instruction: hologram quest_marker
  hide_marker:
    type: hologram
    instruction: hologram quest_marker hide

Сама голограмма создаётся через /dh create quest_marker и привязывается командой /dh attach quest_marker npc_12 0 2.5 0. BetonQuest управляет только видимостью.

Журнал и UI игрока

Журнал - это книга, которая описывает игроку, что он сейчас делает и что уже выполнил. Записи в journal.yml:

journal:
  rats_started: "&7В подвале трактира кто-то возится. Трактирщик попросил разобраться с крысами."
  rats_finished: "&aКрысы уничтожены, награда получена."
  blacksmith_intro: "&7Кузнец ищет подмастерье."

Записи добавляются событием journal add <id> и удаляются journal del <id>. По дефолту игрок открывает журнал командой /journal. Можно повесить открытие на правый клик книги в инвентаре через config.yml:

journal:
  give_on_join: true
  custom_journal: true
  show_in_backpack: true

Для сводного UI с прогрессом квестов есть встроенное меню (/q menu) или внешние плагины вроде QuestsGUI. Большие проекты обычно пишут собственный GUI поверх PlaceholderAPI, потому что встроенное меню по фиче-листу базовое.

Шпаргалка по основным objectives

ТипЧто считаетПример instruction
mobkillубийство мобовmobkill ZOMBIE 10 notify
locationприход в радиусlocation 100;64;-50;world 5
blockbreak/place блокаblock COAL_ORE 32 events:done
craftкрафт предметаcraft DIAMOND_PICKAXE 1
interactклик по блоку/мобуinteract left ANY ENTITY
consumeсъесть/выпитьconsume cooked_beef 5
enchantзачароватьenchant diamond_sword sharpness:3
fishрыбалкаfish COD 20
killубийство игрокаkill name:Steve 1
breedразведение животныхbreed COW 3
commandввод командыcommand !/spawn
delayпройти Х минутdelay 30 ticks:false
experienceнабрать опытexperience 30 level
passwordввести в чатpassword secretWord

Полный список и параметры есть на docs.betonquest.org/objectives. Каждый objective можно дополнить флагами notify, persistent (не сбрасывать после reconnect), events: для срабатывания на готовности.

Миграция с 1.x на 2.x: что важно знать

Если у вас на проде ещё 1.x, прыгать на 2.x просто так не получится. Формат пакетов изменился, многие события переименованы, журнал переписан под новый storage. Команда BetonQuest сделала встроенный мигратор:

/q migrate

Команда конвертирует папки QuestPackages/<name>/main.yml старого формата в директории нового. Перед запуском сделайте бэкап plugins/BetonQuest/ и базы (SQLite файл или дамп MySQL). После миграции прогоните сервер на тестовом окружении - часть кастомных событий и интеграций придётся править руками.

Что переименовалось:

  • tag: -> явный тип tag с instruction
  • inline-conditions через запятую -> поле conditions: отдельно
  • старый формат point -> новый event point с instruction
  • compat с Heroes/MythicLib пересобран под новые API

Если миграция падает - откатывайтесь к бэкапу и читайте docs.betonquest.org/migration пошагово. Авторы пишут гайд по каждому breaking-change.

Производительность: что может съесть TPS

BetonQuest сам по себе лёгкий: события и условия отрабатывают на эвентах Bukkit, проверки идут в основном потоке. Узкие места появляются от неправильной конфигурации.

  • MySQL вместо SQLite на проде с 100+ онлайн обязателен. SQLite-файл блокируется при записи, и квестовые ивенты выстраиваются в очередь
  • objective location проверяет позицию каждого игрока каждую секунду. Если у вас 200 таких objectives на квест, при 100 онлайн это 20000 проверок/сек. Используйте location для финальных точек, для зон лучше region через WorldGuard и условие worldguard
  • objective delay работает на тиках только если поставить ticks:true. По умолчанию он использует системное время, что переживает рестарт сервера и не грузит scheduler
  • debug в config.yml в проде должен быть false. На true BetonQuest спамит в консоль каждое действие, и при активном квестовом сюжете лог растёт на 100 МБ/час
  • Conversations с большим деревом (100+ нод) парсятся при /q reload секунды. Разбивайте по файлам внутри conversations/, плагин подхватывает всё

Если плагин начинает лагать в spark profiler - смотрите на тикеры WorldGuard и сами objectives. Часто причина не в BetonQuest, а в callback-плагинах вроде MythicMobs или Citizens, которые BetonQuest зовёт.

Типичные ошибки админов

  • Все квесты в одном пакете. Через полгода в default/ копится 200 файлов и любая правка ломает соседний квест. Делайте по пакету на сюжетную линию
  • Tags вместо objective conditions. Если можно проверить objective напрямую (condition objective hunt_rats), не плодите промежуточные теги вроде started_hunt_rats
  • Хардкод координат в YAML. Когда переносите спавн - все объекты location ломаются. Выносите координаты в variables: пакета и используйте %spawn_x%
  • Нет journal-записей. Игрок прошёл через 5 NPC, забыл, к кому возвращаться, бросил квест. Каждое значимое действие должно дописывать строку в журнал
  • Конфликт ID между пакетами. ID диалога start есть у трёх пакетов - BetonQuest подхватит первый загруженный. Префиксуйте: city_innkeeper, dungeon_innkeeper
  • Условия без !-инверсий. Без !quest_done NPC будет бесконечно предлагать квест уже выполнившему его игроку
  • MySQL без бэкапа. Прогресс квестов - это данные игроков, теряются они так же больно, как инвентарь. Настройте дамп раз в час на отдельный диск

FAQ

Можно ли ставить BetonQuest на Folia? Официальной поддержки Folia нет. Часть функций работает, но conversations и таймеры ломаются на регионах. Команда плагина в issues пишет, что Folia в roadmap, но дата не зафиксирована. На Folia пока живите с Quests Plugin или ждите.

Чем BetonQuest отличается от Quests Plugin? Quests проще для входа: GUI-конфигуратор, простые задачи. BetonQuest сложнее, но даёт ветвящиеся диалоги, условия любой логики и реальный квестовый граф. Если нужны "убей 50 зомби - получи алмаз" - Quests хватит. Если нужна Skyrim-like цепочка из 30 NPC и условий - только BetonQuest.

Как сделать ежедневные квесты? Через event delay с ticks:false и условие objective. Игрок завершает квест -> событие добавляет тег с TTL через delay-objective -> через 24 часа BetonQuest сам снимает тег и квест становится доступен снова.

Что делать, если плагин падает при старте? В 90% случаев это сломанный YAML в одном из пакетов. Открывайте logs/latest.log, BetonQuest пишет полный путь до проблемной строки. Часто помогает прогон файла через yamllint.

Можно ли импортировать готовые квесты? Да, на github.com/BetonQuest/Quest-Tutorials лежит коллекция примеров под 2.x. Просто кладёте папку в QuestPackages/ и делаете /q reload. Перед использованием проверяйте версию совместимости - старые пакеты под 1.x не загрузятся без миграции.

Как разделить квесты по серверам в BungeeCord? В config.yml укажите mysql: с одной БД для всех серверов. BetonQuest хранит теги привязанными к UUID игрока, так что прогресс будет общим. Пакеты при этом разные на каждом сервере: на хабе один набор, в RPG-мире другой.

Если квесты у вас раскручиваются и сервер начинает собирать аудиторию, помните про защиту от DDoS-атак на старте крупных эвентов: один правильный quest-event с массовым телепортом уже несколько раз в нашей практике совпадал с попытками снять сервер. BetonQuest сам по себе на это не повлияет, но иметь фильтр на входе в такие моменты стоит держать в голове.


Protégez votre serveur contre les attaques DDoS

Protection gratuite avec configuration en 5 minutes. 1 To de bande passante inclus.

Essayer gratuitement


Articles connexes