Раз в пару часов сервер выключает будни. Где-то в мире открывается провал в земле, в чат летит анонс с координатами — и весь онлайн срывается копать прямо сейчас, а не когда-нибудь потом. Пятнадцать минут спустя шахты нет, будто её и не было, а у полусотни игроков в карманах новая валюта и азарт «ещё раз». Это не метафора, а готовый механизм: CloudDeadlyMine — ивент «Смертельная шахта», аналог культовой механики HolyWorld, под Paper 1.19.4, студия Cloud Delight.
CloudDeadlyMine — не разовый скрипт, а самостоятельный цикл. Плагин сам решает, когда открыть шахту, сам её строит, сам считает удары кирки и выдаёт награду, сам чинит выбитую руду по ходу ивента и сам убирает всё после закрытия — от настройки до настройки ни одной ручной команды не требуется. Игроку остаётся простое и приятное действие: бежать и копать, пока не закрылось. Для сервера это готовый повод регулярно собирать онлайн в одной точке, понятная механика «руда → деньги» без единого объяснения в чате и управляемый вброс валюты в экономику — обе таблицы наград админ держит в своих руках через конфиг.
Ивент живёт на встроенном таймере из двух чисел конфига: event.interval-minutes — пауза между шахтами (по умолчанию 120 минут) и event.duration-minutes — сколько шахта держится открытой (по умолчанию 15). Важный нюанс: пауза отсчитывается не от открытия предыдущей шахты, а от её закрытия — следующий цикл планируется внутри cleanup(), когда всё уже прибрано. То же самое действует и при старте сервера: onEnable не открывает шахту сразу, а сразу ставит таймер на полный интервал плюс время фазы анонса (по умолчанию до 15 минут сверху, по максимальному значению из before-minutes) — то есть первая шахта после рестарта появится заметно позже, чем через голый interval-minutes.
Точка на карте выбирается в момент старта фазы анонсов, не заранее. Если spawn.use-fixed: true — шахта каждый раз садится в одну и ту же точку (center-x/center-z). Если false (дефолт) — координаты берутся случайно в радиусе spawn.radius (по умолчанию 500 блоков) от той же базовой точки center-x/center-z (по умолчанию 0,0 — условный центр карты). Высоту руками никто не задаёт: плагин берёт самый высокий блок в выбранной колонке (getHighestBlockYAt) — шахта всегда стартует от поверхности рельефа и уходит вниз на structure.height блоков, упираясь нижней границей в дно мира, если конфиг просит копать глубже, чем позволяет мир.
Активной может быть только одна шахта разом — это не настройка, а архитектура: движок живёт в трёх состояниях (ожидание / идёт анонс / активна), и попытка старта — хоть автоматическая, хоть командой — просто ничего не даёт, если плагин уже не в состоянии ожидания.
Список announce.before-minutes (дефолт — 15, 10, 5, 1) задаёт не только моменты уведомлений, а всю длину фазы анонса целиком: плагин берёт максимум списка как точку отсчёта и от неё считает, через сколько тиков разослать каждое сообщение и когда наконец заспавнить шахту. Поставишь [30, 20, 10, 1] — вся фаза анонса растянется на 30 минут; оставишь одно число — получишь одно предупреждение. Текст анонса (announce.message) поддерживает плейсхолдеры %minutes% и %x% %y% %z%, у открытия и закрытия — свои шаблоны (spawn-message, close-message).
Ручной запуск командой работает принципиально иначе: /deadlymine start полностью пропускает фазу анонсов и спавнит шахту мгновенно, без единого сообщения в чат. Если для внепланового ивента важно заранее собрать игроков — анонс придётся написать самому, плагин его не пришлёт. Ручной старт снимает с таймера ожидающий автозапуск, но не ломает цикл насовсем: как только эта шахта закроется — сама или по /deadlymine stop — cleanup() как обычно поставит следующий автозапуск через полный интервал.
Шахта — не лабиринт с ходами, а один большой колодец. Правило генерации простое: блок становится «оболочкой» (стена, пол, потолок), если лежит на границе прямоугольного короба хотя бы по одной оси; всё, что внутри границ, — воздух. Отсюда форма, которую легко не заметить, просто гуляя внутри: пол (нижний слой) и потолок (верхний слой) — сплошные плиты во всю площадь сечения, а боковые стены — тонкие, в один блок, только по периметру каждого промежуточного уровня. Материал оболочки зависит от высоты: нижняя половина шахты — structure.wall-material-deep (дипслейт по умолчанию), верхняя половина, включая потолок, — structure.wall-material (камень), а нижний слой пола — отдельный материал, structure.floor-material (булыжник).
Руда встраивается в оболочку по единой плотности — ore-density (0.18 по умолчанию) — и эта доля считается именно от блоков оболочки, а не от всего объёма шахты (внутренность и так пустая). На дефолтных размерах 11×11×20 оболочка — это примерно 960 блоков (сплошные пол и потолок дают около 240, тонкие стены по периметру на 18 промежуточных уровнях — ещё порядка 720), и при 18% плотности это в среднем около 170 блоков руды на одну шахту за один спавн — раскиданных по полу, потолку и стенам, а не собранных в жилы. Материал каждого рудного блока выбирается случайно из списка ore-materials.
Вход — единственная дыра 3×3 в потолке, прямо над точкой спавна; при постройке плагин отдельно вырезает её в воздух и насовсем убирает оттуда руду — даже при регенерации она туда больше не возвращается. Это же и единственный выход. Ставить блоки и выливать вёдра внутри привата нельзя (см. ниже), а значит подстелить себе лестницу вниз тоже не получится — только прыжок на всю высоту шахты. Плагин никак не гасит урон от падения, это стоит учитывать при увеличении structure.height: чем глубже шахта, тем жёстче приземление на входе.
Каждые refresh-seconds секунд (минимум 5, по умолчанию 60) плагин проходит по списку изначальных позиций руды и там, где сейчас воздух — блок выбили, — снова ставит случайную руду из списка. Регенерация трогает только эти конкретные точки: ни стены, ни пол она не восстанавливает и не портит, а вход, откуда руда удалена насовсем при постройке, регенерацией никогда не зарастает.
Приват шахты не имеет отношения к WorldGuard — плагин его не использует ни как soft-, ни как hard-зависимость, в коде нет ни одного обращения к его API. Вся защита — это внутренний RegionManager, который хранит шесть чисел (границы куба по X/Y/Z) и имя мира, плюс одна проверка «входит ли точка в этот куб». Её дёргают на разлом блока, установку блока, вычерпывание ведром и на списки блоков в EntityExplodeEvent/BlockExplodeEvent. Защищённая зона — это структура плюс отступ region.padding (по умолчанию 3 блока) со всех шести сторон, включая верх и низ, так что подкоп сверху или снизу тоже перехватывается.
Внутри этой зоны запрещено всё, кроме одного действия — ломать руду. Блок из списка ore-materials, лежащий внутри структуры, — единственное исключение: вместо отмены события плагин гасит ванильный дроп и опыт с него и вместо предмета выдаёт валюту. Всё остальное — стены, пол, потолок, блоки в зоне отступа — ломать нельзя вообще. Ставить блоки и выливать вёдра внутри тоже запрещено. Взрывы (крипер, TNT — любой источник, порождающий EntityExplodeEvent или BlockExplodeEvent) не портят структуру: плагин просто вычищает из списка «что сейчас снесётся» все блоки внутри зоны, а сам факт взрыва и урон по игрокам никак не трогает. Право deadlymine.bypass отключает все эти проверки разом.
Награда прилетает за каждый отдельно выбитый блок руды — не за жилу и не по кулдауну, а строго по факту разлома. Обе таблицы наград в конфиге — это не проценты, а веса: плагин суммирует все веса секции и тянет случайное число в этом диапазоне, так что реальный шанс каждой суммы — это её вес, делённый на сумму весов. На дефолтных значениях сумма весов ровно 100, поэтому цифры ниже читаются как проценты — но стоит добавить новую строку или поменять один вес, и пропорции пересчитаются сами.
Основная часть добычи — обычная валюта (символ по умолчанию $):
С шансом currency.donate-chance (0.02 = 2%) удар вместо обычной валюты приносит донат-валюту (символ по умолчанию ★) — своя, отдельная таблица весов, и выпадает она вместо обычной, не вместе с ней:
Подача отличается по весу события: обычная награда — тихий плюс в actionbar плюс звук ENTITY_EXPERIENCE_ORB_PICKUP по умолчанию; донатная — заголовок на весь экран (шаблон effects.donate-title, вспышка около двух секунд — без задержки на появление, полторы секунды показа, полсекунды на затухание) и отдельный звук, ENTITY_PLAYER_LEVELUP по умолчанию. На каждый удар по руде — ещё и партиклы (VILLAGER_HAPPY, восемь штук с небольшим разлётом), если effects.particles включён, и общий bossbar с обратным отсчётом до закрытия шахты — один на всех, кто сейчас онлайн.
Таблицы лидеров или личной статистики («кто сколько накопал») в плагине нет — ни базы данных, ни хранения количества ударов или заработанного за конкретную шахту он не ведёт. У моста к валютам даже есть метод чтения баланса игрока, но в текущем цикле ивента он нигде не вызывается — начисление работает в одну сторону, только на выдачу, без обратного чтения и без записи истории. Если нужен топ добытчиков — это отдельная задача поверх текущего кода, а не включаемая опция конфига.
Все четыре внешних плагина в plugin.yml объявлены soft-зависимостями: отсутствие любого из них просто отключает свою часть функциональности и пишет предупреждение в лог, а не роняет плагин целиком.
/deadlymine reload без полного рестарта — голограмма всё равно не появится, помогает только перезапуск сервера.schematic.file/schematic.paste-air в конфиге ни на что не влияют. Заготовка под готовые схематики в коде есть и работает как отдельный кусок, но в рабочий цикл ивента она не подключена.event.auto-enabled: true, плагин сам анонсирует и открывает шахту каждые 120 минут, 15 минут держит открытой и сам всё убирает. Админ нужен только на случай правки конфига./deadlymine start (или сразу с координатами: /deadlymine start 250 -800) поднимает шахту немедленно, минуя очередь и анонсы. Если для события важно заранее собрать игроков — анонс придётся написать самому, автосообщения тут не будет.spawn.use-fixed: true плюс заданные center-x/center-z держат шахту всегда в одном месте — удобно, если вокруг заранее обустроена площадка или декорации, не привязанные к плагину./deadlymine reload. Сервер перезапускать не нужно, кроме одного случая — включения DecentHolograms задним числом (см. выше)./deadlymine stop — мгновенный cleanup: структура восстанавливается из снапшота блок в блок, регион снимается, а следующий автозапуск планируется как обычно, будто шахта закрылась по таймеру.Все подкоманды — под одной точкой входа с двумя короткими алиасами, /dm и /шахта (работает и кириллицей):
| Команда | Действие |
|---|---|
/deadlymine start | Мгновенный запуск, координаты выбирает сам плагин. |
/deadlymine start 250 -800 | Мгновенный запуск с заданным центром X/Z — высоту (Y) плагин всё равно определит сам по рельефу. |
/deadlymine stop | Досрочно закрыть текущую шахту, вернуть ландшафт на место. |
/deadlymine reload | Перечитать config.yml и таблицы наград без перезапуска сервера. |
/deadlymine info | Статус: активна и сколько осталось (мм:сс), идёт анонс, или ожидание следующего цикла. |
/dm, /шахта | Короткие алиасы главной команды — принимают те же подкоманды. |
Без аргументов или с неизвестным словом команда просто печатает список подсказок; без права deadlymine.admin любая попытка обрывается сообщением об отказе.
deadlymine.admin — доступ ко всем подкомандам управления (по умолчанию — операторам).deadlymine.bypass — игнорировать приват шахты целиком: ломать структуру, ставить блоки, пользоваться вёдрами внутри зоны, даже пока ивент активен (по умолчанию — тоже операторам).Конфиг — один файл, разбитый на смысловые блоки; почти любой из них применяется без перезапуска сервера командой /deadlymine reload (кроме отмеченного выше случая с DecentHolograms):
| Блок | Ключи | За что отвечает |
|---|---|---|
| license | enabled, key, url, grace-hours | Защита от несанкционированных копий: онлайн-проверка ключа при старте плагина, при недоступности сервера проверки — работа по локальному кэшу в пределах grace-hours, иначе плагин отключает сам себя. Для своего сервера — enabled: false. |
| event | auto-enabled, interval-minutes, duration-minutes | Автозапуск целиком, пауза между циклами (отсчитывается от закрытия), длительность активной фазы. |
| announce | before-minutes, message, spawn-message, close-message | Моменты и тексты предупреждений, открытия и закрытия; список before-minutes задаёт всю длину фазы анонса. |
| spawn | world, use-fixed, center-x, center-z, radius | Мир и способ выбора точки: фиксированная либо случайная в радиусе от базового центра. Высота всегда определяется автоматически, по рельефу. |
| structure | width, depth, height, wall-material, wall-material-deep, floor-material | Размеры короба и материалы оболочки: верхняя половина, нижняя половина, отдельно пол. |
| ore-materials / ore-density | список блоков, ore-density | Какие блоки считаются рудой и какая доля оболочки ими засевается при постройке. |
| refresh-seconds | — | Период регенерации выбитой руды на исходных позициях. |
| region | padding | Отступ приватной зоны вокруг структуры по всем шести сторонам. |
| schematic | file, paste-air | Заготовка под вставку .schem через WorldEdit; на сегодня в цикл ивента не подключена, генерация всегда процедурная. |
| currency | vault-symbol, points-symbol, donate-chance, donate-amounts, normal-amounts | Символы валют, шанс доната и обе весовые таблицы наград. |
| effects | bossbar, bossbar-title, hologram, hologram-lines, particles, sound-normal, sound-donate, donate-title | Вся подача: таймер-бар, текст голограммы, партиклы и звуки отдельно на обычный и на донатный дроп. |
Шахта, которая сама открывается, сама себя бережёт без единого чужого плагина защиты и сама убирает за собой, — и всё, что остаётся серверу, это игроки с кирками и таймер, который снова пошёл на исход.