Files
minecraft-launcher/doc/cpp/GameLauncher.md
T
2026-09-03 09:16:56 +03:00

13 KiB
Raw Blame History

GameLauncher

Обзор класса

GameLauncher — то, ради чего существует весь остальной лаунчер: он готовит и запускает JVM с Minecraft. К моменту его вызова уже известно всё — версия разобрана, файлы скачаны, пользователь авторизован, — и класс превращает это в командную строку и дочерний процесс.

Кроме самого запуска класс умеет проверять комплектность .minecraft и распаковывать нативные библиотеки, без которых игра не стартует.

Один экземпляр — одна игра одновременно.

Место в проекте и зависимости

Подключает minecraftversion.h: разобранная версия — половина входных данных запуска, вторая половина приходит структурой LaunchOptions из этого же заголовка.

Экземпляр создаётся и принадлежит LauncherBackend, который заполняет 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 с учётом требования версии.

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 или MsaAuthService. Разобранную версию он получает через VersionLoader::load() из minecraftversion.h.

Все четыре сигнала бэкенд переправляет в QML: progress и gameFinished попадают в плашку сообщений главного окна, output — в консоль, а gameStarted меняет признак gameRunning.

Статический missingFiles() вызывается отдельно от запуска — из метода проверки комплектности сборки, результат которого показывает BuildsDialog.

Внешнее взаимодействие

Дочерний процесс. Класс запускает java через QProcess. Аргументы собираются buildArguments(); для профилей Ely.by в них добавляется -javaagent с путём к authlib-injector. Стандартный вывод процесса читается построчно и отдаётся сигналом output, завершение — сигналом gameFinished. Направление обмена одностороннее: лаунчер запускает процесс и читает его вывод, ничего не передавая обратно после старта.

Все сигналы процесса приходят в поток GUI.

Пример использования

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);

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