9.3 KiB
VersionManifestService
Обзор класса
Каталог версий Minecraft — это манифест Mojang: около тысячи записей от альф 2010 года до
свежайших снапшотов. VersionManifestService отвечает за него целиком: скачивает манифест,
кэширует в папке лаунчера и отдаёт из кэша, пока тот не устарел.
Класс нужен двум потребителям: окну выбора версии, которому нужен весь список, и установщику, которому по идентификатору версии нужна ссылка на её описание.
Место в проекте и зависимости
Экземпляр создаётся и принадлежит LauncherBackend. Ссылку на него получает VersionInstaller — установщик берёт из манифеста адрес описания версии.
Путь к файлу кэша даёт LauncherPaths::versionManifestFile() из
launcherpaths.h.
Требования сборки: Qt6::Core (QDateTime, QHash, QList, QUrl) и Qt6::Network
(QNetworkAccessManager).
Иерархия и роль
Наследует QObject: мета-объектная система, два сигнала и владение по родителю. Виртуальных
методов базового класса не переопределяет.
Публичные структуры
RemoteVersionEntry
Одна строка манифеста Mojang.
| Поле | Тип | Описание |
|---|---|---|
id |
QString |
Идентификатор версии: 1.21.8, 25w33a, b1.7.3 |
type |
QString |
Категория: release, snapshot, old_beta или old_alpha |
url |
QUrl |
Адрес <id>.json с описанием версии |
sha1 |
QString |
Контрольная сумма самого описания |
releaseTime |
QDateTime |
Дата выпуска; по ней список сортируется новыми вперёд |
Категории type — те же ключи, по которым окно выбора версии делит каталог на вкладки; версии, не
попавшие ни в одну из четырёх, интерфейс относит к категории «прочие».
Псевдонимы типов
VersionManifestService::Callback — std::function<void(bool ok, const QString &warning)>.
Сочетание ok == true с непустым warning означает особый случай: данные отдали, но из
устаревшего кэша — сеть недоступна, а показать что-то нужно.
Публичные методы
explicit VersionManifestService(QObject *parent = nullptr)
Создаёт сервис и его QNetworkAccessManager. Манифест при этом не читается — чтение кэша
откладывается до первого обращения. Конструктор помечен explicit.
QList<RemoteVersionEntry> versions() const
Текущий список версий. Возвращает копию; пустой список означает, что данных ещё нет.
bool hasData() const
Есть ли хоть какие-то данные — из сети или из кэша.
bool isRefreshing() const
Идёт ли сейчас сетевое обновление. Интерфейс показывает по этому признаку строку загрузки вместо пустого списка.
QDateTime fetchedAt() const
Когда данные были получены. По этой отметке решается, устарел ли кэш.
std::optional<RemoteVersionEntry> find(const QString &id) const
Запись по идентификатору версии; std::nullopt, если такой версии в манифесте нет. Из неё
установщик берёт ссылку на описание версии. Поиск идёт по внутреннему указателю, а не перебором.
void ensureLoaded(Callback callback, bool forceRefresh = false)
Единственная точка входа. Свежий кэш означает отложенный вызов колбэка без обращения к сети; иначе запускается один сетевой запрос на всех, кто успел попросить, — колбэки накапливаются и вызываются все разом по его завершении.
Параметр forceRefresh обходит проверку свежести кэша: так работает кнопка принудительного
обновления.
Колбэк вызывается ровно один раз и всегда в потоке GUI, в том числе когда данные уже есть.
Сигналы
versionsChanged()
Список версий изменился — пришли новые данные из сети или прочитан кэш.
Обработчик перечитывает versions() и обновляет интерфейс. В лаунчере на этот сигнал завязано
свойство каталога версий, которое читает окно выбора.
refreshingChanged()
Изменился признак сетевого обновления. Обработчик показывает или убирает индикатор загрузки.
Владение и время жизни
Класс наследует QObject и принимает parent — родитель его и удалит.
QNetworkAccessManager создаётся в конструкторе с сервисом в роли родителя.
Отложенные колбэки хранятся в списке до завершения текущего запроса. Уничтожение сервиса с незавершённым запросом обрывает его вместе с менеджером сети, и накопленные колбэки не вызываются.
Ссылку на сервис держит установщик версий; уничтожать сервис раньше установщика нельзя.
Потокобезопасность
Только поток GUI — так же, как AuthService. Чтение и запись кэша выполняются в вызывающем потоке, поэтому первое обращение к манифесту делает короткую файловую операцию синхронно.
Взаимодействие с другими классами
LauncherBackend вызывает ensureLoaded() при открытии окна выбора версии и по кнопке
обновления, а сигналы versionsChanged и refreshingChanged переправляет в свойства, которые
читает QML. Список из versions() он сводит с установленными версиями и отдаёт в интерфейс уже
готовыми строками.
VersionInstaller обращается к find(), чтобы получить адрес описания
версии перед началом загрузки.
Внешнее взаимодействие
Сеть, исходящие запросы. Класс скачивает манифест версий Mojang через
QNetworkAccessManager. Формат — JSON поверх HTTPS, запрос инициирует лаунчер.
Стратегия при недоступной сети встроена в контракт колбэка: если есть устаревший кэш, он
отдаётся с ok == true и заполненным warning, и интерфейс показывает список вместо ошибки.
Полное отсутствие данных даёт ok == false.
Файловый кэш. Манифест сохраняется в файл, путь к которому даёт
LauncherPaths::versionManifestFile(), вместе с отметкой времени получения.
Сигналы и колбэки приходят в поток GUI.
Пример использования
auto *manifest = new VersionManifestService(this);
connect(manifest, &VersionManifestService::versionsChanged, this, &Backend::rebuildCatalog);
manifest->ensureLoaded([this, manifest](bool ok, const QString &warning) {
if (!ok) {
emit catalogError(warning);
return;
}
if (!warning.isEmpty())
showStatus(warning); // список из устаревшего кэша
const auto entry = manifest->find(QStringLiteral("1.21.8"));
if (entry)
startDownload(entry->url);
});
При создании этого документа использовался ИИ.