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

62 KiB
Raw Permalink Blame History

Платформа для 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. Основная архитектура

Система состоит из четырёх концептуальных слоёв.

┌──────────────────────────────────────────┐
│ 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. Структура репозитория

Начальная структура репозитория:

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. Конфигурация платформы

Добавить единый высокоуровневый конфигурационный файл платформы.

Рекомендуемый начальный формат:

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

Рекомендуемый файл:

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 интерфейс должен быть одной командой.

Пример имени:

mcpack

Точный язык реализации можно выбрать позже.

В v1 допустимо реализовать всё shell-скриптами или Makefile.

Ожидаемые команды в долгосрочной перспективе:

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:

source pack + server config + pinned toolchain
→ validation
→ временная копия source
→ packwiz refresh + packwiz modrinth export в копии
→ dist/<name>-<version>/

Build не меняет tracked source. Если refresh выявляет устаревший исходный индекс, release прекращается с инструкцией явно обновить и закоммитить его.

Состав релиза:

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. Распространение клиентской сборки

Основной клиентский артефакт:

*.mrpack

Ожидаемый flow для пользователя:

Prism Launcher
→ Add Instance
→ Import
→ выбрать .mrpack
→ launch

Игрок не должен вручную устанавливать:

  • loaders;
  • отдельные моды;
  • config-файлы.

Корректная side-разметка обязательна и проверяется на клиенте и сервере. Разметка модов не определяет установку произвольных config/resource/datapack-файлов: их стороны и целевые пути проверить в spike.

Для v1 начать с Modrinth. Перед добавлением CurseForge или внешних JAR проверить скачивание и право распространения: packwiz может включить JAR непосредственно в архив. См. документацию packwiz.

Для обновления в 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 заменить при реализации):

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. Выбранный 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/-.
  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. Структура удалённого сервера

/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. Стратегия серверной конфигурации

Разделить конфигурацию на три класса.

Конфигурация уровня модпака

Хранится в:

pack/config/
pack/defaultconfigs/
pack/kubejs/

Это часть релиза модпака.

Конфигурация уровня сервера

Хранится в:

server/

Примеры:

  • базовый server.properties;
  • Compose-конфигурация;
  • шаблоны server-specific config.

Runtime-generated конфигурация

Хранится в:

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.

Например:

mcpack config import server

15. Ручное редактирование runtime-файлов

Одно из требований — администратор должен иметь возможность вручную править файлы через SSH.

Например:

ssh minecraft

cd /srv/minecraft/friday/runtime

vim config/example.toml
vim server.properties

Эта возможность должна сохраняться.

Перед deployment сравнивать управляемые конфиги с ожидаемым состоянием прежнего релиза. При ручных изменениях показать diff и прекратить применение до явного выбора: перенести правки в source либо разрешить замену. Известные runtime-generated изменения обрабатывать по политике раздела 14. Это обязательная минимальная проверка конфликтов v1; неуправляемые persistent файлы сохраняются.

Будущее улучшение:

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 различать явные операции:

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:

mcpack logs
mcpack logs --follow
mcpack console

Ожидаемый mapping:

ssh host docker compose logs

и:

ssh -t host docker exec -it <container> rcon-cli

Не реализовывать собственный протокол Minecraft console.


20. Версионирование

Использовать semantic versioning для самого модпака:

MAJOR.MINOR.PATCH

Предлагаемая семантика:

SemVer описывает масштаб изменений, но не гарантирует безопасность мира; совместимость отката оценивается отдельно.

PATCH

  • исправления конфигурации;
  • небольшие compatibility fixes;
  • server tuning;
  • безопасные patch-update модов.

MINOR

  • добавление модов;
  • удаление некритичных модов;
  • gameplay additions;
  • значимые изменения конфигурации.

MAJOR

  • миграция версии Minecraft;
  • крупная миграция loader;
  • намеренно world-breaking изменения;
  • существенная переработка сборки.

Не выводить версию Minecraft из semantic version самого модпака.


21. Требования к воспроизводимости

Для:

git checkout v0.4.0

проект должен воспроизвести ту же эффективную сборку при доступности внешних downloads. Побайтово одинаковый ZIP не обещается: timestamps и порядок упаковки могут отличаться. Idempotency deployment определяется checksum сохранённого релиза, а не повторным export.

Git и .mrpack не гарантируют вечную доступность downloads. Готовые релизы хранить; offline cache/mirror — отдельная будущая возможность.

Избегать:

latest
recommended
newest
automatic unpinned loader versions

Фиксировать:

  • версию Minecraft;
  • loader;
  • моды;
  • digest container image и версию Java;
  • версию или commit packwiz и других инструментов, влияющих на build.

Toolchain зафиксировать уже в spike; формат lock file уточнить после него.

Пример:

packwiz: "..."
itzg_image: "..."
platform_schema: 1

22. Git strategy

Отслеживать:

platform/
pack/
server/
scripts/
Makefile
README.md
PLAN.md

Игнорировать:

dist/*
!dist/.gitkeep

runtime/*
!runtime/.gitkeep

server/.env

*.log

backups/

Создавать Git tags для релизов:

git tag v0.4.0

Потенциальный будущий release flow:

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.

Использовать:

.env
environment variables
SSH config

Предоставить:

.env.example

24. SSH configuration

Предполагать, что администраторы могут определить:

Host minecraft
    HostName example.org
    User minecraft
    IdentityFile ~/.ssh/minecraft_ed25519

Тогда platform config достаточно:

server:
  host: minecraft

Не требовать хранить SSH username или путь до private key в config, если это не нужно.


25. Обработка ошибок

Команды должны падать рано и с понятной диагностикой.

Плохо:

deployment failed

Хорошо:

ERROR: packwiz export failed

Command:
  packwiz modrinth export

Exit status:
  1

No files were uploaded to the server.

Этапы deployment должны быть явно видны.

Например:

[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

Важная будущая возможность:

mcpack deploy --dry-run

Команда должна показать:

  • какой локальный release будет собран;
  • destination host;
  • какие файлы будут загружены;
  • какой backup будет создан;
  • какое Compose-действие будет выполнено;
  • переход между active versions.

Dry run не должен изменять локальное или удалённое состояние.

Желательно предусмотреть эту возможность архитектурно с самого начала.


27. Команда doctor

Реализовать:

mcpack doctor

Проверять локальное окружение:

  • packwiz установлен;
  • Docker установлен, если используются локальные server tasks;
  • SSH установлен;
  • rsync установлен;
  • Git repository корректен;
  • config валиден.

Опциональные remote checks:

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.

Результат:

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:

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.

Реализовать:

mcpack build

или первоначально:

make build

Ответственность:

  • парсинг platform config;
  • валидация pack;
  • создание dist;
  • экспорт .mrpack;
  • детерминированное переименование артефакта;
  • генерация SHA-256;
  • генерация release manifest.

Acceptance criteria:

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:

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:

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.

Acceptance criteria:

mcpack rollback

без указания режима ничего не меняет. Явный rollback использует сохранённый полный релиз без повторного build; pack-only требует подтверждения совместимости.

Восстановление persistent snapshot автоматизировано и проверено на изолированном SSH/Docker-стенде. Оба режима требуют явного подтверждения и проверенного backup текущего состояния; pointers меняются после health. Ручной recovery после ошибки описан в docs/rollback.md.


Phase 9 — Release workflow

Статус: завершена. Candidate build, version commit, чистый финальный build, checksums и annotated tag проверены с настоящим packwiz в отдельном Git clone. Результаты: docs/phase9-results.md. Workflow и recovery: docs/releases.md.

Реализовано:

mcpack release <version>

Проверки:

  • Git worktree чистый;
  • version валидна и ещё не занята релизом или tag;
  • версия явно обновляется в pack.toml согласно разделу 22;
  • build успешен;
  • checksum создан;
  • Git tag создан.

Публикация остаётся вне scope первой версии.


29. Выбор языка реализации

Не принимать решение преждевременно.

Начать с:

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:

cmd/
└── mcpack/
    └── main.go

internal/
├── config/
├── packwiz/
├── build/
├── deploy/
├── backup/
├── health/
├── ssh/
├── docker/
├── release/
└── cli/

Ключевое правило:

Integration packages должны оборачивать внешние инструменты, а не переписывать их функциональность.

Например:

internal/packwiz

должен вызывать packwiz и переводить только релевантный платформе результат.

Он не должен реализовывать Modrinth dependency resolver.


31. Абстракция выполнения команд

При переходе к Go создать executor по требованиям реальных вызовов; spike не требует этой абстракции.

Концепция:

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, представленный через:

Git
filesystem
release manifest
active-release

Remote state:

releases/
active-release
previous-release
deployment-state.json
backups/
runtime/

Состояние должно намеренно оставаться inspectable и repairable без binary самой платформы.


33. Idempotency

Команды должны нормально переносить повторный запуск.

Например:

mcpack build

может заменять локальный development artifact. Финализированный release неизменяем: совпадающие checksums дают no-op, другое содержимое требует новой версии. Сборка выполняется во временном каталоге.

mcpack deploy

должен сверять checksums всего релиза и различать uploaded, applied и healthy active state.

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.

Например:

testdata/
├── minimal-pack/
├── invalid-config/
├── valid-config/
└── fake-runtime/

Fixtures должны быть минимальными.

Не коммитить Minecraft binaries или крупные mod jars в test data.


36. Observability

CLI должен выводить достаточно информации для диагностики проблем.

Для всех внешних команд предусмотреть verbose logging.

Например:

mcpack deploy --verbose

Возможный output:

remote host: minecraft
remote path: /srv/minecraft/friday
release: 0.4.0
artifact sha256: ...

Никогда не выводить секреты.


37. Будущая возможность: hosting сборок

Позже можно добавить optional HTTP publication.

Возможная архитектура:

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:

git push
   │
   ▼
validate
   │
   ▼
build
   │
   ▼
publish artifact
   │
   ▼
optional deploy

Возможные провайдеры:

  • GitHub Actions;
  • GitLab CI;
  • Gitea Actions;
  • self-hosted CI.

Не делать CI обязательным.

Локальные команды остаются каноническими.


40. Будущая возможность: несколько серверов

В будущем конфигурация может поддерживать:

servers:
  survival:
    host: mc-prod
    directory: /srv/minecraft/survival

  test:
    host: mc-test
    directory: /srv/minecraft/test

Тогда:

mcpack deploy survival
mcpack deploy test

Не реализовывать, пока deployment на один сервер не станет стабильным.

Config schema нужно проектировать так, чтобы такое расширение оставалось возможным.


41. Будущая возможность: profiles

Возможные profiles:

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 работает надёжно:

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.

Задача:

Реализуй только 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. Ближайшие шаги

Выполнять в таком порядке:

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.