Files
minecraft-lab/minecraft_modpack_platform_PLAN.md
T
2026-10-04 00:30:09 +07:00

1710 lines
62 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Платформа для Minecraft-модпаков — план реализации
## 1. Цель
Создать local-first платформу для создания, версионирования, упаковки, развёртывания и сопровождения воспроизводимых Minecraft-модпаков для небольшой группы игроков.
Платформа должна быть оптимизирована под:
- пользовательские модпаки на NeoForge и Forge;
- запуск без обязательного Microsoft/Mojang-аккаунта и без онлайн-проверки сессии;
- Prism Launcher как первоначальный клиентский лаунчер.
- Docker Compose как серверный runtime.
- удалённый доступ к серверу по SSH.
- Git как источник истины для описания сборки и конфигурации.
- обычные читаемые файлы на диске вместо непрозрачных Docker volumes.
- простую установку, удаление и обновление модов.
- воспроизводимые сборки.
- простой rollback.
- минимум собственной логики там, где задача уже хорошо решена существующими инструментами экосистемы.
Сама платформа должна в первую очередь выступать как orchestration-слой вокруг:
- packwiz
- Modrinth `.mrpack`
- Prism Launcher
- `itzg/minecraft-server`
- Docker Compose
- Git
- SSH / rsync
Не разрабатывать собственный resolver зависимостей Minecraft-модов без реальной необходимости.
Авторизация аккаунтов не является задачей платформы. Целевой сервер использует online-mode=false и enforce-secure-profile=false; для Prism допускается offline-аккаунт/Launch Offline. NeoForge и Forge — целевые loader; проверка Fabric не заменяет их integration spike.
---
# 2. Основная архитектура
Система состоит из четырёх концептуальных слоёв.
```text
┌──────────────────────────────────────────┐
│ 1. ИСХОДНИК МОДПАКА │
│ │
│ packwiz │
│ mods / configs / datapacks / resources │
│ Minecraft + версии loader │
└────────────────────┬─────────────────────┘
│
build
│
┌──────────┴──────────┐
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ 2. CLIENT PACK │ │ 3. SERVER PACK │
│ │ │ │
│ Modrinth .mrpack │ │ Modrinth .mrpack│
│ Prism Launcher │ │ itzg installer │
└──────────────────┘ └─────────┬────────┘
│
▼
┌──────────────────┐
│ 4. SERVER STATE │
│ │
│ world │
│ logs │
│ backups │
│ whitelist │
│ server runtime │
└──────────────────┘
```
Ключевое правило:
> Git source является источником истины для желаемого состава сборки и управляемой конфигурации. Runtime является источником истины для текущего мира и прочего persistent state. Сгенерированные артефакты фиксируют конкретный релиз, но не заменяют его исходники.
---
# 3. Выбор технологий
## Обязательные компоненты
### packwiz
Использовать packwiz для:
- метаданных зависимостей модов;
- фиксации точных версий модов;
- интеграции с Modrinth;
- интеграции с CurseForge там, где это необходимо;
- metadata о client/server side;
- индексирования конфигов и ресурсов;
- генерации `.mrpack`.
### Modrinth `.mrpack`
Основной формат распространяемого артефакта.
Причины:
- Prism Launcher импортирует его напрямую.
- Формат поддерживает client/server side metadata.
- Он переносим.
- Хорошо работает с packwiz.
- Может использоваться серверным tooling для установки сборки.
### Prism Launcher
Основной клиентский лаунчер.
Платформа должна генерировать артефакты, которые Prism может использовать без необходимости вручную изменять созданный instance.
### Docker Compose
Оркестрация сервера.
### itzg/minecraft-server
Контейнерный runtime Minecraft-сервера.
По возможности использовать конфигурацию через environment variables и bind-mounted директории.
### Git
Git отслеживает:
- metadata модпака;
- определения модов;
- конфиги;
- скрипты;
- server compose-файлы;
- конфигурацию платформы.
Git не должен отслеживать:
- миры;
- логи;
- большие backups;
- runtime cache;
- секреты.
### SSH + rsync
Основной транспорт deployment для первой версии.
В v1 не требовать Kubernetes, Docker Registry, серверных агентов или CI/CD-инфраструктуры.
---
# 4. Структура репозитория
Начальная структура репозитория:
```text
minecraft-platform/
├── README.md
├── PLAN.md
├── Makefile
├── .gitignore
│
├── platform/
│ ├── config.yaml
│ └── schemas/
│
├── pack/
│ ├── pack.toml
│ ├── index.toml
│ ├── mods/
│ ├── config/
│ ├── defaultconfigs/
│ ├── resourcepacks/
│ ├── shaderpacks/
│ ├── datapacks/
│ └── kubejs/
│
├── server/
│ ├── compose.yaml
│ ├── compose.override.yaml.example
│ ├── server.properties
│ ├── config/
│ └── .env.example
│
├── scripts/
│ ├── build
│ ├── deploy
│ ├── rollback
│ ├── backup
│ ├── doctor
│ └── console
│
├── dist/
│ └── .gitkeep
│
└── runtime/
└── .gitkeep
```
`runtime/` используется только для локального development-runtime и должен быть добавлен в `.gitignore`, кроме `.gitkeep`.
Удалённый сервер должен использовать аналогичную структуру runtime-директорий.
---
# 5. Конфигурация платформы
Добавить единый высокоуровневый конфигурационный файл платформы.
Рекомендуемый начальный формат:
```yaml
schema_version: 1
pack:
directory: ./pack
build:
output_directory: ./dist
server:
host: minecraft
directory: /srv/minecraft/friday
memory: 8G
port: 25565
deploy:
transport: ssh
healthcheck_timeout: 120
```
Рекомендуемый файл:
```text
platform/config.yaml
```
Этот файл является manifest верхнего уровня для платформы.
packwiz остаётся источником истины для metadata отдельных модов.
Имя, версия сборки, Minecraft, loader и его версия читаются из `pack/pack.toml`. Не дублировать их и версии модов в `config.yaml`. Примеры версий в плане иллюстративны; совместимую комбинацию выбрать и проверить в Phase 0.
---
# 6. Правила источников истины
Необходимо явно зафиксировать зоны ответственности.
## Platform config отвечает за
- версию схемы конфигурации;
- серверные значения по умолчанию;
- deployment target;
- схему именования релизов.
## packwiz отвечает за
- имя и версию сборки в `pack.toml`;
- Minecraft, тип и точную версию loader в `pack.toml`;
- моды;
- версии модов;
- side metadata;
- downloads;
- pack indexes;
- правила включения на client/server.
## Серверная конфигурация отвечает за
- `server.properties`;
- начальные шаблоны whitelist и operators;
- server-specific overrides конфигурации модов;
- настройки Docker runtime.
## Runtime отвечает за
- действующие whitelist и operators (шаблоны применяются только при первом запуске);
- persistent данные модов, в том числе вне world;
- world;
- logs;
- cache;
- временные downloads;
- сгенерированное runtime-состояние.
Никогда не считать `runtime/mods` источником истины.
---
# 7. Дизайн CLI
В перспективе user-facing интерфейс должен быть одной командой.
Пример имени:
```text
mcpack
```
Точный язык реализации можно выбрать позже.
В v1 допустимо реализовать всё shell-скриптами или Makefile.
Ожидаемые команды в долгосрочной перспективе:
```bash
mcpack init
mcpack add create
mcpack add sodium --client
mcpack remove create
mcpack update create
mcpack update --all
mcpack check
mcpack doctor
mcpack build
mcpack release
mcpack deploy
mcpack restart
mcpack status
mcpack logs
mcpack console
mcpack backup
mcpack rollback
```
CLI должен оставаться тонким orchestration-слоем.
По возможности команды должны напрямую делегировать работу packwiz, Docker Compose, SSH и rsync.
---
# 8. Процесс сборки
Канонический flow:
```text
source pack + server config + pinned toolchain
→ validation
→ временная копия source
→ packwiz refresh + packwiz modrinth export в копии
→ dist/<name>-<version>/
```
Build не меняет tracked source. Если refresh выявляет устаревший исходный индекс, release прекращается с инструкцией явно обновить и закоммитить его.
Состав релиза:
```text
dist/friday-minecraft-0.4.0/
├── friday-minecraft-0.4.0.mrpack
├── server/
│ ├── compose.yaml
│ ├── server.properties
│ └── config/
├── manifest.json
└── SHA256SUMS
```
Manifest обязателен: schema version, имя и версия, Minecraft, loader и его версия, Git commit, признак dirty build, версия packwiz, image digest и список управляемых файлов. SHA256SUMS покрывает все файлы релиза кроме самого SHA256SUMS. Секреты и deployment target в релиз не включаются.
Prism получает .mrpack, сервер — весь каталог релиза. Общий .mrpack — начальный вариант; отдельная серверная трансформация допустима по результатам spike и должна быть воспроизводимой.
Локальный development build допускает dirty worktree и явно помечается. Release и deployment требуют чистый worktree. Готовые релизы сохраняются для deployment и rollback без повторной сборки.
---
# 9. Валидация сборки
`mcpack check` должен как минимум проверять:
- platform config успешно парсится;
- версия Minecraft указана;
- loader входит в комбинации, подтверждённые spike;
- версия loader зафиксирована;
- packwiz-файлы существуют;
- metadata packwiz внутренне консистентны;
- отсутствуют очевидные дубликаты определений модов;
- необходимые server-файлы существуют;
- output directory доступна для записи;
- известные пути секретов не отслеживаются Git (это не гарантия обнаружения всех секретов);
- pack может быть успешно экспортирован;
- Java образа соответствует выбранному Minecraft/loader;
- manifest и checksums согласованы.
Позже можно добавить:
- проверку совместимости client/server dependencies;
- обнаружение несовместимого loader;
- duplicate mod IDs;
- неподдерживаемые версии Minecraft;
- расширенную проверку совместимости Java runtime;
- schema validation конфигов.
---
# 10. Распространение клиентской сборки
Основной клиентский артефакт:
```text
*.mrpack
```
Ожидаемый flow для пользователя:
```text
Prism Launcher
→ Add Instance
→ Import
→ выбрать .mrpack
→ launch
```
Игрок не должен вручную устанавливать:
- loaders;
- отдельные моды;
- config-файлы.
Корректная side-разметка обязательна и проверяется на клиенте и сервере. Разметка модов не определяет установку произвольных config/resource/datapack-файлов: их стороны и целевые пути проверить в spike.
Для v1 начать с Modrinth. Перед добавлением CurseForge или внешних JAR проверить скачивание и право распространения: packwiz может включить JAR непосредственно в архив. См. [документацию packwiz](https://packwiz.infra.link/tutorials/hosting/modrinth/).
Для обновления в v1 игрок импортирует новый релиз в отдельный instance. Автоматическое обновление прежнего instance не обещается; личные настройки и saves не входят в релиз.
Примеры:
- Sodium: client-side;
- server performance mods: server-side;
- gameplay/content mods: обе стороны, если это требуется.
---
# 11. Server runtime
Использовать itzg/minecraft-server с закреплённым image digest и подходящей Java.
Пример контракта Compose (placeholders заменить при реализации):
```yaml
services:
minecraft:
image: itzg/minecraft-server:PINNED_TAG@sha256:PINNED_DIGEST
restart: unless-stopped
ports:
- "${MC_PORT:-25565}:25565"
environment:
EULA: "${MC_EULA:?Set MC_EULA after accepting the Minecraft EULA}"
MEMORY: "${MC_MEMORY:-8G}"
TYPE: MODRINTH
ONLINE_MODE: "false"
ENFORCE_SECURE_PROFILE: "false"
MODRINTH_MODPACK: /modpack/friday-minecraft-0.4.0.mrpack
volumes:
- ${MC_ROOT:?Set absolute server root}/runtime:/data
- ${MC_RELEASE_DIR:?Set absolute release directory}:/modpack:ro
```
Compose входит в релиз; абсолютные bind paths не зависят от cwd. Все операции явно передают одно стабильное Compose project name. Глобальный container_name не требуется.
Локальный .mrpack поддерживается [itzg](https://docker-minecraft-server.readthedocs.io/en/latest/types-and-platforms/mod-platforms/modrinth-modpacks/). Выбранный loader, очистку старых модов, side filtering и перезапись overrides проверить на закреплённом образе в Phase 0.
Критичные изменяемые данные хранятся в runtime на host, без named volumes. Первичная настройка включает UID/GID, принятие EULA и локальный файл секретов .env.
---
# 12. Процесс deployment
mcpack deploy применяет готовый неизменяемый релиз. Если его нет, сначала выполняется build из чистого worktree.
1. Проверить source, релиз и checksums.
2. Подключиться к host с установленными Docker, Compose, rsync, tar и zstd.
3. Получить общую remote-блокировку для deploy/backup/rollback.
4. Проверить права, свободное место, состояние предыдущей операции и конфликты конфигов.
5. Загрузить релиз во временный каталог, проверить checksums на host и атомарно опубликовать каталог releases/<name>-<version>.
6. Если этот релиз уже активен и healthy, завершить без restart.
7. Корректно остановить сервер и убедиться в завершении процесса.
8. Создать и проверить backup существующего persistent state.
9. Записать deployment state и применить новый релиз.
10. Запустить контейнер и дождаться healthcheck.
11. Только после успеха атомарно обновить active-release и previous-release.
При первом запуске с пустым runtime backup не требуется; этот случай фиксируется явно. Любая смена релиза существующего сервера требует backup, включая изменения конфигурации.
Ошибка загрузки не останавливает сервер. Ошибка backup запрещает запуск нового релиза; прежний можно запустить, если runtime ещё не менялся. При ошибке после применения нового релиза остановить сервер, вернуть non-zero и сохранить failed deployment state с инструкциями восстановления. Автоматически запускать старый pack на потенциально изменённом мире нельзя.
Одинаковая версия с другим содержимым отклоняется. Прерывание оставляет читаемый state: этап, исходный и целевой релизы, checksums, backup ID. Повторный запуск проверяет state и не начинает новую операцию поверх незавершённой.
---
# 13. Структура удалённого сервера
```text
/srv/minecraft/friday/
├── .env
├── active-release
├── previous-release
├── deployment-state.json
├── releases/
│ ├── friday-minecraft-0.3.0/
│ └── friday-minecraft-0.4.0/
├── runtime/
└── backups/
```
active-release содержит имя каталога последнего успешно запущенного релиза. Compose и серверные overrides берутся из этого релиза. Host settings и секреты остаются в .env; rollback их не меняет.
Указатели обновляются атомарно. Deployment state различает последний успешный и фактически применяемый релизы во время перехода. Все операции используют одну remote-блокировку.
---
# 14. Стратегия серверной конфигурации
Разделить конфигурацию на три класса.
## Конфигурация уровня модпака
Хранится в:
```text
pack/config/
pack/defaultconfigs/
pack/kubejs/
```
Это часть релиза модпака.
## Конфигурация уровня сервера
Хранится в:
```text
server/
```
Примеры:
- базовый `server.properties`;
- Compose-конфигурация;
- шаблоны server-specific config.
## Runtime-generated конфигурация
Хранится в:
```text
runtime/
```
Порядок применения: pack defaults → server overrides → runtime generation для неуправляемых файлов. У каждого управляемого пути один владелец; пересечения разрешаются явно как overrides, иначе validation прекращается.
Manifest содержит управляемые пути. Удалять только файлы прежнего релиза; неизвестные файлы не удалять молча. Для конфигов, изменяемых самим runtime, определить в spike политику replace, seed-only или preserve. Проверить defaultconfigs и datapacks на существующем мире.
Не определять тип или владельца конфига только по директории: в проверяемом NeoForge 1.21.1 серверные конфиги создаются в `runtime/config/`. Путь, поддержку `defaultconfigs/` и per-world overrides проверять для закреплённого loader; результаты одной ветки не переносить автоматически на Forge.
Не коммитить runtime-generated файлы автоматически.
В будущем добавить явную команду для переноса полезных runtime-изменений обратно в source.
Например:
```bash
mcpack config import server
```
---
# 15. Ручное редактирование runtime-файлов
Одно из требований — администратор должен иметь возможность вручную править файлы через SSH.
Например:
```bash
ssh minecraft
cd /srv/minecraft/friday/runtime
vim config/example.toml
vim server.properties
```
Эта возможность должна сохраняться.
Перед deployment сравнивать управляемые конфиги с ожидаемым состоянием прежнего релиза. При ручных изменениях показать diff и прекратить применение до явного выбора: перенести правки в source либо разрешить замену. Известные runtime-generated изменения обрабатывать по политике раздела 14. Это обязательная минимальная проверка конфликтов v1; неуправляемые persistent файлы сохраняются.
Будущее улучшение:
```bash
mcpack diff-runtime
```
Команда сравнивает server runtime config с конфигами под Git.
---
# 16. Backups
Перед сменой релиза существующего сервера обязателен backup после корректной остановки. mcpack backup использует ту же блокировку и в v1 также останавливает сервер, затем возвращает его в прежнее состояние работы после успешного backup.
Начальный вариант — архивировать весь runtime, кроме явно установленных disposable logs/cache/downloads. Исключения подтвердить в spike. Сохранять данные модов вне world, конфиги, server.properties, whitelist и operators. Releases и backups не входят в архив runtime.
Каждый snapshot имеет уникальный timestamp + ID, архив tar.zst и metadata JSON: исходный и целевой релизы, checksums релиза и архива, исключения и время.
Писать временный архив, проверить завершение tar/zstd и читаемость архива, затем публиковать атомарно. Ошибка блокирует deployment.
В v1 обязательна проверенная инструкция восстановления в отдельную директорию вместе с соответствующим сохранённым релизом. Backup не удаляется автоматически. Off-host копии и retention policy — последующее улучшение.
---
# 17. Rollback
В v1 различать явные операции:
```bash
mcpack rollback-pack 0.3.0
mcpack rollback --backup <backup-id>
```
rollback-pack меняет релиз без восстановления persistent state и требует явного подтверждения совместимости с текущим миром. SemVer не доказывает совместимость. Команда rollback без указания режима показывает план и ничего не меняет.
rollback --backup восстанавливает snapshot и связанный с ним исходный релиз, явно сообщая о потере прогресса после снимка. В v1 эта операция может оставаться документированной ручной процедурой, проверенной на практике.
Обе операции используют блокировку, останавливают сервер и сначала сохраняют текущее состояние отдельным backup. Целевой релиз и snapshot проверяются до изменения runtime. Восстановление — в отдельный каталог с последующей заменой runtime; распаковка поверх существующих файлов запрещена.
Откат возвращает .mrpack, server overrides и Compose/image исходного релиза. Host secrets остаются прежними. Указатели обновляются только после healthcheck. Старый pack не запускается автоматически на мире, изменённом неудачным deployment.
---
# 18. Health checks
Deployment успешен, когда контейнер стабильно работает и Minecraft status query подтверждает готовность отвечать по игровому протоколу. Использовать штатный healthcheck itzg, проверив его на закреплённом образе.
Container state и TCP connect — диагностические проверки, недостаточные для подтверждения готовности. Crash, restart loop и timeout возвращают non-zero с указанием logs и recovery state.
Timeout настраиваемый; 120 секунд — пример, не универсальный предел. Первый запуск с загрузкой dependencies учитывать отдельно. Реальное подключение клиента и состав модов проверяются в spike.
---
# 19. Логи и консоль
Предоставить wrappers:
```bash
mcpack logs
mcpack logs --follow
mcpack console
```
Ожидаемый mapping:
```bash
ssh host docker compose logs
```
и:
```bash
ssh -t host docker exec -it <container> rcon-cli
```
Не реализовывать собственный протокол Minecraft console.
---
# 20. Версионирование
Использовать semantic versioning для самого модпака:
```text
MAJOR.MINOR.PATCH
```
Предлагаемая семантика:
SemVer описывает масштаб изменений, но не гарантирует безопасность мира; совместимость отката оценивается отдельно.
## PATCH
- исправления конфигурации;
- небольшие compatibility fixes;
- server tuning;
- безопасные patch-update модов.
## MINOR
- добавление модов;
- удаление некритичных модов;
- gameplay additions;
- значимые изменения конфигурации.
## MAJOR
- миграция версии Minecraft;
- крупная миграция loader;
- намеренно world-breaking изменения;
- существенная переработка сборки.
Не выводить версию Minecraft из semantic version самого модпака.
---
# 21. Требования к воспроизводимости
Для:
```bash
git checkout v0.4.0
```
проект должен воспроизвести ту же эффективную сборку при доступности внешних downloads. Побайтово одинаковый ZIP не обещается: timestamps и порядок упаковки могут отличаться. Idempotency deployment определяется checksum сохранённого релиза, а не повторным export.
Git и .mrpack не гарантируют вечную доступность downloads. Готовые релизы хранить; offline cache/mirror — отдельная будущая возможность.
Избегать:
```text
latest
recommended
newest
automatic unpinned loader versions
```
Фиксировать:
- версию Minecraft;
- loader;
- моды;
- digest container image и версию Java;
- версию или commit packwiz и других инструментов, влияющих на build.
Toolchain зафиксировать уже в spike; формат lock file уточнить после него.
Пример:
```yaml
packwiz: "..."
itzg_image: "..."
platform_schema: 1
```
---
# 22. Git strategy
Отслеживать:
```text
platform/
pack/
server/
scripts/
Makefile
README.md
PLAN.md
```
Игнорировать:
```gitignore
dist/*
!dist/.gitkeep
runtime/*
!runtime/.gitkeep
server/.env
*.log
backups/
```
Создавать Git tags для релизов:
```bash
git tag v0.4.0
```
Потенциальный будущий release flow:
```bash
mcpack release 0.4.0
```
который:
1. валидирует дерево;
2. требует clean working copy;
3. обновляет версию;
4. выполняет build;
5. при ошибке восстанавливает прежнюю версию;
6. коммитит изменение версии в pack.toml;
7. собирает финальный release из чистого commit и генерирует checksums;
8. создаёт tag только после успешного build. При ошибке финального build tag не создаётся, состояние явно выводится.
Не выполнять Git push автоматически в v1.
---
# 23. Секреты
Никогда не хранить в Git:
- SSH private keys;
- RCON passwords;
- server secrets;
- API tokens;
- CurseForge credentials, если они потребуются;
- credentials backup repository.
Использовать:
```text
.env
environment variables
SSH config
```
Предоставить:
```text
.env.example
```
---
# 24. SSH configuration
Предполагать, что администраторы могут определить:
```sshconfig
Host minecraft
HostName example.org
User minecraft
IdentityFile ~/.ssh/minecraft_ed25519
```
Тогда platform config достаточно:
```yaml
server:
host: minecraft
```
Не требовать хранить SSH username или путь до private key в config, если это не нужно.
---
# 25. Обработка ошибок
Команды должны падать рано и с понятной диагностикой.
Плохо:
```text
deployment failed
```
Хорошо:
```text
ERROR: packwiz export failed
Command:
packwiz modrinth export
Exit status:
1
No files were uploaded to the server.
```
Этапы deployment должны быть явно видны.
Например:
```text
[1/7] Validate pack
[2/7] Build release
[3/7] Upload and verify release
[4/7] Stop server and backup state
[5/7] Apply release
[6/7] Start and healthcheck
[7/7] Record active release
```
---
# 26. Dry run
Важная будущая возможность:
```bash
mcpack deploy --dry-run
```
Команда должна показать:
- какой локальный release будет собран;
- destination host;
- какие файлы будут загружены;
- какой backup будет создан;
- какое Compose-действие будет выполнено;
- переход между active versions.
Dry run не должен изменять локальное или удалённое состояние.
Желательно предусмотреть эту возможность архитектурно с самого начала.
---
# 27. Команда doctor
Реализовать:
```bash
mcpack doctor
```
Проверять локальное окружение:
- packwiz установлен;
- Docker установлен, если используются локальные server tasks;
- SSH установлен;
- rsync установлен;
- Git repository корректен;
- config валиден.
Опциональные remote checks:
```bash
mcpack doctor --remote
```
Проверять:
- SSH connectivity;
- доступность Docker;
- доступность Docker Compose;
- права на remote directory;
- свободное место на диске.
---
# 28. Этапы разработки
## Phase 0 — Spike
Цель:
Вручную проверить интеграцию компонентов экосистемы.
Задачи:
- создать минимальный packwiz pack;
- выбрать и закрепить NeoForge или Forge и совместимую версию Minecraft;
- добавить минимальный совместимый набор Modrinth-модов, включая gameplay-мод и client-only мод;
- экспортировать `.mrpack`;
- импортировать `.mrpack` в Prism;
- запустить совместимый modded server через `itzg/minecraft-server`;
- установить тот же pack на серверной стороне;
- проверить, что клиент может подключиться;
- проверить bind-mounted runtime и сохранение мира при recreate;
- проверить client-only мод и его отсутствие на сервере;
- обновить релиз, удалить мод и проверить отсутствие старого JAR;
- проверить pack config, server override и ручные правки;
- проверить defaultconfigs/datapacks на существующем мире;
- создать backup остановленного сервера и восстановить его с прежним релизом;
- проверить healthcheck и startup failure.
Результат:
```text
docs/spike-results.md
```
Не писать основной CLI до подтверждения integration path. Минимальные скрипты, Compose и каркас для spike допустимы. Prism import и подключение требуют реальной GUI-сессии; проверять offline-аккаунт/Launch Offline с сервером online-mode=false. При отсутствии GUI отметить проверки pending, а не passed.
Acceptance criteria:
- Prism импортирует сгенерированный pack;
- сервер успешно запускается;
- modded client с целевым loader подключается к серверу без онлайн-проверки аккаунта;
- runtime-файлы существуют как обычные host-файлы.
---
## Phase 1 — Оформление каркаса после spike
Статус: завершена для NeoForge 1.21.1. Каркас и проверка чистого локального clone описаны в `docs/phase1-results.md`. Platform manifest подключается к командам в Phase 2.
Создать:
- структуру репозитория;
- `platform/config.yaml`;
- `.gitignore`;
- первоначальный packwiz pack;
- первоначальный Compose-файл;
- `.env.example`.
Acceptance criteria:
```bash
git clone
packwiz refresh
packwiz modrinth export
docker compose config
```
выполняются успешно.
---
## Phase 2 — Build command
Статус: завершена. `./mcpack build` читает platform config и создаёт полный development release 0.0.4; `--release` требует чистого Git worktree. Проверки и текущие ограничения описаны в `docs/phase2-results.md`, контракт — в `docs/build.md`.
Реализовать:
```bash
mcpack build
```
или первоначально:
```bash
make build
```
Ответственность:
- парсинг platform config;
- валидация pack;
- создание `dist`;
- экспорт `.mrpack`;
- детерминированное переименование артефакта;
- генерация SHA-256;
- генерация release manifest.
Acceptance criteria:
```text
dist/<name>-<version>/<name>-<version>.mrpack
dist/<name>-<version>/server/
dist/<name>-<version>/SHA256SUMS
dist/<name>-<version>/manifest.json
```
существуют после build.
---
## Phase 3 — Управление модами
Статус: завершена. Mod wrappers сохраняют вывод/prompts/exit code packwiz. Реальные add/remove/update/update --all и четыре full build проверены в тестовом clone; результаты — `docs/phase3-results.md`, контракт — `docs/mods.md`.
Предоставить тонкие wrappers:
```bash
mcpack add <mod>
mcpack remove <mod>
mcpack update <mod>
mcpack update --all
```
Не скрывать без необходимости сообщения об ошибках packwiz.
Acceptance criteria:
- добавленные моды появляются в metadata packwiz;
- удаление мода корректно меняет source;
- build остаётся валидным.
---
## Phase 4 — Server runtime
Статус: завершена. Full release 0.0.4 проверен на пустом runtime через `scripts/server.sh`: pinned Minecraft/NeoForge/image, host bind mounts, restart/recreate без потери мира. Основной Phase 0 сервер не менялся. Результаты — `docs/phase4-results.md`, контракт — `docs/runtime.md`.
Создать Docker runtime, который:
- использует pinned Minecraft version;
- использует pinned loader;
- использует host bind mounts;
- загружает сгенерированный pack;
- сохраняет world между restart/recreate.
Acceptance criteria:
```bash
docker compose up -d
```
запускает сервер с пустой runtime directory после явной настройки EULA, host env, прав и путей согласно разделу 11.
---
## Phase 5 — Backups и восстановление
Статус: завершена. `./mcpack backup` сохраняет весь остановленный runtime и исходный полный релиз под общей lifecycle lock; `restore` проверяет snapshot и восстанавливает только в новый root. Ошибка backup блокирует apply callback. Реальный backup/ошибка tar/запуск восстановленного NeoForge проверены на отдельном сервере; результаты — `docs/phase5-results.md`, инструкция — `docs/backups.md`.
До remote deployment реализовать раздел 16: блокировку, остановку, backup и проверенную процедуру восстановления.
Acceptance criteria: ошибка backup блокирует применение; snapshot восстанавливается в отдельный каталог; данные модов вне world сохраняются.
---
## Phase 6 — Healthcheck
Статус: завершена. `scripts/server.sh up/start/restart --wait` и `health` проверяют штатный mc-health, свежий Minecraft status query и окно стабильности. Реальные timeout, crash с exit 137 и restart loop проверены на отдельных test roots; ошибки возвращают non-zero с report/logs и recovery state. Результаты — `docs/phase6-results.md`, контракт — `docs/health.md`.
Реализовать раздел 18. Успешный старт возвращает 0; crash, restart loop и timeout — non-zero с указанием logs.
---
## Phase 7 — SSH Deployment
Статус: завершена для проверенного NeoForge 1.21.1. `mcpack deploy` использует SSH/rsync, общую host lock, immutable checksums, проверку ручных конфликтов, backup-before-apply и healthcheck перед active/previous pointers. Полный update flow проверен на локальном SSH-стенде; clean release 0.0.4 реально установлен и healthy на crab@192.168.1.61:2228 в отдельном root. Повторный deploy — no-op. Результаты — `docs/phase7-results.md`, контракт — `docs/deploy.md`.
Реализовать полный flow раздела 12 с готовыми backup и healthcheck.
Acceptance criteria:
- первый релиз устанавливается на host с готовыми зависимостями; установка Docker и cloud provisioning вне scope;
- повторный deploy healthy релиза не перезапускает сервер;
- та же версия с другим содержимым отклоняется;
- world сохраняется;
- параллельная операция блокируется;
- сбой передачи, backup или startup оставляет восстановимое состояние;
- ручные конфликты конфигов выявляются до замены файлов.
---
## Phase 8 — Rollback
Статус: завершена. Реализованы pack-only и snapshot rollback по SSH без build.
Результаты и ограничения: [docs/phase8-results.md](docs/phase8-results.md).
Acceptance criteria:
```bash
mcpack rollback
```
без указания режима ничего не меняет. Явный rollback использует сохранённый полный релиз без повторного build; pack-only требует подтверждения совместимости.
Восстановление persistent snapshot автоматизировано и проверено на изолированном
SSH/Docker-стенде. Оба режима требуют явного подтверждения и проверенного backup
текущего состояния; pointers меняются после health. Ручной recovery после ошибки
описан в [docs/rollback.md](docs/rollback.md).
---
## Phase 9 — Release workflow
Статус: завершена. Candidate build, version commit, чистый финальный build,
checksums и annotated tag проверены с настоящим packwiz в отдельном Git clone.
Результаты: [docs/phase9-results.md](docs/phase9-results.md).
Workflow и recovery: [docs/releases.md](docs/releases.md).
Реализовано:
```bash
mcpack release <version>
```
Проверки:
- Git worktree чистый;
- version валидна и ещё не занята релизом или tag;
- версия явно обновляется в pack.toml согласно разделу 22;
- build успешен;
- checksum создан;
- Git tag создан.
Публикация остаётся вне scope первой версии.
---
# 29. Выбор языка реализации
Не принимать решение преждевременно.
Начать с:
```text
Makefile + shell
```
если этого достаточно.
Перейти к полноценному CLI, когда orchestration станет сложным.
Возможные варианты:
## Go
Преимущества:
- один binary;
- отличный CLI tooling;
- удобно работать с SSH/process orchestration;
- простая cross-platform distribution;
- strong typing.
Предпочтительный вариант, если платформа станет переиспользуемым инструментом.
## Python
Преимущества:
- быстрая разработка;
- хорошая экосистема YAML/TOML;
- удобно писать automation.
Недостаток:
- управление runtime/environment.
## Shell
Преимущества:
- минимум начального кода;
- прозрачность.
Недостатки:
- error handling;
- portability;
- сложное state management;
- тестирование.
Рекомендация:
Для integration spike использовать shell/Makefile.
Если проект переживёт spike и deployment-логика начнёт расти, реализовать основной CLI на Go.
---
# 30. Предлагаемая структура Go CLI
Если выбран Go:
```text
cmd/
└── mcpack/
└── main.go
internal/
├── config/
├── packwiz/
├── build/
├── deploy/
├── backup/
├── health/
├── ssh/
├── docker/
├── release/
└── cli/
```
Ключевое правило:
Integration packages должны оборачивать внешние инструменты, а не переписывать их функциональность.
Например:
```text
internal/packwiz
```
должен вызывать packwiz и переводить только релевантный платформе результат.
Он не должен реализовывать Modrinth dependency resolver.
---
# 31. Абстракция выполнения команд
При переходе к Go создать executor по требованиям реальных вызовов; spike не требует этой абстракции.
Концепция:
```go
type Executor interface {
Run(ctx context.Context, name string, args ...string) error
}
```
Позже реализовать:
- local executor;
- SSH executor;
- dry-run executor.
Это даст:
- testability;
- command logging;
- dry runs;
- единообразные ошибки.
---
# 32. Модель состояния
Не использовать скрытую database платформы в v1.
Предпочитать state, представленный через:
```text
Git
filesystem
release manifest
active-release
```
Remote state:
```text
releases/
active-release
previous-release
deployment-state.json
backups/
runtime/
```
Состояние должно намеренно оставаться inspectable и repairable без binary самой платформы.
---
# 33. Idempotency
Команды должны нормально переносить повторный запуск.
Например:
```bash
mcpack build
```
может заменять локальный development artifact. Финализированный release неизменяем: совпадающие checksums дают no-op, другое содержимое требует новой версии. Сборка выполняется во временном каталоге.
```bash
mcpack deploy
```
должен сверять checksums всего релиза и различать uploaded, applied и healthy active state.
```bash
mcpack backup
```
должен создавать уникальные timestamped backups.
Не полагаться на одноразовое hidden initialization state, которое нельзя восстановить.
---
# 34. Стратегия тестирования
## Unit tests
Для внутреннего кода платформы:
- config parsing;
- validation;
- release naming;
- version parsing;
- command generation;
- manifest generation.
## Integration tests
Использовать временные директории для:
- pack build;
- release layout;
- атомарного переключения `active-release` после healthcheck;
- backup archive и восстановления в отдельный каталог;
- блокировок, interrupted deployment и отказа при несовпадении checksums;
- конфликтов управляемых конфигов и сохранения неизвестных файлов.
## External integration tests
Ручные или opt-in:
- packwiz;
- Docker;
- SSH;
- реальный запуск Minecraft.
Не требовать запуск Minecraft-сервера при каждом unit test run.
---
# 35. Fixtures
Создать небольшие test fixtures.
Например:
```text
testdata/
├── minimal-pack/
├── invalid-config/
├── valid-config/
└── fake-runtime/
```
Fixtures должны быть минимальными.
Не коммитить Minecraft binaries или крупные mod jars в test data.
---
# 36. Observability
CLI должен выводить достаточно информации для диагностики проблем.
Для всех внешних команд предусмотреть verbose logging.
Например:
```bash
mcpack deploy --verbose
```
Возможный output:
```text
remote host: minecraft
remote path: /srv/minecraft/friday
release: 0.4.0
artifact sha256: ...
```
Никогда не выводить секреты.
---
# 37. Будущая возможность: hosting сборок
Позже можно добавить optional HTTP publication.
Возможная архитектура:
```text
build
│
├── .mrpack
└── packwiz files
│
▼
static HTTP host
```
Возможные сценарии:
- Prism import по URL;
- автоматические packwiz updates;
- сервер сам забирает pack;
- release index.
Не входит в v1.
---
# 38. Будущая возможность: автообновление клиентов
Потенциальное решение:
- разместить packwiz files по HTTP;
- использовать Prism-compatible bootstrap/update mechanism;
- игрок импортирует pack один раз;
- pack обновляется автоматически перед launch.
Не реализовывать до стабилизации базового release/deployment flow.
---
# 39. Будущая возможность: CI/CD
Потенциальный pipeline:
```text
git push
│
▼
validate
│
▼
build
│
▼
publish artifact
│
▼
optional deploy
```
Возможные провайдеры:
- GitHub Actions;
- GitLab CI;
- Gitea Actions;
- self-hosted CI.
Не делать CI обязательным.
Локальные команды остаются каноническими.
---
# 40. Будущая возможность: несколько серверов
В будущем конфигурация может поддерживать:
```yaml
servers:
survival:
host: mc-prod
directory: /srv/minecraft/survival
test:
host: mc-test
directory: /srv/minecraft/test
```
Тогда:
```bash
mcpack deploy survival
mcpack deploy test
```
Не реализовывать, пока deployment на один сервер не станет стабильным.
Config schema нужно проектировать так, чтобы такое расширение оставалось возможным.
---
# 41. Будущая возможность: profiles
Возможные profiles:
```text
client
server
performance-client
performance-server
optional-content
```
Но сначала использовать side metadata packwiz.
Не вводить собственную систему profiles без реального use case.
---
# 42. Не-цели для v1
Не реализовывать:
- собственный Minecraft launcher;
- собственный mod repository;
- собственный dependency solver;
- web UI;
- поддержку Kubernetes;
- автоматический public hosting;
- database;
- multi-user authentication;
- cloud provisioning;
- автоматическую миграцию world;
- автоматическое разрешение конфликтующих модов;
- автоматический Git push;
- dynamic container orchestration.
v1 должна оставаться максимально простой и предсказуемой.
---
# 43. Definition of Done для v1
Первая полезная версия готова, когда следующий flow работает надёжно:
```bash
git clone <repo>
mcpack doctor
mcpack add create
mcpack build
# друг импортирует сгенерированный .mrpack в Prism
mcpack deploy
mcpack logs
```
И выполняются следующие свойства:
- client artifact импортируется в Prism;
- сервер запускается из того же определения сборки;
- клиент на NeoForge/Forge может подключиться без Microsoft/Mojang-аккаунта;
- моды версионируются через packwiz;
- server files хранятся как обычные директории на host;
- world переживает recreation контейнера;
- deployment выполняется через SSH;
- pack можно пересобрать из Git;
- перед любой сменой релиза существующего сервера создаётся проверенный backup;
- предыдущий полный release и его persistent snapshot можно восстановить;
- удаление мода, конфликт конфигов и failed deployment проверены;
- для критичных данных не требуется Docker named volume.
---
# 44. Первая задача для Codex
Codex должен начать с integration spike, а не с реализации финального CLI.
Задача:
```text
Реализуй только Phase 0.
Создай минимально возможный рабочий репозиторий, который доказывает:
1. packwiz может описывать модпак.
2. packwiz может экспортировать Modrinth .mrpack.
3. Prism Launcher может импортировать этот артефакт.
4. itzg/minecraft-server может запустить сервер на основе той же сборки.
5. Состояние сервера хранится в bind-mounted директории.
6. Модифицированный клиент Prism может подключиться к серверу.
7. Обновление удаляет старые моды и предсказуемо применяет конфиги.
8. Backup и восстановление persistent state с прежним релизом работают.
Недоступные GUI-проверки отметить pending; Phase 0 не считать завершённой
до фактического импорта и подключения.
Пока не реализовывай mcpack CLI.
Задокументируй все команды, предположения, точные версии инструментов,
обнаруженные проблемы и любые необходимые изменения архитектуры
в docs/spike-results.md.
Не добавляй generated runtime data в Git.
```
---
# 45. Принципы реализации для Codex
При реализации проекта:
1. Предпочитай простые и прозрачные механизмы.
2. Не дублируй функциональность, которую надёжно предоставляют packwiz или Docker.
3. Не вводи скрытое mutable state без веской причины.
4. Любой deployment должен быть восстановим.
5. Фиксируй версии.
6. Сохраняй возможность человеку напрямую работать с исходными файлами.
7. Разрушительные операции должны быть явными.
8. Делай backup перед изменением persistent Minecraft state.
9. Считай world более ценным, чем application runtime.
10. Client и server artifacts должны происходить из одного source pack.
11. По возможности держи код платформы независимым от конкретного modpack.
12. Не исправляй и не изменяй пользовательскую конфигурацию молча.
13. Команды должны возвращать осмысленные exit codes.
14. Ошибки внешних команд должны содержать полезный контекст.
15. Предпочитай deterministic output paths и имена артефактов.
---
# 46. Ближайшие шаги
Выполнять в таком порядке:
```text
1. Создать каркас репозитория.
2. Установить и зафиксировать версию packwiz.
3. Выбрать одну версию Minecraft.
4. Выбрать один loader.
5. Добавить минимальный заведомо совместимый набор модов.
6. Экспортировать .mrpack.
7. Импортировать его в Prism.
8. Создать Docker Compose для сервера.
9. Запустить сервер с bind-mounted runtime.
10. Подключиться к серверу из Prism.
11. Проверить обновление, удаление мода, конфиги, backup/restore и healthcheck.
12. Записать результаты spike и pending проверки.
13. После подтверждения критериев начинать разработку mcpack CLI.
```
Главный архитектурный вопрос, который необходимо проверить во время spike:
> Может ли один и тот же source pack чисто порождать и Prism client experience, и Dockerized server runtime без ручного расхождения между ними?
Если да — сохранить эту архитектуру.
Если нет — задокументировать минимально необходимый слой трансформации между client/server до разработки дополнительного tooling.