new docs for project
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
# JavaRuntimeService
|
||||
|
||||
## Обзор класса
|
||||
|
||||
`JavaRuntimeService` — каталог сборок Java, которые лаунчер умеет скачать: качает, кэширует в
|
||||
папке лаунчера и отдаёт из кэша, пока тот не устарел. Устроен так же, как
|
||||
[VersionManifestService](VersionManifestService.md).
|
||||
|
||||
Источников два, и они дополняют друг друга. **Mojang** (категория «Java») — ровно тот рантайм,
|
||||
которым запускает игру официальный лаунчер: версий немного, зато они заведомо совместимы.
|
||||
**Eclipse Temurin** (категории JDK и JRE) — свежие сборки всех мажорных версий, включая те, до
|
||||
которых Mojang ещё не дошёл.
|
||||
|
||||
Отдаются только сборки под текущие операционную систему и архитектуру: выбрать заведомо
|
||||
неработающую нечем. Исключение — macOS на Apple Silicon, где под Java 8 и 16 сборок `aarch64` нет
|
||||
вовсе и приходится брать `x64`, который работает через Rosetta.
|
||||
|
||||
## Место в проекте и зависимости
|
||||
|
||||
Подключает [javaruntime.h](javaruntime.md): перечисление `JavaRuntimeKind` и структура
|
||||
`JavaRuntimeEntry` приходят оттуда.
|
||||
|
||||
Экземпляр создаётся и принадлежит [LauncherBackend](LauncherBackend.md). Записями каталога
|
||||
пользуется [JavaInstaller](JavaInstaller.md).
|
||||
|
||||
Путь к файлу кэша даёт `LauncherPaths::javaCatalogFile()` из [launcherpaths.h](launcherpaths.md).
|
||||
|
||||
Требования сборки: `Qt6::Core` (`QDateTime`, `QHash`, `QSet`) и `Qt6::Network`
|
||||
(`QNetworkAccessManager`).
|
||||
|
||||
## Иерархия и роль
|
||||
|
||||
Наследует `QObject`: мета-объектная система, два сигнала и владение по родителю. Виртуальных
|
||||
методов базового класса не переопределяет.
|
||||
|
||||
## Псевдонимы типов
|
||||
|
||||
`JavaRuntimeService::Callback` — `std::function<void(bool ok, const QString &warning)>`. Как и в
|
||||
остальных каталогах лаунчера, `ok == true` с непустым `warning` означает данные из устаревшего
|
||||
кэша.
|
||||
|
||||
## Публичные методы
|
||||
|
||||
#### explicit JavaRuntimeService(QObject \*parent = nullptr)
|
||||
|
||||
Создаёт сервис и его `QNetworkAccessManager`. Кэш читается лениво. Конструктор помечен `explicit`.
|
||||
|
||||
#### void ensureLoaded(Callback callback, bool forceRefresh = false)
|
||||
|
||||
Единственная точка входа. Свежий кэш означает отложенный вызов колбэка без сети; иначе запускается
|
||||
обновление. Параметр `forceRefresh` обходит проверку свежести — так работает кнопка обновления
|
||||
каталога.
|
||||
|
||||
Одно обновление складывается из нескольких запросов сразу к обоим источникам. Ответы приходят
|
||||
вразнобой, поэтому они накапливаются, и каталог подменяется целиком только когда пришли все.
|
||||
|
||||
#### QList<JavaRuntimeEntry> entries(JavaRuntimeKind kind) const
|
||||
|
||||
Сборки одной категории: `Mojang`, `Jdk` или `Jre`. Новые версии идут первыми.
|
||||
|
||||
#### std::optional<JavaRuntimeEntry> find(const QString &id) const
|
||||
|
||||
Запись по идентификатору сборки; `std::nullopt`, если такой нет. Поиск идёт по внутреннему
|
||||
указателю.
|
||||
|
||||
#### std::optional<JavaRuntimeEntry> bestFor(int major) const
|
||||
|
||||
Что скачать, если для версии игры нужна Java указанной мажорной версии, а подходящей в системе
|
||||
нет.
|
||||
|
||||
Правила выбора: точное совпадение мажорной версии предпочтительнее более новой, а JDK
|
||||
предпочтительнее JRE — установщики Forge и NeoForge иногда требуют инструментов из полного
|
||||
комплекта. `std::nullopt` означает, что предложить нечего.
|
||||
|
||||
#### bool isRefreshing() const
|
||||
|
||||
Идут ли сейчас запросы. Признак остаётся истинным, пока не завершится последний из них.
|
||||
|
||||
#### bool hasData() const
|
||||
|
||||
Есть ли в каталоге хоть что-то — из сети или из кэша.
|
||||
|
||||
## Сигналы
|
||||
|
||||
#### catalogChanged()
|
||||
|
||||
Каталог заменён новыми данными. Испускается один раз за обновление, когда пришли ответы от всех
|
||||
источников, а не по каждому из них.
|
||||
|
||||
Обработчик перечитывает `entries()` для нужных категорий и обновляет интерфейс.
|
||||
|
||||
#### refreshingChanged()
|
||||
|
||||
Изменился признак обновления. Обработчик показывает или убирает индикатор загрузки.
|
||||
|
||||
## Владение и время жизни
|
||||
|
||||
Класс наследует `QObject` и принимает `parent` — родитель его и удалит.
|
||||
`QNetworkAccessManager` создаётся в конструкторе с сервисом в роли родителя.
|
||||
|
||||
Отложенные колбэки хранятся до завершения текущего обновления. Уничтожение сервиса с
|
||||
незавершёнными запросами обрывает их вместе с менеджером сети, и колбэки не вызываются.
|
||||
|
||||
## Потокобезопасность
|
||||
|
||||
Только поток GUI. Чтение и запись кэша выполняются синхронно в вызывающем потоке.
|
||||
|
||||
## Взаимодействие с другими классами
|
||||
|
||||
`LauncherBackend` вызывает `ensureLoaded()` при открытии окна выбора Java и по кнопке обновления,
|
||||
а сигналы переправляет в свойства, которые читает QML. Перед отдачей в интерфейс он сводит записи
|
||||
каталога с уже установленными сборками из `JavaRuntimeStore` — окно выбора показывает статус, не
|
||||
считая ничего само.
|
||||
|
||||
[JavaInstaller](JavaInstaller.md) получает запись каталога и по ней скачивает и распаковывает
|
||||
сборку. `bestFor()` используется, когда для запуска не хватает Java и лаунчер должен сам
|
||||
предложить, что поставить.
|
||||
|
||||
Требования версий игры к Java берутся из пространства имён `JavaRequirement` в
|
||||
[javaruntime.h](javaruntime.md).
|
||||
|
||||
## Внешнее взаимодействие
|
||||
|
||||
**Сеть, исходящие запросы.** Класс обращается к двум внешним каталогам: API Adoptium (сборки
|
||||
Temurin) и списку рантаймов Mojang. Формат обоих — JSON поверх HTTPS, разбор разделён на две
|
||||
функции.
|
||||
|
||||
Запросов на одно обновление несколько: список сборок Temurin запрашивается по мажорным версиям,
|
||||
и на macOS с Apple Silicon неудачный запрос сборки `aarch64` может быть переспрошен для `x64` —
|
||||
это и есть тот самый случай Java 8 и 16.
|
||||
|
||||
Общий счётчик незавершённых запросов сводит их воедино: пока он не обнулился, каталог не
|
||||
подменяется, а предупреждения от отдельных источников накапливаются.
|
||||
|
||||
Все сигналы и колбэки приходят в поток GUI.
|
||||
|
||||
## Пример использования
|
||||
|
||||
```cpp
|
||||
auto *javaCatalog = new JavaRuntimeService(this);
|
||||
connect(javaCatalog, &JavaRuntimeService::catalogChanged, this, &Backend::rebuildJavaCatalog);
|
||||
|
||||
javaCatalog->ensureLoaded([this, javaCatalog](bool ok, const QString &warning) {
|
||||
if (!ok) {
|
||||
emit javaCatalogError(warning);
|
||||
return;
|
||||
}
|
||||
const auto best = javaCatalog->bestFor(version.javaMajor);
|
||||
if (best)
|
||||
emit suggestJavaInstall(best->id, best->version);
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
При создании этого документа использовался ИИ.
|
||||
Reference in New Issue
Block a user