CloudTombEvent — ивент «Гробница»

Раз в восемь часов (по умолчанию — интервал настраивается) внутри пирамиды появляется сундук. Сервер это чувствует: все бросают дела и бегут в одну точку карты, потому что приз достаётся первому добежавшему. Никакой сложной механики для игрока — увидел вспышку, услышал рёв визера и объявление в чат, добежал через строй бессмертных стражей, открыл. Всё остальное берёт на себя плагин: таймер, схематика пирамиды, приватный регион, спавн охраны и взвешенный лут — дальше разобрано по деталям, вплоть до точных цифр из кода.

Что это такое

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, отсюда и проценты:

ПредметВесШанс на бросокКоличество
Железный слиток3025.2%3–16
Бутылка опыта2521.0%4–16
Золотой слиток2016.8%2–8
Изумруд1512.6%1–5
Алмаз108.4%1–3
Золотое яблоко86.7%1–2
Алмазный меч54.2%1
Алмазный нагрудник43.4%1
Зачарованное золотое яблоко21.7%1

Таблица целиком меняется в конфиге — материал берётся по имени из Bukkit Material, вес и диапазон количества свои для каждой строки, строк может быть сколько угодно. Опечатался в названии материала — плагин не упадёт, просто пропустит строку и напишет предупреждение в лог при загрузке.

Приват региона: что запрещено

Внутри bounding box действует жёсткий приват на всех, кроме игроков с tomb.bypass (по умолчанию — OP). Под запретом: ломать блоки, ставить блоки, кликать по чему угодно — дверям, рычагам, кнопкам, любым блокам с интерфейсом, — а также черпать и выливать вёдра. Каждое нарушение гасится сообщением о привате в чат нарушителю.

  • Взрывы — от крипера, TNT, кроватей — региону не вредят: блоки внутри границ плагин исключает из списка на снос до применения взрыва. Сам урон и отбрасывание сущностей взрывом при этом не блокируются — защита касается только блоков.
  • Единственное исключение из запрета на взаимодействие — клик именно по блоку активного ивент-сундука, и только по нему: координаты сверяются впритык, любой другой блок региона, даже соседний, под запретом как обычно.
  • tomb.bypass снимает все ограничения разом — обычно этим правом обладает только техадмин, чтобы обслуживать пирамиду.

Как поставить: сценарии

Базовая установка одинакова для любого сценария: положить jar в plugins/, перезапустить сервер (создастся config.yml с заглушками), вписать реальные координаты под свою карту, выполнить /tomb reload — можно без перезапуска.

Пирамида уже стоит на карте

Ничего лишнего: вписать region.min/max и chest.x/y/z (быстрее всего — встать на нужный блок и выполнить /tomb setchest), поле schematic.file оставить пустым. Приват и спавн стражей заработают сразу по region, схематика не потребуется вовсе.

Пирамида через схематику WorldEdit

Удобно, когда пирамиду нужно поставить одинаковой на нескольких картах или пересобрать после порчи рельефа: построить эталон один раз, сохранить .schem, положить в schematics/, прописать файл и точку вставки — и /tomb paste ставит копию одной командой. Захотелось передвинуть пирамиду — поменяли paste-x/y/z и вставили заново.

Встроенный сундук или bAirDrop

Если на сервере уже стоит bAirDrop и хочется, чтобы «Гробница» выглядела как остальные аирдропы — включить use-bairdrop: true и прописать команду. Нет bAirDrop или не нужен — ничего включать не надо, работает встроенный сундук с лут-таблицей из этого же конфига.

Без DecentHolograms

Голограмма не обязательна. Без 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.adminOPДоступ ко всем подкомандам /tomb
tomb.bypassOPПолный обход привата региона: ломать, ставить, взаимодействовать без ограничений

Оба права по умолчанию только у операторов — рядовой игрок во всём периметре пирамиды может лишь вскрыть сам ивент-сундук, когда тот появился, и ничего больше.

Настройка: все параметры

Полный список того, что плагин читает из config.yml (кроме лицензионного блока — тот про защиту от сливов, не про ивент):

ПараметрДефолтЧто делает
worldworldМир, где стоит пирамида
pyramid.center-x/y/z0 64 0Информационная точка центра, нигде не читается кодом
region.min/max-x/y/z-10 60 -10 / 10 80 10Bounding box: приват и зона спавна стражей
chest.x/y/z0 65 0Координата сундука; проще всего — /tomb setchest
chest-respawn-hours8Интервал нового сундука, часы реального времени
open-broadcastтекст с & и {player}Сообщение всему серверу при вскрытии
use-bairdrop / bairdrop-commandfalse / «bairdrop spawn {x} {y} {z}»Хук на bAirDrop вместо встроенного сундука
loot9 записейЛут-таблица: material/weight/min/max
loot-slots9Сколько слотов из 27 заполнять
husks.enabledtrueВключить периодический спавн стражей
husks.spawn-interval-ticks100Как часто пытаться подсадить стража (5 сек)
husks.max-husks10Потолок живых стражей одновременно
husks.custom-name&4Страж ГробницыИмя над головой стража
husks.bonus-hp / speed-multiplier40.0 / 1.2Добавка к HP (итого 60) и множитель скорости
schematic.fileпустоИмя .schem в schematics/; пусто — не используется
schematic.paste-x/y/z / paste-air0 64 0 / falseТочка вставки и вставлять ли воздух схематики
effects.hologramtrueПоказывать голограмму (нужен DecentHolograms)
effects.hologram-lines / hologram-idleпо 2 строкиТекст голограммы: сундук активен / идёт отсчёт (%time%)
effects.particles / particletrue / FLAMEКольцо частиц вокруг сундука и его тип
effects.beamtrueВертикальный луч END_ROD над сундуком
effects.spawn-sound / open-soundWITHER_SPAWN / BEACON_DEACTIVATEЗвуки появления и вскрытия сундука

Любое изменение подхватывается командой /tomb reload без перезапуска сервера — кроме нюанса с положением голограммы, разобранного выше.

«Гробница» — не декорация на карте, а работающий цикл: точный таймер, честный взвешенный лут, приватный регион и бессмертная — но не вечная — охрана. Ядро собрано и обкатано на уровне мелких деталей вроде поворота партикл-кольца; техадмину остаётся вписать координаты своей пирамиды и запустить отсчёт.