Уровни и карты EternalTD
«Уровень» в EternalTD — это YAML-конфигурация в plugins/EternalTD/levels/ в паре с папкой шаблона мира в plugins/EternalTD/worlds/. Когда игрок присоединяется, EternalTD клонирует шаблонный мир в контейнер миров сервера и запускает сессию в этой клонированной копии.
Поля конфигурации уровня
| Поле | Тип | По умолчанию | Примечания |
|---|---|---|---|
isEnabled | bool | true | Отключённые уровни пропускаются при загрузке |
levelName | string | null | Отображаемое имя, показываемое в сообщениях, таблицах и меню NPC |
levelDescription | список строк | [] | Строки, показываемые в меню NPC. Поддерживает плейсхолдеры $highscoreWave и $highscorePlayer |
worldName | string | null | Имя папки шаблона в plugins/EternalTD/worlds/ |
startLocation | список строк | null | Список сериализованных локаций, где спавнятся мобы |
endLocation | список строк | null | Список сериализованных локаций, к которым идут мобы («красные» плитки) |
levelLocations | список строк | null | Каждый проходимый квадрат сетки на уровне, генерируется автоматически при регистрации выбора этажа |
wavesConfigFile | string | обязательно | Имя файла связанной конфигурации волны (waves/<name>.yml) |
waveCount | int | -1 | Кэшированное количество волн, в настоящее время информационное |
highscoreWave | int | 0 | Лучшая волна, достигнутая на этом уровне |
highscorePlayerName | string | "no one" | Отображаемое имя игрока, установившего рекорд |
environment | enum | NORMAL | Окружение мира, используемое при загрузке клонированного мира |
Размер сетки, используемый повсюду, — 3 блока на логический квадрат (константа GRID_SIZE в коде).
Формат строки локации
Локации в EternalTD сериализуются как строки, разделённые запятыми, вида:
worldName,x,y,z,yaw,pitch
Обычно вы не пишете их вручную — /etd selectfloor плюс команды регистрации вычисляют и сохраняют их за вас.
Жизненный цикл мира
Когда игрок присоединяется к уровню:
- EternalTD ищет папку шаблона по
worldNameвplugins/EternalTD/worlds/. - Он выбирает следующий свободный числовой суффикс (
<worldName>_0,<worldName>_1, ...) и записывает клон в контейнер миров сервера, предварительно очищая любые устаревшие копии в старой или современной структуре. - Клонированный мир загружается как временный пустой мир через
TemporaryWorldManagerиз MagmaCore, поэтому миграция Paper 26.1+ изолируется. - Игрок телепортируется в новый мир; внутренний
InstanceProtectorприменяет правила защиты EternalTD.
Когда сессия заканчивается:
- Любые оставшиеся игроки в клонированном мире телепортируются обратно в точку появления из
config.ymlили кикаются, если точка появления не настроена. - Клонированный мир выгружается и удаляется с диска (
TemporaryWorldManager.permanentlyDeleteWorld).
Правила защиты инстанса
Пока уровень активен, в клонированном мире применяются следующие правила:
- Взрывы отключены
- Течение жидкостей отключено
- Элитры отключены
- Переключение полёта запрещено
- Дружественный огонь запрещён
- Стандартный спавн мобов запрещён
Рабочий процесс создания карт
Текущий процесс создания карт использует игровой инструментарий:
- Поместите папку шаблона мира в
plugins/EternalTD/worlds/<worldName>/. - Создайте или загрузите соответствующий YAML уровня в
plugins/EternalTD/levels/. - Выполните
/etd reloadи присоединитесь к миру уровня вручную (или откройте его в одиночной игре для настройки). - Используйте
/etd selectfloorи кликните правой/левой кнопкой по двум углам, чтобы отметить игровую область, или используйте/etd selectfloorcoordinates <x1> <y1> <z1> <x2> <y2> <z2>, чтобы задать их напрямую. - Выполните
/etd showselection <level>, чтобы убедиться, что выбор выглядит правильно. - Выполните
/etd register <level>, чтобы очистить выбор. Обратите внимание, что в текущей сборке ниregister, ниshowselectionфактически не сохраняют область этажа — помощник, который должен сохранятьlevelLocations(LevelsConfigFields#addLevelLocations), определён, но ни одна команда его не вызывает. На данный моментlevelLocationsприходится вручную записывать в YAML уровня, если они ещё не заполнены загруженным пакетом. - Встаньте на стартовую плитку спавна и выполните
/etd register <level> start. Повторите для каждой стартовой плитки (эта команда действительно сохраняется вstartLocation). - Встаньте на конечную плитку и выполните
/etd register <level> end. Повторите для каждой конечной плитки (эта команда действительно сохраняется вendLocation). - Перезагрузите снова и протестируйте уровень, присоединившись к нему через меню NPC или
/etd join <level>.
Команды выбора генерируют квадраты сетки по формуле:
size = abs(corner1 - corner2 + 1) / 3
Квадраты, верхний блок которых — воздух (или чей блок пола проходим), пропускаются, поэтому блоки пола должны быть твёрдыми, чтобы квадрат регистрировался как играбельный.
Проверка пути
EternalTD выполняет проверку поиска пути A* всякий раз, когда устанавливается башня. Если установка башни оставит любую стартовую плитку без проходимого пути к любой конечной плитке, установка отклоняется, и золото не тратится.
Воздушные враги используют отдельный путь, который полностью игнорирует башни и вместо этого следует воздушному смещению (4 блока над настроенным путём).
NPC и меню уровней
Конфигурации NPC в plugins/EternalTD/npcs/ связывают NPC-жителей с одним или несколькими уровнями. Клик правой кнопкой мыши по NPC открывает инвентарь из 9 слотов, в котором каждый уровень показан как панель из зелёного окрашенного стекла с названием и описанием уровня.
| Поле | Тип | По умолчанию | Примечания |
|---|---|---|---|
isEnabled | bool | true | Отключённые NPC пропускаются |
levelIDs | список строк | обязательно | Имена файлов уровней, предлагаемых этим NPC |
location | string | null | Локация спавна в стандартном формате worldName,x,y,z,yaw,pitch |
name | string | "Default Name" | Отображаемое имя NPC |
difficulty | string | "Difficulty: Not Set" | Метка сложности, показываемая над NPC |
disguise | string | null | Дескриптор LibsDisguises (например, custom:etd_tutorial_npc) |
customDisguiseData | string | null | Дополнительные данные команды LibsDisguises — обычно длинная строка скина игрока |
Житель появляется неуязвимым, с отключённым AI, постоянным и помеченным namespace-ключом NPC EternalTD. Если установлен LibsDisguises и заданы оба поля disguise и customDisguiseData, житель маскируется при спавне.
Плавающая стойка для брони с меткой difficulty спавнится в 2.3 блоках над NPC.
Поведение точки появления
DefaultConfig управляет тем, как игроки обрабатываются в мире-хабе:
setupDone— флаг, отслеживающий, было ли завершено руководство первоначальной настройки.spawnLocations— по умолчаниюetd_spawn,0,65,0,0,0. Используется только когда существует мирetd_spawn.manageSpawn— по умолчаниюtrue. Когда включено, присоединяющиеся игроки телепортируются в точку появления через 1 тик после входа.playerGuide— текст игрового руководства.
Когда manageSpawn равно true и мир точки появления загружен, каждый игрок, присоединяющийся к серверу, телепортируется в spawnLocations.