Что такое модульные подземелья?
Модульные подземелья появились в BetterStructures 2.0.0. Вместо размещения одного фиксированного схематика система собирает подземелье из небольших модулей, построенных вручную. Из них можно создавать многоэтажные подземелья с разной планировкой при каждом запуске генерации.
Как генерируются модульные подземелья
-
Модули Размер настраивается: часто используют 16×16×16 блоков, а некоторые пакеты — 32×16×32 или другие размеры. Общие точки соединения и граничные теги помогают состыковать модули без зазоров и наложений. Размеры задаются через
moduleSizeXZиmoduleSizeYв генераторе. Модуль может содержать коридор, комнату, лестницу или место для особого сражения. -
Процесс генерации При генерации в новом чанке BetterStructures применяет Wave Function Collapse (WFC): случайно выбирает совместимые по граничным тегам модули и собирает их вместе. Время зависит от радиуса, вертикального диапазона, пула модулей, ограничений и производительности сервера. Планировка рассчитывается асинхронно; вставка из очереди использует общий настроенный бюджет времени серверного тика. Большие или несовместимые планировки всё равно могут требовать много ресурсов либо не собраться.
-
Размер подземелья Увеличение радиуса позволяет строить подземелья протяжённостью в сотни блоков. Большинство подземелий имеют несколько этажей, соединённых лестницами или шахтами. Для вертикальных соединений используются
upиdownвborders: теги противоположных граней должны совпадать.
Пакеты и их сочетание
В каталоге есть Dungeoneering Modules Free и Dungeoneering Modules Premium. В поставляемом генераторе dungeoneering указаны стартовые схематики из обоих пакетов. Также в каталоге есть Tommyknockers Modules Free и Tommyknockers Modules Premium — модульная шахта, которую охраняют боссы EliteMobs; для Premium нужен пакет Free. Установите модули и зависимости, перечисленные в пакете, включая необходимый контент FreeMinecraftModels. Совместимые дополнительные модули расширяют выбор планировок; установка одного схематика не устанавливает связанные модели или контент мобов.
Маркеры сущностей и контейнеров
Генератор читает текст с лицевой стороны табличек и отбрасывает пустые строки. Напишите маркер строчными буквами в первой строке, а аргументы — сразу под ним. Регистр учитывается, кроме [elitemobs]. При модульной вставке удаляются все блоки табличек, включая декоративные и содержащие неподдерживаемые маркеры.
| Тег таблички | Дополнительные строки | Поведение |
|---|---|---|
[spawn] | Тип сущности Bukkit во второй строке | Создаёт постоянную ванильную сущность по центру блока таблички. В отдельном модульном мире также записывает позицию как маркер появления для интеграций. |
[chest] | Нет | Ставит сундук и заполняет его по treasureFile генератора модулей. |
[trapped_chest] | Нет | Ставит сундук-ловушку и заполняет его по treasureFile генератора модулей. |
[pool: poolname] | Нет | Выбирает босса из пула спавна EliteMobs и создаёт его по центру блока таблички. В существующем ландшафте это одноразовый региональный босс EliteMobs. О том, как в отдельном модульном мире обрабатываются обычные и инстансные боссы, см. раздел о пулах спавна. |
[elitemobs] | Имя файла босса EliteMobs в следующих строках, объединённых без разделителей | Только в модулях, вставляемых в существующий ландшафт (isWorldGeneration: false): создаёт одноразового регионального босса EliteMobs по центру блока таблички. Отдельные модульные миры его игнорируют. |
[barrel] | Нет | Записывает позицию бочки в отдельном мире. Интеграция должна создать её через spawnBarrels(). Сам маркер не ставит и не заполняет бочку. |
[exit] | Имена верхнего и нижнего компонентов в строках 2 и 3, без .schem | Записывает выходы в отдельном мире. Компоненты из components/ должна разместить интеграция. Если отсутствует хотя бы одна строка аргумента, оба имени заменяются на genericelevator_up и genericelevator_down. |
Маркеры [barrel] и [exit] обрабатываются только при isWorldGeneration: true. Для вставки в существующий ландшафт используйте isWorldGeneration: false; в этом режиме работают [spawn], [chest], [trapped_chest], [pool: poolname] и [elitemobs]. Таблички боссов в существующем ландшафте требуют включённого EliteMobs; без него BetterStructures записывает в лог одно предупреждение на подземелье и не создаёт боссов. Модули не создают защиту арены WorldGuard. Для обычных бочек с добычей поставьте в модуле настоящие блоки бочек и настройте их заполнение, как описано ниже.
Пулы спавна
Таблички [pool: poolname] обращаются к настройкам в spawn_pools/. Каждый YAML-файл содержит следующие поля:
| Поле | По умолчанию | Описание |
|---|---|---|
isEnabled | — | Не читается. У пулов спавна нет переключателя включения. |
poolStrings | [] | Список имён файлов боссов EliteMobs для выбора. |
minLevel | -1 | Сохраняется, но не читается. |
maxLevel | -1 | Уровень, который получают инстансные боссы из этого пула. Явно задайте допустимый уровень. |
Обработчику нужен EliteMobs. Он случайно выбирает имя файла босса из poolStrings. К имени пула перед .yml добавляется spawnPoolSuffix генератора: например, _hard выбирает poolname_hard.yml. Генератор без spawnPoolSuffix ищет poolname.yml. Не оставляйте пробелы в конце имени пула. Если файла пула нет, список poolStrings пуст или EliteMobs не знает имени файла босса, в лог записывается предупреждение и для этой таблички ничего не создаётся.
В отдельном модульном мире обычные, неинстансные боссы появляются во время вставки. Инстансные ждут вызова spawnInstancedEntities() со стороны интеграции. Каждый из них появляется с уровнем maxLevel пула и получает ID сложности инстанса EliteMobs в зависимости от расстояния до начальной точки подземелья. Расстояние — это большее из смещений по X и Z, которое сравнивается с шириной подземелья (2 × radius − 1) × moduleSizeXZ: меньше шестой части этой ширины даёт 2, меньше трети — 1, всё, что дальше, — 0. useGradientLevels на это не влияет.
Интеграции моделей и мобов
Модульная и обычная вставка используют разные обработчики табличек. Модульная вставка обрабатывает таблички [elitemobs] только в существующем ландшафте, как указано выше. Таблички структур [mythicmobs] и [custom], описанные в разделе Создание структур. Используйте поддерживаемые маркеры выше и соблюдайте требования пакета к зависимостям.
Сам по себе схематик не восстанавливает произвольные сущности моделей, которыми управляют другие плагины. Установите необходимые модели и сопутствующие плагины. Не рассчитывайте, что отсутствующий босс автоматически станет декоративной моделью.
Размеры модулей
Размер модулей настраивается и не является фиксированным.
Генератор использует следующие параметры:
moduleSizeXZ: ширина и глубина в блоках; явно задайте по размеру схематика.moduleSizeY: высота в блоках; явно задайте по размеру схематика.
Частый размер: 16×16×16 блоков, его тоже нужно указать явно. Другой распространённый вариант: 32×16×32 блока в некоторых пакетах.
Для авторов модулей:
- Проверьте
moduleSizeXZиmoduleSizeYгенератора. - Постройте все модули для него строго одинакового размера.
- Проверьте фактические размеры схематиков и точки соединения: генератор не проверяет геометрию за вас.
Пример собственных размеров:
Укажите в конфигурации генератора:
moduleSizeXZ: 32 # Width and depth
moduleSizeY: 16 # Height
Все модули одного генератора должны иметь одинаковые размеры. Не смешивайте 16×16×16 и 32×16×32 в одной системе подземелий.
Поля конфигурации генератора модулей
Помимо moduleSizeXZ и moduleSizeY, генератор поддерживает следующие настройки:
| Поле | По умолчанию | Описание |
|---|---|---|
isEnabled | true | Разрешает естественный выбор. Ручная команда не проверяет этот переключатель. |
radius | Указать явно | Радиус в ячейках модульной сетки. Горизонтальный размер ячейки — moduleSizeXZ; внешний ряд зарезервирован под границу. |
edges | false | Сохраняется, но текущий генератор не читает это поле. Края определяются тегами world_border. |
startModule | — | Список стартовых файлов .schem. Один выбирается случайно и ставится с поворотом 0 в ячейку (0, 0, 0). |
minChunkY | 0 | Минимальный вертикальный индекс модульной сетки включительно, а не координата блока Y в мире. |
maxChunkY | 0 | Максимальный вертикальный индекс включительно. Диапазон должен включать слой 0. |
moduleSizeXZ | Указать явно | Ширина и глубина модуля в блоках. |
moduleSizeY | Указать явно | Высота модуля в блоках. |
debug | false | Рисует диагностические блоки и текст в целевом мире. Используйте только в области, которую можно удалить. |
useGradientLevels | false | Сохраняется, но текущий расчёт уровней пула его не читает. |
spawnPoolSuffix | — | Суффикс имён пулов. Если он не нужен, не указывайте ключ или задайте "". |
isWorldGeneration | false | true создаёт отдельный пустотный мир; false вставляет в существующий. |
treasureFile | — | Файл добычи сундуков подземелья. |
generateLootInBarrels | true | Нужно ли заполнять бочки в модулях. |
barrelTreasureFilename | treasure_barrel_food.yml | Файл добычи бочек подземелья. |
validWorlds | Пусто, все миры | Имена миров, допускающих естественную генерацию. |
validWorldEnvironments | Пусто, все окружения | Допустимые окружения: NORMAL, NETHER, THE_END, CUSTOM. Поставляемый генератор dungeoneering явно задаёт [NORMAL, CUSTOM], поэтому изначально подземелья появляются только в мирах типа обычного мира. Поведение при пропуске ключа описано ниже. |
centerModuleAltitude | 0 | Начальная Y-координата естественной генерации в существующем ландшафте. Слой 0 смещён вверх на половину moduleSizeY. Ручное размещение в существующем мире начинается с позиции игрока, а в отдельном мире — с (0, 0, 0). |
Отсутствующие ключи используют текущее значение поля в определении генератора. Готовые генераторы инициализируют значения под свой контент. В написанном вручную генераторе radius, moduleSizeXZ и moduleSizeY начинаются с 0; эти нули могут быть записаны в файл. Не считайте, что пропущенный размер станет равен 16. Отсутствие validWorlds или validWorldEnvironments не накладывает ограничений, в том числе не ограничивает генератор NORMAL/CUSTOM. Возьмите за основу полную рабочую конфигурацию и явно задайте радиус, размеры, стартовые модули и ограничения миров.
Поля отдельных модулей
Каждый модуль поддерживает следующие поля:
| Поле | По умолчанию | Описание |
|---|---|---|
isEnabled | true | Включён ли модуль. |
weight | 100 | Вес выбора при генерации. Отрицательное или неконечное значение (NaN, бесконечность) записывает предупреждение в лог и становится 0, что исключает модуль из выбора. |
repetitionPenalty | 0 | Прибавляется к весу за каждый уже выбранный соседний модуль с тем же именем схематика. Положительные значения поощряют повторы, отрицательные уменьшают их. Итоговый вес должен оставаться положительным. |
noRepeat | false | Исключает кандидата рядом с выбранным модулем той же идентичности конфигурации, включая клоны. Не ограничивает появление одним разом на подземелье. |
enforceVerticalRotation | false | Требует одинаковых поворотов вокруг Y у модулей сверху/снизу, если хотя бы один включает эту настройку. |
enforceHorizontalRotation | false | Требует одинаковых поворотов вокруг Y у горизонтальных соседей, если хотя бы один включает настройку. |
minY | -4 | Минимальный слой модульной сетки для выбора кандидата, включительно. |
maxY | 20 | Максимальный слой модульной сетки для выбора кандидата, включительно. |
biome | default | Сохраняется, но не ограничивает выбор модулей. |
minecraftBiome | null | Сохраняется, но не ограничивает выбор модулей. |
treasureFile | — | Загружается в конфигурацию, но сундуки по маркерам сейчас используют treasureFile генератора. |
generateLootInBarrels | true | Нужно ли заполнять бочки этого модуля. |
barrelTreasureFilename | treasure_barrel_food.yml | Файл добычи бочек этого модуля. |
borders | — | Граничные теги, определяющие совместимость соединений. |
cloneConfig | — | Читает клонируемые настройки из другого файла конфигурации модуля. |
compoundModule | — | Сохраняется, но текущий генератор не использует его для сборки составных модулей. |
isAutomaticallyPlaced | true | Разрешает обычный выбор кандидата. Настроенный стартовый модуль обходит этот фильтр. |
Задайте все шесть записей borders: north, south, east, west, up и down, каждую со списком тегов. Обычные теги совпадают строго, с учётом регистра. Например, corridor подходит к corridor; no-mirror_corridor подходит к corridor, но не к другому no-mirror_corridor. Для каждого модуля создаются четыре поворота вокруг Y: 0, 90, 180 и 270 градусов.
nothing допускает пустого соседа. world_border отмечает модули для внешнего кольца горизонтальной области размещения; каждая грань наружу должна содержать только теги world_border. Для закрытых верхних и нижних границ используйте nothing. Радиус 5 допускает до 9 × 9 горизонтальных ячеек модулей с пустой границей вокруг. Эти правила фильтруют обычных кандидатов; начальный модуль ставится напрямую, поэтому его конфигурация и геометрия должны подходить для начала координат.
В cloneConfig укажите имя .yml другого модуля. Клонируемые настройки будут читаться из него. Если цель найдена, BetterStructures удалит из локального файла лишние ключи: treasureFile, barrelTreasureFilename, generateLootInBarrels, borders, minY, maxY, weight, repetitionPenalty, два переключателя вращения, noRepeat, шесть ключей *IsPassable и isAutomaticallyPlaced. В файле останутся isEnabled, biome, minecraftBiome, cloneConfig и compoundModule. Получение составного модуля во время работы также следует цели клонирования. Если файла нет, клонирование игнорируется с предупреждением, а модуль сохраняет свои значения.
В созданных конфигурациях также есть northIsPassable, southIsPassable, eastIsPassable, westIsPassable, upIsPassable и downIsPassable. По умолчанию они равны true, но генератор их не читает. Изменения не действуют; используйте borders.
Не создавайте циклы cloneConfig. Цикл вроде a.yml -> b.yml -> a.yml останавливает загрузку модулей с ошибкой "Cyclic module clone configuration", в которой указана вся цепочка.
Ручная генерация через /bs generateModules
/bs generateModules <ModuleGeneratorsConfigFile.yml> запускает генерацию по требованию, не дожидаясь естественного появления. Автодополнение перечисляет все загруженные файлы генераторов модулей.
Результат зависит от isWorldGeneration:
isWorldGeneration: true: создаётся новый мир. К имени файла генератора добавляется_0,_1,_2…; выбирается первый вариант, папки которого ещё нет. Это пустотный мир с окружениемNORMAL, без удержания спавн-чанков в памяти и с отключённым автосохранением. Команда переводит игрока в наблюдатели, но не телепортирует в новый мир.isWorldGeneration: false: генерация идёт в текущем мире игрока.
Полоса босса показывает сборку планировки и исчезает после постановки вставки в очередь. Сообщение о сборке не означает, что блоки и сущности уже вставлены. Если не установлен ни один настроенный стартовый схематик, генерация прекращается. Отключённый стартовый модуль тоже может привести к отмене, поскольку его контейнер недоступен.
Команда требует игрока с betterstructures.generatemodules и отклоняется при перезагрузке контента. Ручная генерация обходит проверки естественного размещения: включение генератора, ограничения миров и защиту площади. Выбирайте место осознанно.
Где находятся файлы модулей
Модули размещаются в plugins/BetterStructures/modules. Поиск рекурсивный: пакет может хранить .schem в подпапках, а соответствующие .yml создаются рядом.
Имена схематиков должны быть уникальны во всём дереве modules. Дубликат или нечитаемый схематик прерывает загрузку модулей. Схематики читаются до проверки isEnabled, поэтому отключение модуля не позволяет обойти повреждённый файл. Папка пакета контента с isEnabled: false пропускается целиком, поэтому его модули не читаются и не загружаются.
Естественное размещение и защита
Естественная генерация проверяет всю настроенную площадь. Размещение пропускается при пересечении с заданным радиусом защиты вокруг координат мира (0, 0), именованным регионом WorldGuard либо сгенерированными чанками, которые недавно не наблюдались как новые. Непосредственно перед постановкой вставки в очередь WorldGuard проверяется снова. Если первоначально несгенерированный чанк за это время успел сгенерироваться, запуск отклоняется. Это проверка состояния чанков, а не поиск блоков игроков или других плагинов защиты. Новый чанк возле старой базы не делает всю площадь подходящей.
У естественно выбираемых генераторов оставляйте isWorldGeneration: false. Естественный выбор не исключает true; это значение всё равно создаёт отдельный мир вместо вставки в проверенный ландшафт.
Блоки, блочные сущности, добыча, сущности и маркеры делят бюджет времени вставки. WorldGenerationFinishEvent вызывается после успешной вставки в отдельный мир и её непосредственной постобработки. Это не означает, что интеграция разместила выходы или создала ожидающих инстансных боссов. Крупная постройка может потребовать нескольких тиков после расчёта планировки.
Приоритет настроек добычи модулей
Сундуки и сундуки-ловушки по маркерам используют treasureFile генератора. Для настоящих блоков бочек generateLootInBarrels должен быть включён и у генератора, и у модуля. Непустой barrelTreasureFilename модуля имеет приоритет над генератором; созданные файлы модулей по умолчанию используют treasure_barrel_food.yml. Перед применением снимка инвентаря сундуки и бочки вызывают отменяемый ChestFillEvent.
Для генерации добычи сундуков используйте маркеры. Текущая модульная вставка не сохраняет инвентари обычных сундуков, сундуков-ловушек и бочек из схематика. Барьеры пропускаются; маркеры бедрока превращаются в камень только там, где целевой блок не твёрдый. Воздух вырезает внутренние пространства в существующих мирах и пропускается в отдельных пустотных мирах.
Сущности, сохранённые в модуле, например стойки для брони, картины и рамки, вставляются вместе с ним. Картины и рамки поворачиваются вместе с модулем, чтобы оставаться прикреплёнными к своей стене.