From 8f2f4f06afbecad97c4960752f79e476927a3731 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Wed, 7 May 2025 20:01:01 -0400 Subject: [PATCH] Overhaul asset updating for Wine and DXVK, make URLs configurable This used to be just be a hardcoded URL (I know, I know...) but now it fetches the latest release from each repository. To make it even more future-proof, the URLs of the repositories and even the GitHub API used to fetch them is configurable. UI to expose that will come in the next commit. --- launcher/config.kcfg | 9 ++++ launcher/include/assetupdater.h | 8 ++-- launcher/src/assetupdater.cpp | 85 +++++++++++++++++++++++++++++---- 3 files changed, 88 insertions(+), 14 deletions(-) diff --git a/launcher/config.kcfg b/launcher/config.kcfg index 2e19859..72afbd9 100644 --- a/launcher/config.kcfg +++ b/launcher/config.kcfg @@ -45,5 +45,14 @@ SPDX-License-Identifier: CC0-1.0 false + + doitsujin/dxvk + + + goatcorp/wine-xiv-git + + + api.github.com + diff --git a/launcher/include/assetupdater.h b/launcher/include/assetupdater.h index 6ea6d71..ba74912 100644 --- a/launcher/include/assetupdater.h +++ b/launcher/include/assetupdater.h @@ -38,6 +38,8 @@ private: [[nodiscard]] QUrl dalamudAssetManifestUrl() const; [[nodiscard]] QUrl dotnetRuntimePackageUrl(const QString &version) const; [[nodiscard]] QUrl dotnetDesktopPackageUrl(const QString &version) const; + [[nodiscard]] QUrl dxvkReleasesUrl() const; + [[nodiscard]] QUrl wineReleasesUrl() const; static bool extractZip(const QString &filePath, const QString &directory); @@ -60,11 +62,9 @@ private: QString m_remoteDalamudDownloadUrl; QString m_remoteDalamudAssetPackageUrl; QString m_remoteCompatibilityToolVersion; + QString m_remoteCompatibilityToolUrl; QString m_remoteDxvkToolVersion; - // TODO: hardcoded - QString m_remoteCompatibilityToolUrl = - QStringLiteral("https://github.com/goatcorp/wine-xiv-git/releases/download/8.5.r4.g4211bac7/wine-xiv-staging-fsync-git-ubuntu-8.5.r4.g4211bac7.tar.xz"); - QString m_remoteDxvkToolUrl = QStringLiteral("https://github.com/doitsujin/dxvk/releases/download/v2.3/dxvk-2.3.tar.gz"); + QString m_remoteDxvkToolUrl; Profile &m_profile; }; diff --git a/launcher/src/assetupdater.cpp b/launcher/src/assetupdater.cpp index 2fe6431..c259b02 100644 --- a/launcher/src/assetupdater.cpp +++ b/launcher/src/assetupdater.cpp @@ -81,8 +81,37 @@ QCoro::Task AssetUpdater::update() QCoro::Task AssetUpdater::checkRemoteCompatibilityToolVersion() { - // TODO: hardcoded for now - m_remoteCompatibilityToolVersion = QStringLiteral("wine-xiv-staging-fsync-git-8.5.r4.g4211bac7"); + const QNetworkRequest request(wineReleasesUrl()); + Utility::printRequest(QStringLiteral("GET"), request); + + const auto reply = co_await launcher.mgr()->get(request); + if (reply->error() != QNetworkReply::NetworkError::NoError) { + Q_EMIT launcher.miscError(i18n("Could not check for the latest compatibility tool version.\n\n%1", reply->errorString())); + co_return false; + } + + const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll()); + const QJsonArray releases = doc.array(); + const QJsonObject latestRelease = releases.first().toObject(); + + if (latestRelease.contains("tag_name"_L1)) { + m_remoteCompatibilityToolVersion = latestRelease["tag_name"_L1].toString(); + } else if (latestRelease.contains("name"_L1)) { + m_remoteCompatibilityToolVersion = latestRelease["name"_L1].toString(); + } else { + m_remoteCompatibilityToolVersion = latestRelease["commit"_L1].toObject()["sha"_L1].toString(); + } + + for (auto asset : latestRelease["assets"_L1].toArray()) { + if (asset["name"_L1].toString().contains("ubuntu"_L1)) { + m_remoteCompatibilityToolUrl = asset["browser_download_url"_L1].toString(); + } + } + + // fallback to first asset just in case + if (m_remoteCompatibilityToolUrl.isEmpty()) { + m_remoteCompatibilityToolUrl = latestRelease["assets"_L1].toArray().first()["browser_download_url"_L1].toString(); + } qInfo(ASTRA_LOG) << "Compatibility tool remote version" << m_remoteCompatibilityToolVersion; @@ -98,8 +127,27 @@ QCoro::Task AssetUpdater::checkRemoteCompatibilityToolVersion() QCoro::Task AssetUpdater::checkRemoteDxvkVersion() { - // TODO: hardcoded for now - m_remoteDxvkToolVersion = QStringLiteral("dxvk-2.3"); + const QNetworkRequest request(dxvkReleasesUrl()); + Utility::printRequest(QStringLiteral("GET"), request); + + const auto reply = co_await launcher.mgr()->get(request); + if (reply->error() != QNetworkReply::NetworkError::NoError) { + Q_EMIT launcher.miscError(i18n("Could not check for the latest DXVK version.\n\n%1", reply->errorString())); + co_return false; + } + + const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll()); + const QJsonArray releases = doc.array(); + const QJsonObject latestRelease = releases.first().toObject(); + + if (latestRelease.contains("tag_name"_L1)) { + m_remoteDxvkToolVersion = latestRelease["tag_name"_L1].toString(); + } else if (latestRelease.contains("name"_L1)) { + m_remoteDxvkToolVersion = latestRelease["name"_L1].toString(); + } else { + m_remoteDxvkToolVersion = latestRelease["commit"_L1].toObject()["sha"_L1].toString(); + } + m_remoteDxvkToolUrl = latestRelease["assets"_L1].toArray().first()["browser_download_url"_L1].toString(); qInfo(ASTRA_LOG) << "DXVK remote version" << m_remoteDxvkToolVersion; @@ -231,8 +279,7 @@ QCoro::Task AssetUpdater::installCompatibilityTool() const co_return false; } - // the first directory is the same as the version we download - const auto *root = dynamic_cast(archive.directory()->entry(m_remoteCompatibilityToolVersion)); + const auto *root = dynamic_cast(archive.directory()->entry(archive.directory()->entries().first())); Q_UNUSED(root->copyTo(m_wineDir.absolutePath(), true)) archive.close(); @@ -251,8 +298,7 @@ QCoro::Task AssetUpdater::installDxvkTool() const const auto request = QNetworkRequest(QUrl(m_remoteDxvkToolUrl)); Utility::printRequest(QStringLiteral("GET"), request); - const auto reply = launcher.mgr()->get(request); - co_await reply; + const auto reply = co_await launcher.mgr()->get(request); qInfo(ASTRA_LOG) << "Finished downloading DXVK"; @@ -273,8 +319,7 @@ QCoro::Task AssetUpdater::installDxvkTool() const co_return false; } - // the first directory is the same as the version we download - const auto *root = dynamic_cast(archive.directory()->entry(m_remoteDxvkToolVersion)); + const auto *root = dynamic_cast(archive.directory()->entry(archive.directory()->entries().first())); Q_UNUSED(root->copyTo(m_dxvkDir.absolutePath(), true)) archive.close(); @@ -435,6 +480,26 @@ QUrl AssetUpdater::dotnetDesktopPackageUrl(const QString &version) const return url; } +QUrl AssetUpdater::dxvkReleasesUrl() const +{ + QUrl url; + url.setScheme(launcher.config()->preferredProtocol()); + url.setHost(launcher.config()->githubApi()); + url.setPath(QStringLiteral("/repos/%1/releases").arg(launcher.config()->dXVKRepository())); + + return url; +} + +QUrl AssetUpdater::wineReleasesUrl() const +{ + QUrl url; + url.setScheme(launcher.config()->preferredProtocol()); + url.setHost(launcher.config()->githubApi()); + url.setPath(QStringLiteral("/repos/%1/releases").arg(launcher.config()->wineRepository())); + + return url; +} + bool AssetUpdater::extractZip(const QString &filePath, const QString &directory) { KZip archive(filePath);