new docs for project
This commit is contained in:
@@ -0,0 +1,200 @@
|
||||
# GameLauncher
|
||||
|
||||
## Обзор класса
|
||||
|
||||
`GameLauncher` — то, ради чего существует весь остальной лаунчер: он готовит и запускает JVM с
|
||||
Minecraft. К моменту его вызова уже известно всё — версия разобрана, файлы скачаны, пользователь
|
||||
авторизован, — и класс превращает это в командную строку и дочерний процесс.
|
||||
|
||||
Кроме самого запуска класс умеет проверять комплектность `.minecraft` и распаковывать нативные
|
||||
библиотеки, без которых игра не стартует.
|
||||
|
||||
Один экземпляр — одна игра одновременно.
|
||||
|
||||
## Место в проекте и зависимости
|
||||
|
||||
Подключает [minecraftversion.h](minecraftversion.md): разобранная версия — половина входных данных
|
||||
запуска, вторая половина приходит структурой `LaunchOptions` из этого же заголовка.
|
||||
|
||||
Экземпляр создаётся и принадлежит [LauncherBackend](LauncherBackend.md), который заполняет
|
||||
`LaunchOptions` из настроек, выбранной сборки и результата авторизации.
|
||||
|
||||
Требования сборки: `Qt6::Core` (`QProcess`, `QStringList`) и `Qt6::CorePrivate` — последний нужен
|
||||
ради `QZipReader`, которым распаковываются нативные библиотеки LWJGL. Зависимость от приватного
|
||||
модуля привязывает проект к конкретной версии Qt; в `CMakeLists.txt` это осознанный выбор, и
|
||||
предупреждение о нём отключено.
|
||||
|
||||
## Иерархия и роль
|
||||
|
||||
Наследует `QObject`: мета-объектная система, четыре сигнала и владение по родителю. Виртуальных
|
||||
методов базового класса не переопределяет.
|
||||
|
||||
## Публичные структуры
|
||||
|
||||
### LaunchOptions
|
||||
|
||||
Всё, что лаунчер знает к моменту нажатия кнопки запуска.
|
||||
|
||||
| Поле | Тип | По умолчанию | Описание |
|
||||
|------|-----|--------------|----------|
|
||||
| `gameDir` | `QString` | — | Папка `.minecraft` |
|
||||
| `versionId` | `QString` | — | Папка в `versions`, которую запускаем |
|
||||
| `playerName` | `QString` | — | Ник игрока из результата авторизации |
|
||||
| `uuid` | `QString` | — | UUID игрока |
|
||||
| `accessToken` | `QString` | — | Токен доступа |
|
||||
| `userType` | `QString` | — | Тип учётной записи: `legacy`, `msa` или `ELYBY` |
|
||||
| `clientToken` | `QString` | — | Токен клиента |
|
||||
| `xuid` | `QString` | — | Идентификатор Xbox; пустое значение заменяется на `0`, как в офлайне |
|
||||
| `javaPath` | `QString` | — | Путь к java; пустое значение означает «искать самим» |
|
||||
| `minMemoryMb` | `int` | `512` | Значение `-Xms` |
|
||||
| `maxMemoryMb` | `int` | `4096` | Значение `-Xmx` |
|
||||
| `extraJvmArgs` | `QStringList` | — | Дополнительные аргументы JVM из настроек |
|
||||
| `windowWidth` | `int` | `0` | Ширина окна игры; `0` — не передавать `--width` и `--height` |
|
||||
| `windowHeight` | `int` | `0` | Высота окна игры |
|
||||
| `fullscreen` | `bool` | `false` | Запускать в полноэкранном режиме |
|
||||
| `serverAddress` | `QString` | — | `host[:port]` для автоматического захода на сервер |
|
||||
| `authlibInjectorPath` | `QString` | — | Путь к `authlib-injector`; пустое значение — не подключать |
|
||||
| `authlibInjectorApi` | `QString` | `ely.by` | Сервер авторизации, на который перенаправляется игра |
|
||||
| `launcherName` | `QString` | `KishkaLauncher` | Имя лаунчера, которое видит игра |
|
||||
| `launcherVersion` | `QString` | `1.0` | Версия лаунчера |
|
||||
|
||||
## Публичные методы
|
||||
|
||||
#### explicit GameLauncher(QObject \*parent = nullptr)
|
||||
|
||||
Создаёт объект. Процесс игры при этом не запускается. Конструктор помечен `explicit`.
|
||||
|
||||
#### bool isRunning() const
|
||||
|
||||
Идёт ли сейчас игра. От этого зависит доступность кнопки запуска в интерфейсе.
|
||||
|
||||
#### static QStringList missingFiles(const LaunchOptions &options, const MinecraftVersion &version, int limit = 12)
|
||||
|
||||
Проверяет `.minecraft` на комплектность и возвращает описания недостающих файлов. Пустой список
|
||||
означает, что всё на месте и сборку можно запускать.
|
||||
|
||||
Параметр `limit` ограничивает длину списка: перечислять все отсутствующие файлы у неустановленной
|
||||
версии бессмысленно, важен сам факт и пара примеров.
|
||||
|
||||
Метод статический, ничего не меняет и вызывается интерфейсом для строки состояния сборки.
|
||||
|
||||
#### static QStringList buildArguments(const LaunchOptions &options, const MinecraftVersion &version, const QString &nativesDir)
|
||||
|
||||
Собирает аргументы ровно в том порядке, в котором их ждёт JVM: сначала аргументы JVM, затем главный
|
||||
класс, затем аргументы игры. Подстановки вида `${...}` из версии заменяются значениями из
|
||||
параметров запуска.
|
||||
|
||||
Метод статический и не имеет побочных эффектов, поэтому годится и для показа собранной командной
|
||||
строки без запуска.
|
||||
|
||||
#### static bool extractNatives(const LaunchOptions &options, const MinecraftVersion &version, const QString &nativesDir, QString \*error)
|
||||
|
||||
Распаковывает файлы `.dll`, `.so` и `.dylib` из нативных библиотек в `<версия>/natives`. Учитывает
|
||||
поле `extractExclude` каждой библиотеки — перечисленные там префиксы не распаковываются.
|
||||
|
||||
Возвращает `false` и заполняет `error` при неудаче. Без этого шага игра не стартует: LWJGL ищет
|
||||
нативные библиотеки именно в этой папке.
|
||||
|
||||
#### bool launch(const LaunchOptions &options, const MinecraftVersion &version, QString \*error)
|
||||
|
||||
Полный цикл запуска: проверка комплектности, распаковка нативных библиотек, поиск java, старт
|
||||
процесса.
|
||||
|
||||
Возвращает `false` и заполняет `error`, если что-то из перечисленного не удалось; `true` означает,
|
||||
что процесс запущен — дальнейшая судьба игры приходит сигналами.
|
||||
|
||||
Путь к java берётся из `options.javaPath`, а при пустом значении ищется через
|
||||
[JavaLocator](javalocator.md) с учётом требования версии.
|
||||
|
||||
#### void terminate()
|
||||
|
||||
Завершает процесс игры. Если игра не запущена, ничего не делает.
|
||||
|
||||
## Сигналы
|
||||
|
||||
#### progress(const QString &message)
|
||||
|
||||
Описание текущего шага подготовки: проверка файлов, распаковка нативных библиотек, поиск java.
|
||||
Обработчик показывает сообщение пользователю — подготовка занимает заметное время.
|
||||
|
||||
#### output(const QString &line)
|
||||
|
||||
Одна строка вывода процесса игры. Обработчик пишет её в журнал; в лаунчере это вывод в консоль.
|
||||
|
||||
#### gameStarted(const QString &commandLine)
|
||||
|
||||
Процесс запущен; в параметре — собранная командная строка целиком. Удобно для диагностики: по ней
|
||||
видно, с какими аргументами и какой java стартовала игра.
|
||||
|
||||
#### gameFinished(int exitCode, bool crashed)
|
||||
|
||||
Игра завершилась. `exitCode` — код выхода процесса, `crashed` отличает аварийное завершение от
|
||||
обычного.
|
||||
|
||||
Обработчик снимает признак «игра идёт», возвращает доступность кнопки запуска и сообщает
|
||||
пользователю итог: ненулевой код или выставленный `crashed` показываются как ошибка.
|
||||
|
||||
## Владение и время жизни
|
||||
|
||||
Класс наследует `QObject` и принимает `parent` — родитель его и удалит.
|
||||
|
||||
Процесс игры хранится в поле `m_process` и создаётся при запуске. Один экземпляр рассчитан ровно
|
||||
на одну игру одновременно: повторный вызов `launch()` при работающем процессе не предусмотрен, и
|
||||
вызывающий код обязан проверять `isRunning()`.
|
||||
|
||||
Дочерний процесс переживает уничтожение объекта не сам по себе — завершать игру перед выходом
|
||||
должен вызывающий код через `terminate()`.
|
||||
|
||||
## Потокобезопасность
|
||||
|
||||
Только поток GUI. `QProcess` привязан к потоку, в котором создан, и все сигналы приходят туда же.
|
||||
Статические методы (`missingFiles()`, `buildArguments()`, `extractNatives()`) состояния не имеют,
|
||||
но выполняют файловый ввод-вывод и на большой версии могут заметно задержать вызывающий поток.
|
||||
|
||||
## Взаимодействие с другими классами
|
||||
|
||||
`LauncherBackend` собирает `LaunchOptions` из трёх источников: настроек лаунчера, описания
|
||||
выбранной сборки и `AuthResult` от [AuthService](AuthService.md) или
|
||||
[MsaAuthService](MsaAuthService.md). Разобранную версию он получает через
|
||||
`VersionLoader::load()` из [minecraftversion.h](minecraftversion.md).
|
||||
|
||||
Все четыре сигнала бэкенд переправляет в QML: `progress` и `gameFinished` попадают в плашку
|
||||
сообщений главного окна, `output` — в консоль, а `gameStarted` меняет признак `gameRunning`.
|
||||
|
||||
Статический `missingFiles()` вызывается отдельно от запуска — из метода проверки комплектности
|
||||
сборки, результат которого показывает [BuildsDialog](../qml/BuildsDialog.md).
|
||||
|
||||
## Внешнее взаимодействие
|
||||
|
||||
**Дочерний процесс.** Класс запускает java через `QProcess`. Аргументы собираются
|
||||
`buildArguments()`; для профилей Ely.by в них добавляется `-javaagent` с путём к
|
||||
`authlib-injector`. Стандартный вывод процесса читается построчно и отдаётся сигналом `output`,
|
||||
завершение — сигналом `gameFinished`. Направление обмена одностороннее: лаунчер запускает процесс
|
||||
и читает его вывод, ничего не передавая обратно после старта.
|
||||
|
||||
Все сигналы процесса приходят в поток GUI.
|
||||
|
||||
## Пример использования
|
||||
|
||||
```cpp
|
||||
auto *launcher = new GameLauncher(this);
|
||||
connect(launcher, &GameLauncher::progress, this, &Backend::showStatus);
|
||||
connect(launcher, &GameLauncher::gameFinished, this, &Backend::onGameFinished);
|
||||
|
||||
LaunchOptions options;
|
||||
options.gameDir = settings.resolvedGameDir;
|
||||
options.versionId = build.resolvedVersionId;
|
||||
options.playerName = auth.playerName;
|
||||
options.uuid = auth.uuid;
|
||||
options.accessToken = auth.accessToken;
|
||||
options.userType = auth.userType;
|
||||
options.maxMemoryMb = settings.maxMemoryMb;
|
||||
|
||||
QString error;
|
||||
if (!launcher->launch(options, version, &error))
|
||||
emit launchError(error);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
При создании этого документа использовался ИИ.
|
||||
Reference in New Issue
Block a user