#pragma once #include "javaruntime.h" #include #include #include #include #include #include class QNetworkAccessManager; // Каталог сборок Java, которые лаунчер умеет скачать: качает, кэширует в папке // лаунчера и отдаёт из кэша, пока тот не устарел. Устроен как // VersionManifestService и работает в GUI-потоке. // // Источников два и они дополняют друг друга: // // * Mojang (категория «Java») — ровно тот рантайм, которым запускает игру // официальный лаунчер. Версий немного, зато они заведомо совместимы. // // * Eclipse Temurin (категории JDK и JRE) — свежие сборки всех мажорных // версий, включая те, до которых Mojang ещё не дошёл. // // Отдаются только сборки под текущие ОС и архитектуру: выбрать заведомо // неработающую нечем. Исключение — macOS на Apple Silicon, где под Java 8 и 16 // сборок aarch64 нет вовсе и приходится брать x64 (работает через Rosetta). class JavaRuntimeService : public QObject { Q_OBJECT public: // ok = true и непустой warning — данные отдали из устаревшего кэша. using Callback = std::function; explicit JavaRuntimeService(QObject *parent = nullptr); void ensureLoaded(Callback callback, bool forceRefresh = false); // Новые версии сверху. QList entries(JavaRuntimeKind kind) const; std::optional find(const QString &id) const; bool isRefreshing() const { return m_outstanding > 0; } bool hasData() const { return !m_entries.isEmpty(); } signals: void catalogChanged(); void refreshingChanged(); private: void startRefresh(); void requestAdoptiumReleases(); // allowFallback — на macOS/aarch64 разрешено переспросить сборку под x64. void requestFeatureRelease(int major, const QString &architecture, bool allowFallback); void requestMojangRuntimes(); // Общий хвост любого запроса: считает незавершённые и, когда их не // осталось, применяет накопленное. void requestFinished(const QString &warning); void finishRefresh(); static QList parseAdoptium(const QByteArray &payload, const QSet <sVersions); static QList parseMojang(const QByteArray &payload); void applyEntries(QList list); bool readCache(); void writeCache(); QNetworkAccessManager *m_network; QList m_entries; QHash m_indexById; QDateTime m_fetchedAt; bool m_cacheRead = false; // Накопитель одного обновления: ответы приходят вразнобой, каталог // подменяется целиком и только когда пришли все. QList m_incoming; QStringList m_warnings; QSet m_ltsVersions; int m_outstanding = 0; QList m_pending; };