Files
BiLauncher/doc/cpp/VersionInstaller.md
T
2026-10-11 22:32:13 +03:00

6.4 KiB
Raw Permalink Blame History

VersionInstaller

versioninstaller.h, versioninstaller.cpp

Ставит версию игры в .minecraft: описание версии, клиентский jar, библиотеки, индекс ресурсов, сами ресурсы и конфиг логирования. Одновременно ставится одна версия, остальные ждут в очереди. Всё работает в GUI-потоке на асинхронной сети.

Экземпляр держит LauncherBackend. Ещё им пользуется ModLoaderInstaller: перед установкой модлоадера нужно поставить базовую версию, а после установки докачать библиотеки нового профиля.

Интерфейс

  • install(gameDir, versionId) — поставить в очередь. Если эта версия уже ставится или ждёт, ничего не происходит. Если id содержит слэши, . или .., сразу приходит failed.
  • cancel() — отменить текущую установку и очистить очередь.
  • isRunning(), isQueued(id), versionId().
  • Для панели прогресса: stage(), currentFile(), bytesDone(), bytesTotal(), fraction() (от 0 до 1; −1, если общий объём неизвестен).

Сигналы: started(id), progressChanged() (не чаще раза в 100 мс), finished(id), failed(id, message), canceled(id).

started испускается один раз на всю серию установок из очереди. finished испускается для каждой версии.

Как идёт установка

  1. Описание версии. У VersionManifestService берётся ссылка на <id>.json, файл скачивается, sha1 сверяется с манифестом, и файл сохраняется в versions/<id>/. Если версии в манифесте нет (профиль модлоадера) или сеть недоступна, берётся файл, который уже лежит на диске. Если нет и его, установка падает.
  2. Родитель. Если в описании есть inheritsFrom, а родителя на диске нет, текущая версия уступает место: в начало очереди встают сначала родитель, потом она сама. Глубина цепочки — до 10 звеньев.
  3. Список файлов. VersionLoader::load() сводит цепочку, и из результата составляется список: клиентский jar, все библиотеки, индекс ресурсов и конфиг логов. Ссылки не по https и библиотеки без адреса пропускаются с предупреждением.
  4. Загрузка. До 8 файлов одновременно. Каждый пишется потоком в QSaveFile, sha1 считается на ходу. При временной ошибке (таймаут, обрыв, HTTP 429 или 5xx) и при несовпадении хеша файл ставится обратно в начало очереди с паузой 400 мс, потом 800 мс. После третьей неудачи установка падает. Другие ошибки сразу её прерывают. Таймаут на файл 30 секунд.
  5. Ресурсы. Как только индекс ресурсов на диске, он разворачивается в задачи на загрузку из resources.download.minecraft.net/<xx>/<hash>. До этого момента в общем объёме учитывается totalSize из описания версии, а потом он заменяется точной суммой.
  6. Старые ресурсы. У версий до 1.6 (virtual, map_to_resources, assets = legacy или pre-1.6) игра ищет ресурсы не в assets/objects, а в обычной папке с именами файлов. Они копируются в assets/virtual/legacy/ или в resources/ по 64 файла за такт таймера, чтобы окно не подвисало.
  7. Проверка. GameLauncher::missingFiles(). Если чего-то нет, это ошибка.

Уже скачанные файлы

Существующий файл считается целым, если его размер совпадает с ожидаемым (или размер неизвестен). Хеш не пересчитывается: перехеширование сотен мегабайт ресурсов при каждой установке обходится дороже, чем редкий битый файл. Для будущей кнопки «Проверить файлы» есть флаг m_verifyExisting, сейчас он всегда false.

Пропуск файлов идёт пачками по 256 за такт. Иначе установка версии, у которой уже есть все ресурсы, повесила бы окно на перебор десятков тысяч записей.

Ошибки и отмена

При ошибке все активные загрузки обрываются, недописанные файлы откатываются (QSaveFile), а очередь очищается: остальные версии из неё тоже не поставятся. К тексту ошибки добавляются до трёх накопленных предупреждений.

Отмена обрывает активные запросы и ждёт, пока все они вернутся. Только после этого приходит canceled. Пока отмена не закончилась, install() отвечает отказом.

Деструктор блокирует сигналы и отменяет установку.


При создании этого документа использовался ИИ.