Files
minecraft-launcher/modloaderinstaller.h
2026-08-28 00:13:59 +03:00

125 lines
5.2 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include "modloader.h"
#include <QObject>
#include <QString>
#include <QStringList>
class QFile;
class QNetworkAccessManager;
class QNetworkReply;
class QProcess;
class ModLoaderVersionService;
class VersionInstaller;
// Установка модлоадера в .minecraft. Два разных пути под одним фасадом:
//
// * Fabric и Quilt отдают готовое описание версии — кладём его в
// versions/<id>/<id>.json и передаём дальше VersionInstaller, который по
// inheritsFrom сам поставит ванильную версию и библиотеки лоадера.
//
// * Forge и NeoForge так не умеют: их установка — это патч клиентского jar,
// поэтому запускаем официальный installer.jar найденной Java в headless-режиме
// и смотрим, какой профиль появился в versions. Процессу установщика при этом
// подсовывается эталонный zlib — см. ZlibReference.
//
// Оба пути начинаются одинаково: пока ванильная версия не скачана целиком,
// ставить лоадер некуда, поэтому ensureBaseVersion стоит перед обеими ветками.
//
// Набор геттеров повторяет VersionInstaller: панель загрузки в интерфейсе
// читает их одинаково, независимо от того, кто сейчас работает.
class ModLoaderInstaller : public QObject
{
Q_OBJECT
public:
ModLoaderInstaller(ModLoaderVersionService *meta,
VersionInstaller *versionInstaller,
QObject *parent = nullptr);
~ModLoaderInstaller() override;
bool isRunning() const { return m_running; }
QString label() const { return m_label; }
QString stage() const { return m_stage; }
QString currentFile() const { return m_currentFile; }
qint64 bytesDone() const { return m_bytesDone; }
qint64 bytesTotal() const { return m_bytesTotal; }
double fraction() const; // 0..1, либо -1 пока итог неизвестен
void install(const QString &gameDir,
ModLoader loader,
const QString &gameVersion,
const QString &loaderVersion,
const QString &javaPreference);
void cancel();
signals:
void started(const QString &label);
void progressChanged();
void finished(const QString &loaderKey,
const QString &gameVersion,
const QString &loaderVersion,
const QString &producedVersionId);
void failed(const QString &label, const QString &message);
void canceled(const QString &label);
void log(const QString &line);
private:
void beginFabricLike();
void beginInstallerJar();
void ensureBaseVersion(std::function<void()> next);
void downloadInstaller(const QUrl &url, std::function<void(const QString &)> next);
bool writeLauncherProfilesStub();
void runInstaller(const QString &installerPath);
void handleInstallerFinished(int exitCode, bool crashed);
QStringList versionsAddedByInstaller() const;
void removeVersionsAddedByInstaller();
QString installerFailureHint() const;
void appendInstallerLog(const QString &line);
void closeInstallerLog();
void handOffToVersionInstaller(const QString &versionId);
void setStage(const QString &stage);
void reset();
void fail(const QString &message);
ModLoaderVersionService *m_meta;
VersionInstaller *m_versionInstaller;
QNetworkAccessManager *m_network;
QNetworkReply *m_reply = nullptr;
QProcess *m_process = nullptr;
QString m_gameDir;
ModLoader m_loader = ModLoader::Fabric;
QString m_gameVersion;
QString m_loaderVersion;
QString m_javaPreference;
QString m_label;
QString m_stage;
QString m_currentFile;
qint64 m_bytesDone = 0;
qint64 m_bytesTotal = 0;
// Профили, которые были в versions до запуска installer.jar: новый ищем
// разницей, а не угадыванием строки — id у Forge разные по эпохам.
QStringList m_versionsBefore;
QStringList m_installerLog;
// Установщик успел отработать — значит, за появившиеся в versions папки
// отвечаем мы и при неудаче их надо убрать.
bool m_installerStarted = false;
// В системе zlib-ng, а подменить его было нечем: почти наверняка причина
// расхождения sha1, о которой стоит сказать прямым текстом.
bool m_zlibNgUnpatched = false;
QFile *m_installerLogFile = nullptr;
QString m_installerLogPath;
// Ждём, пока VersionInstaller докачает то, что установщик не положил.
QString m_awaitingVersionId;
bool m_running = false;
bool m_canceling = false;
};