Раз в восемь часов (по умолчанию — интервал настраивается) внутри пирамиды появляется сундук. Сервер это чувствует: все бросают дела и бегут в одну точку карты, потому что приз достаётся первому добежавшему. Никакой сложной механики для игрока — увидел вспышку, услышал рёв визера и объявление в чат, добежал через строй бессмертных стражей, открыл. Всё остальное берёт на себя плагин: таймер, схематика пирамиды, приватный регион, спавн охраны и взвешенный лут — дальше разобрано по деталям, вплоть до точных цифр из кода.
CloudTombEvent — ивент «Гробница» для Paper 1.19.4 (Java 17, api-version 1.19) от студии Cloud Delight. Идея честная, без лишних слоёв: посреди мира стоит пирамида, внутри — приватный регион с бессмертными кадаврами-стражами, а в глубине по таймеру появляется сундук с наградой. Атмосфера держится на деталях: гудящий луч над сундуком, кольцо огненных частиц, рёв визера при появлении добычи, вспышка и общий чат, который на весь сервер узнаёт имя победителя.
Плагин полностью самодостаточен: для базовой работы не нужен ни один сторонний плагин — регион, таймер, спавн стражей, лут и эффекты работают из коробки. Три интеграции (WorldEdit, bAirDrop, DecentHolograms) подключены мягкими зависимостями и только расширяют возможности, не ломая ивент при отсутствии. Управление — одна команда /tomb с пятью подкомандами (работает и алиас /гробница), права по умолчанию только у OP.
Саму пирамиду плагин не строит — это либо готовая постройка на карте, либо схематика WorldEdit, которую вставляет команда /tomb paste. Процесс: построить пирамиду один раз вручную, выделить //wand, сохранить //schem save имя, скопировать получившийся .schem-файл в plugins/CloudTombEvent/schematics/ и прописать имя файла в schematic.file. Команда читает файл через WorldEdit API (формат определяется автоматически по расширению), открывает EditSession и вставляет буфер в точку schematic.paste-x/y/z — тот же Origin-угол, что был при выделении оригинала. Параметр paste-air: false стоит по умолчанию — воздух схематики при вставке игнорируется, чтобы не выгрызать в рельефе прямоугольную яму; включив true, получите полную перезапись объёма, включая пустоты. Нет WorldEdit на сервере — команда просто ответит отказом, а вручную построенная пирамида работает как ни в чём не бывало: схематика полностью опциональна.
Поле pyramid.center-x/y/z в конфиге — чисто информационное: в коде оно нигде не читается ни одной командой или механикой, просто памятка техадмину, где у пирамиды центр. Рабочая величина — region: прямоугольный bounding box по min-x/y/z и max-x/y/z, который одновременно и зона привата, и зона спавна стражей. Бокс всегда прямоугольный параллелепипед — если пирамида ступенчатая, защищённая зона всё равно останется прямоугольной и может захватывать пустоту за пределами видимых стен.
Внутри региона дежурят кадавры (Husk) с кастомным именем «Страж Гробницы» (текст и цвет настраиваются, имя всегда видно над головой). У стража три отличия от рядового хаска. Первое — флаг invulnerable, выставленный напрямую через API: урона нет вообще, ни от оружия, ни от падения, ни от солнца. Второе — здоровье: к стандартным 20 HP хаска (10 сердец) конфиг добавляет husks.bonus-hp (по умолчанию 40) — итого 60 HP, 30 сердец. Третье — скорость: множитель speed-multiplier (по умолчанию 1.2) даёт +20% к базовой скорости передвижения.
Спавн — по таймеру: раз в husks.spawn-interval-ticks тиков (по умолчанию 100 = 5 секунд) плагин пытается подсадить ещё одного стража в случайную точку bounding box — но только если в радиусе 64 блоков от неё реально стоит игрок, иначе тик пропускается, чтобы не плодить мобов в пустых чанках. Потолок одновременных стражей (max-husks, по умолчанию 10) считается не внутренним счётчиком, а прямым подсчётом реальных сущностей в мире с меткой плагина — PersistentDataContainer, ключ tomb_husk: счётчик соврал бы при выгрузке чанков, метка — нет.
Поправка к расхожему представлению: стражи не бессмертны в смысле «вечны» — урон их не берёт, но despawn стандартной ванильной логикой при долгом отсутствии игроков рядом всё же случается (setRemoveWhenFarAway(true)). В коде это отмечено как осознанное исправление: раньше флаг стоял в false, и стражи копились навсегда, превращаясь в утечку сущностей и лишнюю нагрузку. По той же причине при остановке плагина (рестарт, /tomb reload) все помеченные стражи принудительно удаляются — мусор между перезапусками не остаётся.
Интервал — chest-respawn-hours, по умолчанию 8. Это часы реального времени, а не игровые сутки: плагин переводит их в тики по формуле «час = 72000 тиков» (20 тиков в секунду × 3600 секунд) и ставит отложенную задачу планировщика. Отсчёт стартует при запуске сервера и заново — сразу после того, как предыдущий сундук открыли.
Появление — либо встроенный механизм (по умолчанию), либо хук на bAirDrop. Встроенный: на координатах chest.x/y/z ставится блок CHEST и заполняется лутом по таблице. Хук: если use-bairdrop: true и bAirDrop реально установлен, вместо этого выполняется консольная команда из bairdrop-command с подстановкой {x}/{y}/{z} — дальше судьбу дропа решает bAirDrop, плагин Гробницы дальше не вмешивается. Команда в конфиге пустая — плагин заметит, напишет предупреждение в лог и всё равно поставит обычный сундук, чтобы ивент не сорвался.
Открытие ловится слушателем по инвентарю: система сверяет, что открытый Chest стоит ровно на тех же координатах и в том же мире, что активный ивент-сундук, — соседний сундук ивент не триггерит. Сработало — сундук снимается с учёта, объявление уходит не только в мир пирамиды, а на весь сервер целиком, и в ту же секунду планируется следующий цикл.
Практическая деталь: /tomb reload — не просто «применить новые числа». Если сундук в этот момент не стоит (идёт отсчёт), reload сбрасывает текущий отсчёт и запускает полный chest-respawn-hours заново, а не продолжает с прерванного места. Если сундук уже активен и ждёт открытия — reload его не трогает вообще, таймер и позиция остаются как есть.
Момент появления — самый громкий: звук на выбор (effects.spawn-sound, по умолчанию ENTITY_WITHER_SPAWN, рёв визера) слышат все игроки в мире пирамиды, плюс партиклы FLASH и EXPLOSION_HUGE прямо над сундуком. Дальше, пока сундук ждёт: вращающееся кольцо частиц (effects.particle, по умолчанию FLAME) из 24 точек радиусом 1.2 блока вокруг основания, с поворотом каждые 4 тика, и — если включён effects.beam — сплошная вертикальная колонна END_ROD высотой 25 блоков, маяком видная издалека. Открыли — кольцо и луч гаснут, вместо них залп из 40 частиц TOTEM (тех самых, что при возрождении с тотемом бессмертия) и отдельный звук закрытия (effects.open-sound, по умолчанию гашение маяка).
Если стоит DecentHolograms — над сундуком, на 1.6 блока выше, висит голограмма с двумя состояниями: во время ожидания — отсчёт с плейсхолдером %time% (обновляется раз в секунду, формат «Хч Мм Сс»), в момент появления сундука — призыв вскрыть. Текст обеих строк настраивается. Нет DecentHolograms — ивент идёт так же, просто без парящей таблички, без ошибок в консоли.
Честно об уровне детализации: включение каждого эффекта, тип партикла и звука, текст голограммы — всё в конфиге. А число частиц в кольце, радиус, частота обновления, высота луча, количество тотем-частиц и смещение голограммы — константы в коде, конфигом не вынесены. И ещё нюанс: после /tomb setchest голограмма сама не переезжает на новое место — её позиция обновляется только при пересоздании (/tomb reload, пока сундук неактивен, либо перезапуск сервера), иначе табличка какое-то время висит над старой точкой, а сундук появляется уже на новой.
Таблица взвешенная: чем выше вес, тем чаще предмет выпадает. По умолчанию плагин заполняет 9 случайных слотов сундука из 27 (loot-slots) — остальные пустые, а позиции внутри сетки каждый раз перемешиваются, добыча не сидит кучкой в одном ряду. Каждый из 9 слотов — независимый бросок по всей таблице, поэтому один и тот же предмет может выпасть несколько раз за один сундук. Суммарный вес по умолчанию — 119, отсюда и проценты:
| Предмет | Вес | Шанс на бросок | Количество |
|---|---|---|---|
| Железный слиток | 30 | 25.2% | 3–16 |
| Бутылка опыта | 25 | 21.0% | 4–16 |
| Золотой слиток | 20 | 16.8% | 2–8 |
| Изумруд | 15 | 12.6% | 1–5 |
| Алмаз | 10 | 8.4% | 1–3 |
| Золотое яблоко | 8 | 6.7% | 1–2 |
| Алмазный меч | 5 | 4.2% | 1 |
| Алмазный нагрудник | 4 | 3.4% | 1 |
| Зачарованное золотое яблоко | 2 | 1.7% | 1 |
Таблица целиком меняется в конфиге — материал берётся по имени из Bukkit Material, вес и диапазон количества свои для каждой строки, строк может быть сколько угодно. Опечатался в названии материала — плагин не упадёт, просто пропустит строку и напишет предупреждение в лог при загрузке.
Внутри bounding box действует жёсткий приват на всех, кроме игроков с tomb.bypass (по умолчанию — OP). Под запретом: ломать блоки, ставить блоки, кликать по чему угодно — дверям, рычагам, кнопкам, любым блокам с интерфейсом, — а также черпать и выливать вёдра. Каждое нарушение гасится сообщением о привате в чат нарушителю.
tomb.bypass снимает все ограничения разом — обычно этим правом обладает только техадмин, чтобы обслуживать пирамиду.Базовая установка одинакова для любого сценария: положить jar в plugins/, перезапустить сервер (создастся config.yml с заглушками), вписать реальные координаты под свою карту, выполнить /tomb reload — можно без перезапуска.
Ничего лишнего: вписать region.min/max и chest.x/y/z (быстрее всего — встать на нужный блок и выполнить /tomb setchest), поле schematic.file оставить пустым. Приват и спавн стражей заработают сразу по region, схематика не потребуется вовсе.
Удобно, когда пирамиду нужно поставить одинаковой на нескольких картах или пересобрать после порчи рельефа: построить эталон один раз, сохранить .schem, положить в schematics/, прописать файл и точку вставки — и /tomb paste ставит копию одной командой. Захотелось передвинуть пирамиду — поменяли paste-x/y/z и вставили заново.
Если на сервере уже стоит bAirDrop и хочется, чтобы «Гробница» выглядела как остальные аирдропы — включить use-bairdrop: true и прописать команду. Нет bAirDrop или не нужен — ничего включать не надо, работает встроенный сундук с лут-таблицей из этого же конфига.
Голограмма не обязательна. Без DecentHolograms ивент идёт без парящего таймера над сундуком: игроки узнают о появлении по звуку, партиклам и объявлению в чат, статус в любой момент проверяется командой /tomb info.
Чтобы не ждать реальные 8 часов — /tomb spawn ставит сундук немедленно, в обход таймера, сразу видно лут и эффекты. /tomb info покажет, активен ли сундук, сколько стражей живо из потолка, и сводку по региону.
Все подкоманды требуют tomb.admin (по умолчанию OP), работает и алиас /гробница вместо /tomb:
| Команда | Что делает |
|---|---|
/tomb reload | Перечитать config.yml. Сундук ждёт открытия — не трогает его; сундука нет — сбрасывает отсчёт и запускает интервал заново |
/tomb spawn | Форс-спавн сундука прямо сейчас, в обход таймера — для теста лута и эффектов |
/tomb paste | Вставить схематику пирамиды из schematics/ (нужен WorldEdit и заполненный schematic.file) |
/tomb setchest | Записать координату сундука по текущей позиции игрока; голограмма подтянется к месту только после /tomb reload |
/tomb info | Статус: активен ли сундук и где, время до следующего, живых стражей из потолка, сводка по региону |
| Право | Дефолт | Что даёт |
|---|---|---|
tomb.admin | OP | Доступ ко всем подкомандам /tomb |
tomb.bypass | OP | Полный обход привата региона: ломать, ставить, взаимодействовать без ограничений |
Оба права по умолчанию только у операторов — рядовой игрок во всём периметре пирамиды может лишь вскрыть сам ивент-сундук, когда тот появился, и ничего больше.
Полный список того, что плагин читает из config.yml (кроме лицензионного блока — тот про защиту от сливов, не про ивент):
| Параметр | Дефолт | Что делает |
|---|---|---|
world | world | Мир, где стоит пирамида |
pyramid.center-x/y/z | 0 64 0 | Информационная точка центра, нигде не читается кодом |
region.min/max-x/y/z | -10 60 -10 / 10 80 10 | Bounding box: приват и зона спавна стражей |
chest.x/y/z | 0 65 0 | Координата сундука; проще всего — /tomb setchest |
chest-respawn-hours | 8 | Интервал нового сундука, часы реального времени |
open-broadcast | текст с & и {player} | Сообщение всему серверу при вскрытии |
use-bairdrop / bairdrop-command | false / «bairdrop spawn {x} {y} {z}» | Хук на bAirDrop вместо встроенного сундука |
loot | 9 записей | Лут-таблица: material/weight/min/max |
loot-slots | 9 | Сколько слотов из 27 заполнять |
husks.enabled | true | Включить периодический спавн стражей |
husks.spawn-interval-ticks | 100 | Как часто пытаться подсадить стража (5 сек) |
husks.max-husks | 10 | Потолок живых стражей одновременно |
husks.custom-name | &4Страж Гробницы | Имя над головой стража |
husks.bonus-hp / speed-multiplier | 40.0 / 1.2 | Добавка к HP (итого 60) и множитель скорости |
schematic.file | пусто | Имя .schem в schematics/; пусто — не используется |
schematic.paste-x/y/z / paste-air | 0 64 0 / false | Точка вставки и вставлять ли воздух схематики |
effects.hologram | true | Показывать голограмму (нужен DecentHolograms) |
effects.hologram-lines / hologram-idle | по 2 строки | Текст голограммы: сундук активен / идёт отсчёт (%time%) |
effects.particles / particle | true / FLAME | Кольцо частиц вокруг сундука и его тип |
effects.beam | true | Вертикальный луч END_ROD над сундуком |
effects.spawn-sound / open-sound | WITHER_SPAWN / BEACON_DEACTIVATE | Звуки появления и вскрытия сундука |
Любое изменение подхватывается командой /tomb reload без перезапуска сервера — кроме нюанса с положением голограммы, разобранного выше.
«Гробница» — не декорация на карте, а работающий цикл: точный таймер, честный взвешенный лут, приватный регион и бессмертная — но не вечная — охрана. Ядро собрано и обкатано на уровне мелких деталей вроде поворота партикл-кольца; техадмину остаётся вписать координаты своей пирамиды и запустить отсчёт.