#pragma once #include "modloader.h" #include #include #include class QNetworkAccessManager; class QNetworkReply; class QProcess; class ModLoaderVersionService; class VersionInstaller; // Установка модлоадера в .minecraft. Два разных пути под одним фасадом: // // * Fabric и Quilt отдают готовое описание версии — кладём его в // versions//.json и передаём дальше VersionInstaller, который по // inheritsFrom сам поставит ванильную версию и библиотеки лоадера. // // * Forge и NeoForge так не умеют: их установка — это патч клиентского jar, // поэтому запускаем официальный installer.jar найденной Java в headless-режиме // и смотрим, какой профиль появился в versions. // // Набор геттеров повторяет 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 next); void downloadInstaller(const QUrl &url, std::function next); bool writeLauncherProfilesStub(); void runInstaller(const QString &installerPath); void handleInstallerFinished(int exitCode, bool crashed); 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; // Ждём, пока VersionInstaller докачает то, что установщик не положил. QString m_awaitingVersionId; bool m_running = false; bool m_canceling = false; };