diff --git a/launcher/java/download/ManifestDownloadTask.cpp b/launcher/java/download/ManifestDownloadTask.cpp index 37dca59da..0a51741a2 100644 --- a/launcher/java/download/ManifestDownloadTask.cpp +++ b/launcher/java/download/ManifestDownloadTask.cpp @@ -39,9 +39,8 @@ void ManifestDownloadTask::executeTask() { setStatus(tr("Downloading Java")); auto download = makeShared(QString("JRE::DownloadJava"), APPLICATION->network()); - auto files = std::make_shared(); - auto action = Net::Download::makeByteArray(m_url, files.get()); + auto [action, files] = Net::Download::makeByteArray(m_url); if (!m_checksum_hash.isEmpty() && !m_checksum_type.isEmpty()) { auto hashType = QCryptographicHash::Algorithm::Sha1; if (m_checksum_type == "sha256") { diff --git a/launcher/minecraft/auth/steps/EntitlementsStep.cpp b/launcher/minecraft/auth/steps/EntitlementsStep.cpp index 35a7de66f..7939b85e7 100644 --- a/launcher/minecraft/auth/steps/EntitlementsStep.cpp +++ b/launcher/minecraft/auth/steps/EntitlementsStep.cpp @@ -31,8 +31,8 @@ void EntitlementsStep::perform() { "Accept", "application/json" }, { "Authorization", QString("Bearer %1").arg(m_data->yggdrasilToken.token).toUtf8() } }; - m_response.reset(new QByteArray()); - m_request = Net::Download::makeByteArray(url, m_response.get()); + auto [request, response] = Net::Download::makeByteArray(url); + m_request = request; m_request->addHeaderProxy(std::make_unique(headers)); m_request->enableAutoRetry(true); @@ -40,19 +40,19 @@ void EntitlementsStep::perform() m_task->setAskRetry(false); m_task->addNetAction(m_request); - connect(m_task.get(), &Task::finished, this, &EntitlementsStep::onRequestDone); + connect(m_task.get(), &Task::finished, this, [this, response] { onRequestDone(response); }); m_task->start(); qDebug() << "Getting entitlements..."; } -void EntitlementsStep::onRequestDone() +void EntitlementsStep::onRequestDone(QByteArray* response) { - qCDebug(authCredentials()) << *m_response; + qCDebug(authCredentials()) << *response; // TODO: check presence of same entitlementsRequestId? // TODO: validate JWTs? - Parsers::parseMinecraftEntitlements(*m_response, m_data->minecraftEntitlement); + Parsers::parseMinecraftEntitlements(*response, m_data->minecraftEntitlement); emit finished(AccountTaskState::STATE_WORKING, tr("Got entitlements")); } diff --git a/launcher/minecraft/auth/steps/EntitlementsStep.h b/launcher/minecraft/auth/steps/EntitlementsStep.h index b6d077004..72f77dabe 100644 --- a/launcher/minecraft/auth/steps/EntitlementsStep.h +++ b/launcher/minecraft/auth/steps/EntitlementsStep.h @@ -1,6 +1,5 @@ #pragma once #include -#include #include "minecraft/auth/AuthStep.h" #include "net/Download.h" @@ -18,11 +17,10 @@ class EntitlementsStep : public AuthStep { QString describe() override; private slots: - void onRequestDone(); + void onRequestDone(QByteArray* response); private: QString m_entitlements_request_id; - std::unique_ptr m_response; Net::Download::Ptr m_request; NetJob::Ptr m_task; }; diff --git a/launcher/minecraft/auth/steps/GetSkinStep.cpp b/launcher/minecraft/auth/steps/GetSkinStep.cpp index 0843b25c6..7b26ca468 100644 --- a/launcher/minecraft/auth/steps/GetSkinStep.cpp +++ b/launcher/minecraft/auth/steps/GetSkinStep.cpp @@ -16,22 +16,22 @@ void GetSkinStep::perform() { QUrl url(m_data->minecraftProfile.skin.url); - m_response.reset(new QByteArray()); - m_request = Net::Download::makeByteArray(url, m_response.get()); + auto [request, response] = Net::Download::makeByteArray(url); + m_request = request; m_request->enableAutoRetry(true); m_task.reset(new NetJob("GetSkinStep", APPLICATION->network())); m_task->setAskRetry(false); m_task->addNetAction(m_request); - connect(m_task.get(), &Task::finished, this, &GetSkinStep::onRequestDone); + connect(m_task.get(), &Task::finished, this, [this, response] { onRequestDone(response); }); m_task->start(); } -void GetSkinStep::onRequestDone() +void GetSkinStep::onRequestDone(QByteArray* response) { if (m_request->error() == QNetworkReply::NoError) - m_data->minecraftProfile.skin.data = *m_response; + m_data->minecraftProfile.skin.data = *response; emit finished(AccountTaskState::STATE_WORKING, tr("Got skin")); } diff --git a/launcher/minecraft/auth/steps/GetSkinStep.h b/launcher/minecraft/auth/steps/GetSkinStep.h index 11a0820fd..2cd74ab92 100644 --- a/launcher/minecraft/auth/steps/GetSkinStep.h +++ b/launcher/minecraft/auth/steps/GetSkinStep.h @@ -1,6 +1,5 @@ #pragma once #include -#include #include "minecraft/auth/AuthStep.h" #include "net/Download.h" @@ -18,10 +17,9 @@ class GetSkinStep : public AuthStep { QString describe() override; private slots: - void onRequestDone(); + void onRequestDone(QByteArray* response); private: - std::unique_ptr m_response; Net::Download::Ptr m_request; NetJob::Ptr m_task; }; diff --git a/launcher/minecraft/auth/steps/LauncherLoginStep.cpp b/launcher/minecraft/auth/steps/LauncherLoginStep.cpp index eb104f4eb..89293c22e 100644 --- a/launcher/minecraft/auth/steps/LauncherLoginStep.cpp +++ b/launcher/minecraft/auth/steps/LauncherLoginStep.cpp @@ -36,8 +36,8 @@ void LauncherLoginStep::perform() { "Accept", "application/json" }, }; - m_response.reset(new QByteArray()); - m_request = Net::Upload::makeByteArray(url, m_response.get(), requestBody.toUtf8()); + auto [request, response] = Net::Upload::makeByteArray(url, requestBody.toUtf8()); + m_request = request; m_request->addHeaderProxy(std::make_unique(headers)); m_request->enableAutoRetry(true); @@ -45,15 +45,15 @@ void LauncherLoginStep::perform() m_task->setAskRetry(false); m_task->addNetAction(m_request); - connect(m_task.get(), &Task::finished, this, &LauncherLoginStep::onRequestDone); + connect(m_task.get(), &Task::finished, this, [this, response] { onRequestDone(response); }); m_task->start(); qDebug() << "Getting Minecraft access token..."; } -void LauncherLoginStep::onRequestDone() +void LauncherLoginStep::onRequestDone(QByteArray* response) { - qCDebug(authCredentials()) << *m_response; + qCDebug(authCredentials()) << *response; if (m_request->error() != QNetworkReply::NoError) { qWarning() << "Reply error:" << m_request->error(); if (Net::isApplicationError(m_request->error())) { @@ -65,7 +65,7 @@ void LauncherLoginStep::onRequestDone() return; } - if (!Parsers::parseMojangResponse(*m_response, m_data->yggdrasilToken)) { + if (!Parsers::parseMojangResponse(*response, m_data->yggdrasilToken)) { qWarning() << "Could not parse login_with_xbox response..."; emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Failed to parse the Minecraft access token response.")); return; diff --git a/launcher/minecraft/auth/steps/LauncherLoginStep.h b/launcher/minecraft/auth/steps/LauncherLoginStep.h index 7ea06ee1e..2501f5707 100644 --- a/launcher/minecraft/auth/steps/LauncherLoginStep.h +++ b/launcher/minecraft/auth/steps/LauncherLoginStep.h @@ -1,6 +1,5 @@ #pragma once #include -#include #include "minecraft/auth/AuthStep.h" #include "net/NetJob.h" @@ -18,10 +17,9 @@ class LauncherLoginStep : public AuthStep { QString describe() override; private slots: - void onRequestDone(); + void onRequestDone(QByteArray* response); private: - std::unique_ptr m_response; Net::Upload::Ptr m_request; NetJob::Ptr m_task; }; diff --git a/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp b/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp index 4cec52599..3feb6852c 100644 --- a/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp +++ b/launcher/minecraft/auth/steps/MSADeviceCodeStep.cpp @@ -66,8 +66,8 @@ void MSADeviceCodeStep::perform() { "Content-Type", "application/x-www-form-urlencoded" }, { "Accept", "application/json" }, }; - m_response.reset(new QByteArray()); - m_request = Net::Upload::makeByteArray(url, m_response.get(), payload); + auto [request, response] = Net::Upload::makeByteArray(url, payload); + m_request = request; m_request->addHeaderProxy(std::make_unique(headers)); m_request->enableAutoRetry(true); @@ -75,7 +75,7 @@ void MSADeviceCodeStep::perform() m_task->setAskRetry(false); m_task->addNetAction(m_request); - connect(m_task.get(), &Task::finished, this, &MSADeviceCodeStep::deviceAuthorizationFinished); + connect(m_task.get(), &Task::finished, this, [this, response] { deviceAuthorizationFinished(response); }); m_task->start(); } @@ -111,9 +111,9 @@ DeviceAuthorizationResponse parseDeviceAuthorizationResponse(const QByteArray& d }; } -void MSADeviceCodeStep::deviceAuthorizationFinished() +void MSADeviceCodeStep::deviceAuthorizationFinished(QByteArray* response) { - auto rsp = parseDeviceAuthorizationResponse(*m_response); + auto rsp = parseDeviceAuthorizationResponse(*response); if (!rsp.error.isEmpty() || !rsp.error_description.isEmpty()) { qWarning() << "Device authorization failed:" << rsp.error; emit finished(AccountTaskState::STATE_FAILED_HARD, @@ -121,7 +121,7 @@ void MSADeviceCodeStep::deviceAuthorizationFinished() return; } if (!m_request->wasSuccessful() || m_request->error() != QNetworkReply::NoError) { - qWarning() << "Device authorization failed:" << *m_response; + qWarning() << "Device authorization failed:" << *response; emit finished(AccountTaskState::STATE_FAILED_HARD, tr("Failed to retrieve device authorization")); return; } @@ -182,11 +182,11 @@ void MSADeviceCodeStep::authenticateUser() { "Content-Type", "application/x-www-form-urlencoded" }, { "Accept", "application/json" }, }; - m_response.reset(new QByteArray()); - m_request = Net::Upload::makeByteArray(url, m_response.get(), payload); + auto [request, response] = Net::Upload::makeByteArray(url, payload); + m_request = request; m_request->addHeaderProxy(std::make_unique(headers)); - connect(m_request.get(), &Task::finished, this, &MSADeviceCodeStep::authenticationFinished); + connect(m_request.get(), &Task::finished, this, [this, response] { authenticationFinished(response); }); m_request->setNetwork(APPLICATION->network()); m_request->start(); @@ -227,7 +227,7 @@ AuthenticationResponse parseAuthenticationResponse(const QByteArray& data) obj.toVariantMap() }; } -void MSADeviceCodeStep::authenticationFinished() +void MSADeviceCodeStep::authenticationFinished(QByteArray* response) { if (m_request->error() == QNetworkReply::TimeoutError) { // rfc8628#section-3.5 @@ -239,7 +239,7 @@ void MSADeviceCodeStep::authenticationFinished() startPoolTimer(); return; } - auto rsp = parseAuthenticationResponse(*m_response); + auto rsp = parseAuthenticationResponse(*response); if (rsp.error == "slow_down") { // rfc8628#section-3.5 // "A variant of 'authorization_pending', the authorization request is diff --git a/launcher/minecraft/auth/steps/MSADeviceCodeStep.h b/launcher/minecraft/auth/steps/MSADeviceCodeStep.h index 62fbbc7a5..cfb8270d4 100644 --- a/launcher/minecraft/auth/steps/MSADeviceCodeStep.h +++ b/launcher/minecraft/auth/steps/MSADeviceCodeStep.h @@ -58,10 +58,10 @@ class MSADeviceCodeStep : public AuthStep { void authorizeWithBrowser(QString url, QString code, int expiresIn); private slots: - void deviceAuthorizationFinished(); + void deviceAuthorizationFinished(QByteArray* response); void startPoolTimer(); void authenticateUser(); - void authenticationFinished(); + void authenticationFinished(QByteArray* response); private: QString m_clientId; @@ -72,7 +72,6 @@ class MSADeviceCodeStep : public AuthStep { QTimer m_pool_timer; QTimer m_expiration_timer; - std::unique_ptr m_response; Net::Upload::Ptr m_request; NetJob::Ptr m_task; }; diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp index 7331eac31..418c46a0e 100644 --- a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp +++ b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp @@ -21,8 +21,8 @@ void MinecraftProfileStep::perform() { "Accept", "application/json" }, { "Authorization", QString("Bearer %1").arg(m_data->yggdrasilToken.token).toUtf8() } }; - m_response.reset(new QByteArray()); - m_request = Net::Download::makeByteArray(url, m_response.get()); + auto [request, response] = Net::Download::makeByteArray(url); + m_request = request; m_request->addHeaderProxy(std::make_unique(headers)); m_request->enableAutoRetry(true); @@ -30,12 +30,12 @@ void MinecraftProfileStep::perform() m_task->setAskRetry(false); m_task->addNetAction(m_request); - connect(m_task.get(), &Task::finished, this, &MinecraftProfileStep::onRequestDone); + connect(m_task.get(), &Task::finished, this, [this, response] { onRequestDone(response); }); m_task->start(); } -void MinecraftProfileStep::onRequestDone() +void MinecraftProfileStep::onRequestDone(QByteArray* response) { if (m_request->error() == QNetworkReply::ContentNotFoundError) { // NOTE: Succeed even if we do not have a profile. This is a valid account state. @@ -50,7 +50,7 @@ void MinecraftProfileStep::onRequestDone() qWarning() << " Error string :" << m_request->errorString(); qWarning() << " Response:"; - qWarning() << QString::fromUtf8(*m_response); + qWarning() << QString::fromUtf8(*response); if (Net::isApplicationError(m_request->error())) { emit finished(AccountTaskState::STATE_FAILED_SOFT, @@ -61,7 +61,7 @@ void MinecraftProfileStep::onRequestDone() } return; } - if (!Parsers::parseMinecraftProfile(*m_response, m_data->minecraftProfile)) { + if (!Parsers::parseMinecraftProfile(*response, m_data->minecraftProfile)) { m_data->minecraftProfile = MinecraftProfile(); emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Minecraft Java profile response could not be parsed")); return; diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStep.h b/launcher/minecraft/auth/steps/MinecraftProfileStep.h index d6de74731..5348f5ba1 100644 --- a/launcher/minecraft/auth/steps/MinecraftProfileStep.h +++ b/launcher/minecraft/auth/steps/MinecraftProfileStep.h @@ -1,6 +1,5 @@ #pragma once #include -#include #include "minecraft/auth/AuthStep.h" #include "net/Download.h" @@ -18,10 +17,9 @@ class MinecraftProfileStep : public AuthStep { QString describe() override; private slots: - void onRequestDone(); + void onRequestDone(QByteArray* response); private: - std::unique_ptr m_response; Net::Download::Ptr m_request; NetJob::Ptr m_task; }; diff --git a/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp b/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp index 3de93bdc7..9e101d42a 100644 --- a/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp +++ b/launcher/minecraft/auth/steps/XboxAuthorizationStep.cpp @@ -42,8 +42,8 @@ void XboxAuthorizationStep::perform() { "Accept", "application/json" }, { "x-xbl-contract-version", "1" } }; - m_response.reset(new QByteArray()); - m_request = Net::Upload::makeByteArray(url, m_response.get(), xbox_auth_data.toUtf8()); + auto [request, response] = Net::Upload::makeByteArray(url, xbox_auth_data.toUtf8()); + m_request = request; m_request->addHeaderProxy(std::make_unique(headers)); m_request->enableAutoRetry(true); @@ -51,19 +51,19 @@ void XboxAuthorizationStep::perform() m_task->setAskRetry(false); m_task->addNetAction(m_request); - connect(m_task.get(), &Task::finished, this, &XboxAuthorizationStep::onRequestDone); + connect(m_task.get(), &Task::finished, this, [this, response] { onRequestDone(response); }); m_task->start(); qDebug() << "Getting authorization token for" << m_relyingParty; } -void XboxAuthorizationStep::onRequestDone() +void XboxAuthorizationStep::onRequestDone(QByteArray* response) { - qCDebug(authCredentials()) << *m_response; + qCDebug(authCredentials()) << *response; if (m_request->error() != QNetworkReply::NoError) { qWarning() << "Reply error:" << m_request->error(); if (Net::isApplicationError(m_request->error())) { - if (!processSTSError()) { + if (!processSTSError(*response)) { emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Failed to get authorization for %1 services. Error %2.").arg(m_authorizationKind, m_request->error())); } else { @@ -78,7 +78,7 @@ void XboxAuthorizationStep::onRequestDone() } Token temp; - if (!Parsers::parseXTokenResponse(*m_response, temp, m_authorizationKind)) { + if (!Parsers::parseXTokenResponse(*response, temp, m_authorizationKind)) { emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Could not parse authorization response for access to %1 services.").arg(m_authorizationKind)); return; @@ -95,11 +95,11 @@ void XboxAuthorizationStep::onRequestDone() emit finished(AccountTaskState::STATE_WORKING, tr("Got authorization to access %1").arg(m_relyingParty)); } -bool XboxAuthorizationStep::processSTSError() +bool XboxAuthorizationStep::processSTSError(const QByteArray& response) { if (m_request->error() == QNetworkReply::AuthenticationRequiredError) { QJsonParseError jsonError; - QJsonDocument doc = QJsonDocument::fromJson(*m_response, &jsonError); + QJsonDocument doc = QJsonDocument::fromJson(response, &jsonError); if (jsonError.error) { qWarning() << "Cannot parse error XSTS response as JSON:" << jsonError.errorString(); emit finished(AccountTaskState::STATE_FAILED_SOFT, diff --git a/launcher/minecraft/auth/steps/XboxAuthorizationStep.h b/launcher/minecraft/auth/steps/XboxAuthorizationStep.h index a152ed5e6..9f424c0c3 100644 --- a/launcher/minecraft/auth/steps/XboxAuthorizationStep.h +++ b/launcher/minecraft/auth/steps/XboxAuthorizationStep.h @@ -1,6 +1,5 @@ #pragma once #include -#include #include "minecraft/auth/AuthStep.h" #include "net/NetJob.h" @@ -18,17 +17,16 @@ class XboxAuthorizationStep : public AuthStep { QString describe() override; private: - bool processSTSError(); + bool processSTSError(const QByteArray& response); private slots: - void onRequestDone(); + void onRequestDone(QByteArray* response); private: Token* m_token; QString m_relyingParty; QString m_authorizationKind; - std::unique_ptr m_response; Net::Upload::Ptr m_request; NetJob::Ptr m_task; }; diff --git a/launcher/minecraft/auth/steps/XboxUserStep.cpp b/launcher/minecraft/auth/steps/XboxUserStep.cpp index c13239dd2..97544d09b 100644 --- a/launcher/minecraft/auth/steps/XboxUserStep.cpp +++ b/launcher/minecraft/auth/steps/XboxUserStep.cpp @@ -37,8 +37,8 @@ void XboxUserStep::perform() // https://learn.microsoft.com/en-us/gaming/gdk/_content/gc/reference/live/rest/additional/httpstandardheaders { "x-xbl-contract-version", "1" } }; - m_response.reset(new QByteArray()); - m_request = Net::Upload::makeByteArray(url, m_response.get(), xbox_auth_data.toUtf8()); + auto [request, response] = Net::Upload::makeByteArray(url, xbox_auth_data.toUtf8()); + m_request = request; m_request->addHeaderProxy(std::make_unique(headers)); m_request->enableAutoRetry(true); @@ -46,13 +46,13 @@ void XboxUserStep::perform() m_task->setAskRetry(false); m_task->addNetAction(m_request); - connect(m_task.get(), &Task::finished, this, &XboxUserStep::onRequestDone); + connect(m_task.get(), &Task::finished, this, [this, response] { onRequestDone(response); }); m_task->start(); qDebug() << "First layer of Xbox auth ... commencing."; } -void XboxUserStep::onRequestDone() +void XboxUserStep::onRequestDone(QByteArray* response) { if (m_request->error() != QNetworkReply::NoError) { qWarning() << "Reply error:" << m_request->error(); @@ -65,7 +65,7 @@ void XboxUserStep::onRequestDone() } Token temp; - if (!Parsers::parseXTokenResponse(*m_response, temp, "UToken")) { + if (!Parsers::parseXTokenResponse(*response, temp, "UToken")) { qWarning() << "Could not parse user authentication response..."; emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("Xbox user authentication response could not be understood.")); return; diff --git a/launcher/minecraft/auth/steps/XboxUserStep.h b/launcher/minecraft/auth/steps/XboxUserStep.h index e3c31ae9d..b6330a499 100644 --- a/launcher/minecraft/auth/steps/XboxUserStep.h +++ b/launcher/minecraft/auth/steps/XboxUserStep.h @@ -1,6 +1,5 @@ #pragma once #include -#include #include "minecraft/auth/AuthStep.h" #include "net/NetJob.h" @@ -18,10 +17,9 @@ class XboxUserStep : public AuthStep { QString describe() override; private slots: - void onRequestDone(); + void onRequestDone(QByteArray* response); private: - std::unique_ptr m_response; Net::Upload::Ptr m_request; NetJob::Ptr m_task; }; diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index 2899b4eee..9d3f3e749 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -177,8 +177,7 @@ void ResourceFolderModel::installResourceWithFlameMetadata(QString path, ModPlat ModPlatform::ResourceProvider::FLAME, }; - auto response = std::make_shared(); - auto job = FlameAPI().getProject(vers.addonId.toString(), response.get()); + auto [job, response] = FlameAPI().getProject(vers.addonId.toString()); connect(job.get(), &Task::failed, this, install); connect(job.get(), &Task::aborted, this, install); connect(job.get(), &Task::succeeded, [response, this, &vers, install, &pack] { diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index f563d99ba..d1d4aba3c 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -134,8 +134,7 @@ QList GetModDependenciesTask::getDependenciesForVersion Task::Ptr GetModDependenciesTask::getProjectInfoTask(std::shared_ptr pDep) { auto provider = pDep->pack->provider; - auto responseInfo = std::make_shared(); - auto info = getAPI(provider)->getProject(pDep->pack->addonId.toString(), responseInfo.get()); + auto [info, responseInfo] = getAPI(provider)->getProject(pDep->pack->addonId.toString()); connect(info.get(), &NetJob::succeeded, [this, responseInfo, provider, pDep] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*responseInfo, &parse_error); diff --git a/launcher/modplatform/EnsureMetadataTask.cpp b/launcher/modplatform/EnsureMetadataTask.cpp index e8262e179..1ef3a56c9 100644 --- a/launcher/modplatform/EnsureMetadataTask.cpp +++ b/launcher/modplatform/EnsureMetadataTask.cpp @@ -215,8 +215,7 @@ Task::Ptr EnsureMetadataTask::modrinthVersionsTask() { auto hash_type = ModPlatform::ProviderCapabilities::hashType(ModPlatform::ResourceProvider::MODRINTH).first(); - auto response = std::make_shared(); - auto ver_task = modrinth_api.currentVersions(m_resources.keys(), hash_type, response.get()); + auto [ver_task, response] = modrinth_api.currentVersions(m_resources.keys(), hash_type); // Prevents unfortunate timings when aborting the task if (!ver_task) @@ -267,15 +266,15 @@ Task::Ptr EnsureMetadataTask::modrinthProjectsTask() for (auto const& data : m_tempVersions) addonIds.insert(data.addonId.toString(), data.hash); - auto response = std::make_shared(); Task::Ptr proj_task; + QByteArray* response; if (addonIds.isEmpty()) { qWarning() << "No addonId found!"; } else if (addonIds.size() == 1) { - proj_task = modrinth_api.getProject(*addonIds.keyBegin(), response.get()); + std::tie(proj_task, response) = modrinth_api.getProject(*addonIds.keyBegin()); } else { - proj_task = modrinth_api.getProjects(addonIds.keys(), response.get()); + std::tie(proj_task, response) = modrinth_api.getProjects(addonIds.keys()); } // Prevents unfortunate timings when aborting the task @@ -341,14 +340,12 @@ Task::Ptr EnsureMetadataTask::modrinthProjectsTask() // Flame Task::Ptr EnsureMetadataTask::flameVersionsTask() { - auto response = std::make_shared(); - QList fingerprints; for (auto& murmur : m_resources.keys()) { fingerprints.push_back(murmur.toUInt()); } - auto ver_task = flame_api.matchFingerprints(fingerprints, response.get()); + auto [ver_task, response] = flame_api.matchFingerprints(fingerprints); connect(ver_task.get(), &Task::succeeded, this, [this, response] { QJsonParseError parse_error{}; @@ -417,15 +414,15 @@ Task::Ptr EnsureMetadataTask::flameProjectsTask() } } - auto response = std::make_shared(); Task::Ptr proj_task; + QByteArray* response; if (addonIds.isEmpty()) { qWarning() << "No addonId found!"; } else if (addonIds.size() == 1) { - proj_task = flame_api.getProject(*addonIds.keyBegin(), response.get()); + std::tie(proj_task, response) = flame_api.getProject(*addonIds.keyBegin()); } else { - proj_task = flame_api.getProjects(addonIds.keys(), response.get()); + std::tie(proj_task, response) = flame_api.getProjects(addonIds.keys()); } // Prevents unfortunate timings when aborting the task diff --git a/launcher/modplatform/ResourceAPI.cpp b/launcher/modplatform/ResourceAPI.cpp index f39536d78..067248567 100644 --- a/launcher/modplatform/ResourceAPI.cpp +++ b/launcher/modplatform/ResourceAPI.cpp @@ -18,10 +18,10 @@ Task::Ptr ResourceAPI::searchProjects(SearchArgs&& args, Callback(); auto netJob = makeShared(QString("%1::Search").arg(debugName()), APPLICATION->network()); - netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(search_url), response.get())); + auto [action, response] = Net::ApiDownload::makeByteArray(QUrl(search_url)); + netJob->addNetAction(action); QObject::connect(netJob.get(), &NetJob::succeeded, [this, response, callbacks] { QJsonParseError parse_error{}; @@ -84,9 +84,9 @@ Task::Ptr ResourceAPI::getProjectVersions(VersionSearchArgs&& args, Callback(QString("%1::Versions").arg(args.pack->name), APPLICATION->network()); - auto response = std::make_shared(); - netJob->addNetAction(Net::ApiDownload::makeByteArray(versions_url, response.get())); + auto [action, response] = Net::ApiDownload::makeByteArray(versions_url); + netJob->addNetAction(action); QObject::connect(netJob.get(), &NetJob::succeeded, [this, response, callbacks, args] { QJsonParseError parse_error{}; @@ -148,8 +148,7 @@ Task::Ptr ResourceAPI::getProjectVersions(VersionSearchArgs&& args, Callback&& callbacks) const { - auto response = std::make_shared(); - auto job = getProject(args.pack->addonId.toString(), response.get()); + auto [job, response] = getProject(args.pack->addonId.toString()); QObject::connect(job.get(), &NetJob::succeeded, [this, response, callbacks, args] { auto pack = args.pack; @@ -204,9 +203,8 @@ Task::Ptr ResourceAPI::getDependencyVersion(DependencySearchArgs&& args, Callbac auto versions_url = versions_url_optional.value(); auto netJob = makeShared(QString("%1::Dependency").arg(args.dependency.addonId.toString()), APPLICATION->network()); - auto response = std::make_shared(); - - netJob->addNetAction(Net::ApiDownload::makeByteArray(versions_url, response.get())); + auto [action, response] = Net::ApiDownload::makeByteArray(versions_url); + netJob->addNetAction(action); QObject::connect(netJob.get(), &NetJob::succeeded, [this, response, callbacks, args] { QJsonParseError parse_error{}; @@ -284,17 +282,18 @@ QString ResourceAPI::mapMCVersionToModrinth(Version v) const return verStr; } -Task::Ptr ResourceAPI::getProject(QString addonId, QByteArray* response) const +std::pair ResourceAPI::getProject(QString addonId) const { auto project_url_optional = getInfoURL(addonId); if (!project_url_optional.has_value()) - return nullptr; + return { nullptr, nullptr }; auto project_url = project_url_optional.value(); auto netJob = makeShared(QString("%1::GetProject").arg(addonId), APPLICATION->network()); - netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(project_url), response)); + auto [action, response] = Net::ApiDownload::makeByteArray(QUrl(project_url)); + netJob->addNetAction(action); - return netJob; + return { netJob, response }; } diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index 90b854530..a83adf82c 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -44,6 +44,7 @@ #include #include +#include #include "../Version.h" @@ -112,8 +113,8 @@ class ResourceAPI { public slots: virtual Task::Ptr searchProjects(SearchArgs&&, Callback>&&) const; - virtual Task::Ptr getProject(QString addonId, QByteArray* response) const; - virtual Task::Ptr getProjects(QStringList addonIds, QByteArray* response) const = 0; + virtual std::pair getProject(QString addonId) const; + virtual std::pair getProjects(QStringList addonIds) const = 0; virtual Task::Ptr getProjectInfo(ProjectInfoArgs&&, Callback&&) const; Task::Ptr getProjectVersions(VersionSearchArgs&& args, Callback>&& callbacks) const; diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index d2742ac5f..5b9551484 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -87,9 +87,11 @@ void PackInstallTask::executeTask() NetJob::Ptr netJob{ new NetJob("ATLauncher::VersionFetch", APPLICATION->network()) }; auto searchUrl = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "packs/%1/versions/%2/Configs.json").arg(m_pack_safe_name).arg(m_version_name); - netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl), response.get())); - connect(netJob.get(), &NetJob::succeeded, this, &PackInstallTask::onDownloadSucceeded); + auto [action, response] = Net::ApiDownload::makeByteArray(QUrl(searchUrl)); + netJob->addNetAction(action); + + connect(netJob.get(), &NetJob::succeeded, this, [this, response] { onDownloadSucceeded(response); }); connect(netJob.get(), &NetJob::failed, this, &PackInstallTask::onDownloadFailed); connect(netJob.get(), &NetJob::aborted, this, &PackInstallTask::onDownloadAborted); @@ -97,17 +99,20 @@ void PackInstallTask::executeTask() jobPtr->start(); } -void PackInstallTask::onDownloadSucceeded() +void PackInstallTask::onDownloadSucceeded(QByteArray* responsePtr) { qDebug() << "PackInstallTask::onDownloadSucceeded:" << QThread::currentThreadId(); + + // NOTE(TheKodeToad): moving the response out to avoid it from being destroyed by jobPtr.reset() + QByteArray response = std::move(*responsePtr); jobPtr.reset(); QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from ATLauncher at" << parse_error.offset << "reason:" << parse_error.errorString(); - qWarning() << *response.get(); + qWarning() << response; return; } auto obj = doc.object(); diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.h b/launcher/modplatform/atlauncher/ATLPackInstallTask.h index 695668731..d1ffdfe7d 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.h +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.h @@ -95,7 +95,7 @@ class PackInstallTask : public InstanceTask { virtual void executeTask() override; private slots: - void onDownloadSucceeded(); + void onDownloadSucceeded(QByteArray* responsePtr); void onDownloadFailed(QString reason); void onDownloadAborted(); @@ -125,7 +125,6 @@ class PackInstallTask : public InstanceTask { bool abortable = false; NetJob::Ptr jobPtr; - std::unique_ptr response = std::make_unique(); InstallMode m_install_mode; QString m_pack_name; diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index ae1599f22..3989d0427 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -51,19 +51,19 @@ void Flame::FileResolvingTask::executeTask() } setStatus(tr("Resolving mod IDs...")); setProgress(0, 3); - m_result.reset(new QByteArray()); QStringList fileIds; for (auto file : m_manifest.files) { fileIds.push_back(QString::number(file.fileId)); } - m_task = flameAPI.getFiles(fileIds, m_result.get()); + auto [task, response] = flameAPI.getFiles(fileIds); + m_task = task; auto step_progress = std::make_shared(); - connect(m_task.get(), &Task::succeeded, this, [this, step_progress]() { + connect(m_task.get(), &Task::succeeded, this, [this, response, step_progress]() { step_progress->state = TaskStepState::Succeeded; stepProgress(*step_progress); - netJobFinished(); + netJobFinished(response); }); connect(m_task.get(), &Task::failed, this, [this, step_progress](QString reason) { step_progress->state = TaskStepState::Failed; @@ -108,7 +108,7 @@ ModPlatform::ResourceType getResourceType(int classId) } } -void Flame::FileResolvingTask::netJobFinished() +void Flame::FileResolvingTask::netJobFinished(QByteArray* response) { setProgress(1, 3); // job to check modrinth for blocked projects @@ -116,7 +116,7 @@ void Flame::FileResolvingTask::netJobFinished() QJsonArray array; try { - doc = Json::requireDocument(*m_result); + doc = Json::requireDocument(*response); array = Json::requireArray(doc.object()["data"]); } catch (Json::JsonException& e) { qCritical() << "Non-JSON data returned from the CF API"; @@ -153,19 +153,19 @@ void Flame::FileResolvingTask::netJobFinished() getFlameProjects(); return; } - m_result.reset(new QByteArray()); - m_task = modrinthAPI.currentVersions(hashes, "sha1", m_result.get()); + auto [modrinthTask, modrinthResponse] = modrinthAPI.currentVersions(hashes, "sha1"); + m_task = modrinthTask; (dynamic_cast(m_task.get()))->setAskRetry(false); auto step_progress = std::make_shared(); - connect(m_task.get(), &Task::succeeded, this, [this, step_progress]() { + connect(m_task.get(), &Task::succeeded, this, [this, modrinthResponse, step_progress]() { step_progress->state = TaskStepState::Succeeded; stepProgress(*step_progress); QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*m_result, &parse_error); + QJsonDocument doc = QJsonDocument::fromJson(*modrinthResponse, &parse_error); if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from Modrinth::CurrentVersions at" << parse_error.offset << "reason:" << parse_error.errorString(); - qWarning() << *m_result; + qWarning() << *modrinthResponse; getFlameProjects(); return; @@ -222,22 +222,22 @@ void Flame::FileResolvingTask::netJobFinished() void Flame::FileResolvingTask::getFlameProjects() { setProgress(2, 3); - m_result.reset(new QByteArray()); QStringList addonIds; for (auto file : m_manifest.files) { addonIds.push_back(QString::number(file.projectId)); } - m_task = flameAPI.getProjects(addonIds, m_result.get()); + auto [task, response] = flameAPI.getProjects(addonIds); + m_task = task; auto step_progress = std::make_shared(); - connect(m_task.get(), &Task::succeeded, this, [this, step_progress] { + connect(m_task.get(), &Task::succeeded, this, [this, response, step_progress] { QJsonParseError parse_error{}; - auto doc = QJsonDocument::fromJson(*m_result, &parse_error); + auto doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from Modrinth projects task at" << parse_error.offset << "reason:" << parse_error.errorString(); - qWarning() << *m_result; + qWarning() << *response; return; } diff --git a/launcher/modplatform/flame/FileResolvingTask.h b/launcher/modplatform/flame/FileResolvingTask.h index 681d7660a..21fa53d2d 100644 --- a/launcher/modplatform/flame/FileResolvingTask.h +++ b/launcher/modplatform/flame/FileResolvingTask.h @@ -36,14 +36,13 @@ class FileResolvingTask : public Task { virtual void executeTask() override; protected slots: - void netJobFinished(); + void netJobFinished(QByteArray* response); private: void getFlameProjects(); private: /* data */ Flame::Manifest m_manifest; - std::unique_ptr m_result; Task::Ptr m_task; }; } // namespace Flame diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index dd0fa4e87..b9b5c2207 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -15,7 +15,7 @@ #include "net/ApiUpload.h" #include "net/NetJob.h" -Task::Ptr FlameAPI::matchFingerprints(const QList& fingerprints, QByteArray* response) +std::pair FlameAPI::matchFingerprints(const QList& fingerprints) { auto netJob = makeShared(QString("Flame::MatchFingerprints"), APPLICATION->network()); @@ -29,10 +29,10 @@ Task::Ptr FlameAPI::matchFingerprints(const QList& fingerprints, QByteArra QJsonDocument body(body_obj); auto body_raw = body.toJson(); + auto [action, response] = Net::ApiUpload::makeByteArray(QString(BuildConfig.FLAME_BASE_URL + "/fingerprints"), body_raw); + netJob->addNetAction(action); - netJob->addNetAction(Net::ApiUpload::makeByteArray(QString(BuildConfig.FLAME_BASE_URL + "/fingerprints"), response, body_raw)); - - return netJob; + return { netJob, response }; } QString FlameAPI::getModFileChangelog(int modId, int fileId) @@ -41,11 +41,10 @@ QString FlameAPI::getModFileChangelog(int modId, int fileId) QString changelog; auto netJob = makeShared(QString("Flame::FileChangelog"), APPLICATION->network()); - auto response = std::make_shared(); - netJob->addNetAction(Net::ApiDownload::makeByteArray( + auto [action, response] = Net::ApiDownload::makeByteArray( QString(BuildConfig.FLAME_BASE_URL + "/mods/%1/files/%2/changelog") - .arg(QString::fromStdString(std::to_string(modId)), QString::fromStdString(std::to_string(fileId))), - response.get())); + .arg(QString::fromStdString(std::to_string(modId)), QString::fromStdString(std::to_string(fileId)))); + netJob->addNetAction(action); QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &changelog] { QJsonParseError parse_error{}; @@ -76,9 +75,9 @@ QString FlameAPI::getModDescription(int modId) QString description; auto netJob = makeShared(QString("Flame::ModDescription"), APPLICATION->network()); - auto response = std::make_shared(); - netJob->addNetAction(Net::ApiDownload::makeByteArray( - QString(BuildConfig.FLAME_BASE_URL + "/mods/%1/description").arg(QString::number(modId)), response.get())); + auto [action, response] = + Net::ApiDownload::makeByteArray(QString(BuildConfig.FLAME_BASE_URL + "/mods/%1/description").arg(QString::number(modId))); + netJob->addNetAction(action); QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &description] { QJsonParseError parse_error{}; @@ -103,7 +102,7 @@ QString FlameAPI::getModDescription(int modId) return description; } -Task::Ptr FlameAPI::getProjects(QStringList addonIds, QByteArray* response) const +std::pair FlameAPI::getProjects(QStringList addonIds) const { auto netJob = makeShared(QString("Flame::GetProjects"), APPLICATION->network()); @@ -117,15 +116,15 @@ Task::Ptr FlameAPI::getProjects(QStringList addonIds, QByteArray* response) cons QJsonDocument body(body_obj); auto body_raw = body.toJson(); - - netJob->addNetAction(Net::ApiUpload::makeByteArray(QString(BuildConfig.FLAME_BASE_URL + "/mods"), response, body_raw)); + auto [action, response] = Net::ApiUpload::makeByteArray(QString(BuildConfig.FLAME_BASE_URL + "/mods"), body_raw); + netJob->addNetAction(action); QObject::connect(netJob.get(), &NetJob::failed, [body_raw] { qDebug() << body_raw; }); - return netJob; + return { netJob, response }; } -Task::Ptr FlameAPI::getFiles(const QStringList& fileIds, QByteArray* response) const +std::pair FlameAPI::getFiles(const QStringList& fileIds) const { auto netJob = makeShared(QString("Flame::GetFiles"), APPLICATION->network()); @@ -140,22 +139,24 @@ Task::Ptr FlameAPI::getFiles(const QStringList& fileIds, QByteArray* response) c QJsonDocument body(body_obj); auto body_raw = body.toJson(); - netJob->addNetAction(Net::ApiUpload::makeByteArray(QString(BuildConfig.FLAME_BASE_URL + "/mods/files"), response, body_raw)); + auto [action, response] = Net::ApiUpload::makeByteArray(QString(BuildConfig.FLAME_BASE_URL + "/mods/files"), body_raw); + netJob->addNetAction(action); QObject::connect(netJob.get(), &NetJob::failed, [body_raw] { qDebug() << body_raw; }); - return netJob; + return { netJob, response }; } -Task::Ptr FlameAPI::getFile(const QString& addonId, const QString& fileId, QByteArray* response) const +std::pair FlameAPI::getFile(const QString& addonId, const QString& fileId) const { auto netJob = makeShared(QString("Flame::GetFile"), APPLICATION->network()); - netJob->addNetAction( - Net::ApiDownload::makeByteArray(QUrl(QString(BuildConfig.FLAME_BASE_URL + "/mods/%1/files/%2").arg(addonId, fileId)), response)); + auto [action, response] = + Net::ApiDownload::makeByteArray(QUrl(QString(BuildConfig.FLAME_BASE_URL + "/mods/%1/files/%2").arg(addonId, fileId))); + netJob->addNetAction(action); QObject::connect(netJob.get(), &NetJob::failed, [addonId, fileId] { qDebug() << "Flame API file failure" << addonId << fileId; }); - return netJob; + return { netJob, response }; } QList FlameAPI::getSortingMethods() const @@ -171,25 +172,26 @@ QList FlameAPI::getSortingMethods() const { 8, "GameVersion", QObject::tr("Sort by Game Version") } }; } -Task::Ptr FlameAPI::getCategories(QByteArray* response, ModPlatform::ResourceType type) +std::pair FlameAPI::getCategories(ModPlatform::ResourceType type) { auto netJob = makeShared(QString("Flame::GetCategories"), APPLICATION->network()); - netJob->addNetAction(Net::ApiDownload::makeByteArray( - QUrl(QString(BuildConfig.FLAME_BASE_URL + "/categories?gameId=432&classId=%1").arg(getClassId(type))), response)); + auto [action, response] = Net::ApiDownload::makeByteArray( + QUrl(QString(BuildConfig.FLAME_BASE_URL + "/categories?gameId=432&classId=%1").arg(getClassId(type)))); + netJob->addNetAction(action); QObject::connect(netJob.get(), &Task::failed, [](QString msg) { qDebug() << "Flame failed to get categories:" << msg; }); - return netJob; + return { netJob, response }; } -Task::Ptr FlameAPI::getModCategories(QByteArray* response) +std::pair FlameAPI::getModCategories() { - return getCategories(response, ModPlatform::ResourceType::Mod); + return getCategories(ModPlatform::ResourceType::Mod); } -QList FlameAPI::loadModCategories(QByteArray* response) +QList FlameAPI::loadModCategories(const QByteArray& response) { QList categories; QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from categories at" << parse_error.offset << "reason:" << parse_error.errorString(); diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index a5f2146c0..63b981504 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -5,7 +5,6 @@ #pragma once #include -#include #include "BuildConfig.h" #include "Json.h" #include "Version.h" @@ -23,14 +22,14 @@ class FlameAPI : public ResourceAPI { ModPlatform::ModLoaderTypes fallback, bool checkLoaders); - Task::Ptr getProjects(QStringList addonIds, QByteArray* response) const override; - Task::Ptr matchFingerprints(const QList& fingerprints, QByteArray* response); - Task::Ptr getFiles(const QStringList& fileIds, QByteArray* response) const; - Task::Ptr getFile(const QString& addonId, const QString& fileId, QByteArray* response) const; + std::pair getProjects(QStringList addonIds) const override; + std::pair matchFingerprints(const QList& fingerprints); + std::pair getFiles(const QStringList& fileIds) const; + std::pair getFile(const QString& addonId, const QString& fileId) const; - static Task::Ptr getCategories(QByteArray* response, ModPlatform::ResourceType type); - static Task::Ptr getModCategories(QByteArray* response); - static QList loadModCategories(QByteArray* response); + static std::pair getCategories(ModPlatform::ResourceType type); + static std::pair getModCategories(); + static QList loadModCategories(const QByteArray& response); QList getSortingMethods() const override; diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp index 5897781d9..37f0bcb32 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.cpp +++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp @@ -52,10 +52,9 @@ void FlameCheckUpdate::executeTask() if (!versionsUrlOptional.has_value()) continue; - auto response = std::make_shared(); - auto task = Net::ApiDownload::makeByteArray(versionsUrlOptional.value(), response.get()); + auto [task, response] = Net::ApiDownload::makeByteArray(versionsUrlOptional.value()); - connect(task.get(), &Task::succeeded, this, [this, resource, response] { getLatestVersionCallback(resource, response.get()); }); + connect(task.get(), &Task::succeeded, this, [this, resource, response] { getLatestVersionCallback(resource, response); }); netJob->addNetAction(task); } m_task.reset(netJob); @@ -139,16 +138,16 @@ void FlameCheckUpdate::collectBlockedMods() quickSearch[addonId] = resource; } - auto response = std::make_shared(); Task::Ptr projTask; + QByteArray* response; if (addonIds.isEmpty()) { emitSucceeded(); return; } else if (addonIds.size() == 1) { - projTask = api.getProject(*addonIds.begin(), response.get()); + std::tie(projTask, response) = api.getProject(*addonIds.begin()); } else { - projTask = api.getProjects(addonIds, response.get()); + std::tie(projTask, response) = api.getProjects(addonIds); } connect(projTask.get(), &Task::succeeded, this, [this, response, addonIds, quickSearch] { diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index 2fe9ca2da..510a75e82 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -184,8 +184,7 @@ bool FlameCreationTask::updateInstance() fileIds.append(QString::number(file.fileId)); } - auto raw_response = std::make_shared(); - auto job = api.getFiles(fileIds, raw_response.get()); + auto [job, raw_response] = api.getFiles(fileIds); QEventLoop loop; diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 37c9380f5..22d758641 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -167,14 +167,14 @@ void FlamePackExportTask::makeApiRequest() setStatus(tr("Finding versions for hashes...")); setProgress(2, 5); - auto response = std::make_shared(); QList fingerprints; for (auto& murmur : pendingHashes.keys()) { fingerprints.push_back(murmur.toUInt()); } - task.reset(api.matchFingerprints(fingerprints, response.get())); + auto [matchTask, response] = api.matchFingerprints(fingerprints); + task = matchTask; connect(task.get(), &Task::succeeded, this, [this, response] { QJsonParseError parseError{}; @@ -245,16 +245,16 @@ void FlamePackExportTask::getProjectsInfo() } } - auto response = std::make_shared(); Task::Ptr projTask; + QByteArray* response; if (addonIds.isEmpty()) { buildZip(); return; } else if (addonIds.size() == 1) { - projTask = api.getProject(*addonIds.begin(), response.get()); + std::tie(projTask, response) = api.getProject(*addonIds.begin()); } else { - projTask = api.getProjects(addonIds, response.get()); + std::tie(projTask, response) = api.getProjects(addonIds); } connect(projTask.get(), &Task::succeeded, this, [this, response, addonIds] { diff --git a/launcher/modplatform/ftb/FTBPackInstallTask.cpp b/launcher/modplatform/ftb/FTBPackInstallTask.cpp index ea3464e32..73c8fdf64 100644 --- a/launcher/modplatform/ftb/FTBPackInstallTask.cpp +++ b/launcher/modplatform/ftb/FTBPackInstallTask.cpp @@ -91,10 +91,11 @@ void PackInstallTask::executeTask() auto netJob = makeShared("FTB::VersionFetch", APPLICATION->network()); auto searchUrl = QString(BuildConfig.FTB_API_BASE_URL + "/modpack/%1/%2").arg(m_pack.id).arg(version.id); - m_response.reset(new QByteArray()); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), m_response.get())); - QObject::connect(netJob.get(), &NetJob::succeeded, this, &PackInstallTask::onManifestDownloadSucceeded); + auto [action, response] = Net::Download::makeByteArray(QUrl(searchUrl)); + netJob->addNetAction(action); + + QObject::connect(netJob.get(), &NetJob::succeeded, this, [this, response] { onManifestDownloadSucceeded(response); }); QObject::connect(netJob.get(), &NetJob::failed, this, &PackInstallTask::onManifestDownloadFailed); QObject::connect(netJob.get(), &NetJob::aborted, this, &PackInstallTask::abort); QObject::connect(netJob.get(), &NetJob::progress, this, &PackInstallTask::setProgress); @@ -105,15 +106,17 @@ void PackInstallTask::executeTask() netJob->start(); } -void PackInstallTask::onManifestDownloadSucceeded() +void PackInstallTask::onManifestDownloadSucceeded(QByteArray* responsePtr) { + // NOTE(TheKodeToad): moving the response out to avoid it from being destroyed by m_net_job.reset() + QByteArray response = std::move(*responsePtr); m_net_job.reset(); QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*m_response, &parse_error); + QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from FTB at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << *m_response; + qWarning() << response; return; } diff --git a/launcher/modplatform/ftb/FTBPackInstallTask.h b/launcher/modplatform/ftb/FTBPackInstallTask.h index 28f363d45..49d2bb991 100644 --- a/launcher/modplatform/ftb/FTBPackInstallTask.h +++ b/launcher/modplatform/ftb/FTBPackInstallTask.h @@ -62,7 +62,7 @@ class PackInstallTask final : public InstanceTask { void executeTask() override; private slots: - void onManifestDownloadSucceeded(); + void onManifestDownloadSucceeded(QByteArray* responsePtr); void onResolveModsSucceeded(); void onCreateInstanceSucceeded(); void onModDownloadSucceeded(); @@ -84,8 +84,6 @@ class PackInstallTask final : public InstanceTask { QList m_fileIds; - std::unique_ptr m_response; - Modpack m_pack; QString m_versionName; Version m_version; diff --git a/launcher/modplatform/legacy_ftb/PackFetchTask.cpp b/launcher/modplatform/legacy_ftb/PackFetchTask.cpp index 5ce3ca1d2..7d1807ab3 100644 --- a/launcher/modplatform/legacy_ftb/PackFetchTask.cpp +++ b/launcher/modplatform/legacy_ftb/PackFetchTask.cpp @@ -53,13 +53,18 @@ void PackFetchTask::fetch() QUrl publicPacksUrl = QUrl(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/modpacks.xml"); qDebug() << "Downloading public version info from" << publicPacksUrl.toString(); - jobPtr->addNetAction(Net::ApiDownload::makeByteArray(publicPacksUrl, publicModpacksXmlFileData.get())); + + auto [publicAction, publicResponse] = Net::ApiDownload::makeByteArray(publicPacksUrl); + jobPtr->addNetAction(publicAction); QUrl thirdPartyUrl = QUrl(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/thirdparty.xml"); qDebug() << "Downloading thirdparty version info from" << thirdPartyUrl.toString(); - jobPtr->addNetAction(Net::Download::makeByteArray(thirdPartyUrl, thirdPartyModpacksXmlFileData.get())); - connect(jobPtr.get(), &NetJob::succeeded, this, &PackFetchTask::fileDownloadFinished); + auto [thirdPartyAction, thirdPartyResponse] = Net::Download::makeByteArray(thirdPartyUrl); + jobPtr->addNetAction(thirdPartyAction); + + connect(jobPtr.get(), &NetJob::succeeded, this, + [this, publicResponse, thirdPartyResponse] { fileDownloadFinished(publicResponse, thirdPartyResponse); }); connect(jobPtr.get(), &NetJob::failed, this, &PackFetchTask::fileDownloadFailed); connect(jobPtr.get(), &NetJob::aborted, this, &PackFetchTask::fileDownloadAborted); @@ -71,9 +76,10 @@ void PackFetchTask::fetchPrivate(const QStringList& toFetch) QString privatePackBaseUrl = BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/%1.xml"; for (auto& packCode : toFetch) { - auto data = std::make_shared(); NetJob* job = new NetJob("Fetching private pack", m_network); - job->addNetAction(Net::ApiDownload::makeByteArray(privatePackBaseUrl.arg(packCode), data.get())); + + auto [action, data] = Net::ApiDownload::makeByteArray(privatePackBaseUrl.arg(packCode)); + job->addNetAction(action); job->setAskRetry(false); connect(job, &NetJob::succeeded, this, [this, job, data, packCode] { @@ -85,20 +91,15 @@ void PackFetchTask::fetchPrivate(const QStringList& toFetch) } job->deleteLater(); - - data->clear(); }); - connect(job, &NetJob::failed, this, [this, job, packCode, data](QString reason) { + connect(job, &NetJob::failed, this, [this, job, packCode](QString reason) { emit privateFileDownloadFailed(reason, packCode); job->deleteLater(); - - data->clear(); }); - connect(job, &NetJob::aborted, this, [this, job, data] { + connect(job, &NetJob::aborted, this, [this, job] { job->deleteLater(); - data->clear(); emit aborted(); }); @@ -107,20 +108,21 @@ void PackFetchTask::fetchPrivate(const QStringList& toFetch) } } -void PackFetchTask::fileDownloadFinished() +void PackFetchTask::fileDownloadFinished(QByteArray* publicPtr, QByteArray* thirdPartyPtr) { - jobPtr.reset(); - QStringList failedLists; - if (!parseAndAddPacks(*publicModpacksXmlFileData, PackType::Public, publicPacks)) { + if (!parseAndAddPacks(*publicPtr, PackType::Public, publicPacks)) { failedLists.append(tr("Public Packs")); } - if (!parseAndAddPacks(*thirdPartyModpacksXmlFileData, PackType::ThirdParty, thirdPartyPacks)) { + if (!parseAndAddPacks(*thirdPartyPtr, PackType::ThirdParty, thirdPartyPacks)) { failedLists.append(tr("Third Party Packs")); } + // NOTE(TheKodeToad): we don't want to reset the jobPtr earlier as it may invalidate the responses! + jobPtr.reset(); + if (failedLists.size() > 0) { emit failed(tr("Failed to download some pack lists: %1").arg(failedLists.join("\n- "))); } else { @@ -139,7 +141,6 @@ bool PackFetchTask::parseAndAddPacks(QByteArray& data, PackType packType, Modpac if (!doc.setContent(data, false, &errorMsg, &errorLine, &errorCol)) { auto fullErrMsg = QString("Failed to fetch modpack data: %1 %2:%3!").arg(errorMsg).arg(errorLine).arg(errorCol); qWarning() << fullErrMsg; - data.clear(); return false; } diff --git a/launcher/modplatform/legacy_ftb/PackFetchTask.h b/launcher/modplatform/legacy_ftb/PackFetchTask.h index dd119c068..3e1035b79 100644 --- a/launcher/modplatform/legacy_ftb/PackFetchTask.h +++ b/launcher/modplatform/legacy_ftb/PackFetchTask.h @@ -3,7 +3,6 @@ #include #include #include -#include #include "PackHelpers.h" #include "net/NetJob.h" @@ -23,15 +22,12 @@ class PackFetchTask : public QObject { QNetworkAccessManager* m_network; NetJob::Ptr jobPtr; - std::unique_ptr publicModpacksXmlFileData = std::make_unique(); - std::unique_ptr thirdPartyModpacksXmlFileData = std::make_unique(); - bool parseAndAddPacks(QByteArray& data, PackType packType, ModpackList& list); ModpackList publicPacks; ModpackList thirdPartyPacks; protected slots: - void fileDownloadFinished(); + void fileDownloadFinished(QByteArray* publicResponse, QByteArray* thirdPartyResponse); void fileDownloadFailed(QString reason); void fileDownloadAborted(); diff --git a/launcher/modplatform/modrinth/ModrinthAPI.cpp b/launcher/modplatform/modrinth/ModrinthAPI.cpp index df231e27b..b1faa43ec 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.cpp +++ b/launcher/modplatform/modrinth/ModrinthAPI.cpp @@ -11,17 +11,18 @@ #include "net/NetJob.h" #include "net/Upload.h" -Task::Ptr ModrinthAPI::currentVersion(QString hash, QString hash_format, QByteArray* response) +std::pair ModrinthAPI::currentVersion(QString hash, QString hash_format) { auto netJob = makeShared(QString("Modrinth::GetCurrentVersion"), APPLICATION->network()); - netJob->addNetAction(Net::ApiDownload::makeByteArray( - QString(BuildConfig.MODRINTH_PROD_URL + "/version_file/%1?algorithm=%2").arg(hash, hash_format), response)); + auto [action, response] = + Net::ApiDownload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_file/%1?algorithm=%2").arg(hash, hash_format)); + netJob->addNetAction(action); - return netJob; + return { netJob, response }; } -Task::Ptr ModrinthAPI::currentVersions(const QStringList& hashes, QString hash_format, QByteArray* response) +std::pair ModrinthAPI::currentVersions(const QStringList& hashes, QString hash_format) { auto netJob = makeShared(QString("Modrinth::GetCurrentVersions"), APPLICATION->network()); @@ -33,16 +34,16 @@ Task::Ptr ModrinthAPI::currentVersions(const QStringList& hashes, QString hash_f QJsonDocument body(body_obj); auto body_raw = body.toJson(); - netJob->addNetAction(Net::ApiUpload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_files"), response, body_raw)); + auto [action, response] = Net::ApiUpload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_files"), body_raw); + netJob->addNetAction(action); netJob->setAskRetry(false); - return netJob; + return { netJob, response }; } -Task::Ptr ModrinthAPI::latestVersion(QString hash, - QString hash_format, - std::optional> mcVersions, - std::optional loaders, - QByteArray* response) +std::pair ModrinthAPI::latestVersion(QString hash, + QString hash_format, + std::optional> mcVersions, + std::optional loaders) { auto netJob = makeShared(QString("Modrinth::GetLatestVersion"), APPLICATION->network()); @@ -62,17 +63,17 @@ Task::Ptr ModrinthAPI::latestVersion(QString hash, QJsonDocument body(body_obj); auto body_raw = body.toJson(); - netJob->addNetAction(Net::ApiUpload::makeByteArray( - QString(BuildConfig.MODRINTH_PROD_URL + "/version_file/%1/update?algorithm=%2").arg(hash, hash_format), response, body_raw)); + auto [action, response] = Net::ApiUpload::makeByteArray( + QString(BuildConfig.MODRINTH_PROD_URL + "/version_file/%1/update?algorithm=%2").arg(hash, hash_format), body_raw); + netJob->addNetAction(action); - return netJob; + return { netJob, response }; } -Task::Ptr ModrinthAPI::latestVersions(const QStringList& hashes, - QString hash_format, - std::optional> mcVersions, - std::optional loaders, - QByteArray* response) +std::pair ModrinthAPI::latestVersions(const QStringList& hashes, + QString hash_format, + std::optional> mcVersions, + std::optional loaders) { auto netJob = makeShared(QString("Modrinth::GetLatestVersions"), APPLICATION->network()); @@ -94,21 +95,21 @@ Task::Ptr ModrinthAPI::latestVersions(const QStringList& hashes, QJsonDocument body(body_obj); auto body_raw = body.toJson(); + auto [action, response] = Net::ApiUpload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_files/update"), body_raw); + netJob->addNetAction(action); - netJob->addNetAction( - Net::ApiUpload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_files/update"), response, body_raw)); - - return netJob; + return { netJob, response }; } -Task::Ptr ModrinthAPI::getProjects(QStringList addonIds, QByteArray* response) const +std::pair ModrinthAPI::getProjects(QStringList addonIds) const { auto netJob = makeShared(QString("Modrinth::GetProjects"), APPLICATION->network()); auto searchUrl = getMultipleModInfoURL(addonIds); - netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl), response)); + auto [action, response] = Net::ApiDownload::makeByteArray(QUrl(searchUrl)); + netJob->addNetAction(action); - return netJob; + return { netJob, response }; } QList ModrinthAPI::getSortingMethods() const @@ -121,19 +122,21 @@ QList ModrinthAPI::getSortingMethods() const { 5, "updated", QObject::tr("Sort by Last Updated") } }; } -Task::Ptr ModrinthAPI::getModCategories(QByteArray* response) +std::pair ModrinthAPI::getModCategories() { auto netJob = makeShared(QString("Modrinth::GetCategories"), APPLICATION->network()); - netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(BuildConfig.MODRINTH_PROD_URL + "/tag/category"), response)); + auto [action, response] = Net::ApiDownload::makeByteArray(QUrl(BuildConfig.MODRINTH_PROD_URL + "/tag/category")); + netJob->addNetAction(action); QObject::connect(netJob.get(), &Task::failed, [](QString msg) { qDebug() << "Modrinth failed to get categories:" << msg; }); - return netJob; + + return { netJob, response }; } -QList ModrinthAPI::loadCategories(QByteArray* response, QString projectType) +QList ModrinthAPI::loadCategories(const QByteArray& response, QString projectType) { QList categories; QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from categories at" << parse_error.offset << "reason:" << parse_error.errorString(); @@ -159,7 +162,7 @@ QList ModrinthAPI::loadCategories(QByteArray* response, Q return categories; } -QList ModrinthAPI::loadModCategories(QByteArray* response) +QList ModrinthAPI::loadModCategories(const QByteArray& response) { return loadCategories(response, "mod"); }; diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index d1ed845cf..412826182 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -11,30 +11,29 @@ #include "modplatform/modrinth/ModrinthPackIndex.h" #include +#include class ModrinthAPI : public ResourceAPI { public: - Task::Ptr currentVersion(QString hash, QString hash_format, QByteArray* response); + std::pair currentVersion(QString hash, QString hash_format); - Task::Ptr currentVersions(const QStringList& hashes, QString hash_format, QByteArray* response); + std::pair currentVersions(const QStringList& hashes, QString hash_format); - Task::Ptr latestVersion(QString hash, - QString hash_format, - std::optional> mcVersions, - std::optional loaders, - QByteArray* response); + std::pair latestVersion(QString hash, + QString hash_format, + std::optional> mcVersions, + std::optional loaders); - Task::Ptr latestVersions(const QStringList& hashes, - QString hash_format, - std::optional> mcVersions, - std::optional loaders, - QByteArray* response); + std::pair latestVersions(const QStringList& hashes, + QString hash_format, + std::optional> mcVersions, + std::optional loaders); - Task::Ptr getProjects(QStringList addonIds, QByteArray* response) const override; + std::pair getProjects(QStringList addonIds) const override; - static Task::Ptr getModCategories(QByteArray* response); - static QList loadCategories(QByteArray* response, QString projectType); - static QList loadModCategories(QByteArray* response); + static std::pair getModCategories(); + static QList loadCategories(const QByteArray& response, QString projectType); + static QList loadModCategories(const QByteArray& response); public: auto getSortingMethods() const -> QList override; diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index 35910338f..4187b0e1d 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -88,7 +88,6 @@ void ModrinthCheckUpdate::getUpdateModsForLoader(std::optional(); QStringList hashes; if (forceModLoaderCheck && loader.has_value()) { for (auto hash : m_mappings.keys()) { @@ -105,9 +104,9 @@ void ModrinthCheckUpdate::getUpdateModsForLoader(std::optional(); - task = api.currentVersions(pendingHashes.values(), "sha512", response.get()); - connect(task.get(), &Task::succeeded, [this, response]() { parseApiResponse(response.get()); }); + auto [versionsTask, response] = api.currentVersions(pendingHashes.values(), "sha512"); + task = versionsTask; + connect(task.get(), &Task::succeeded, [this, response]() { parseApiResponse(response); }); connect(task.get(), &Task::failed, this, &ModrinthPackExportTask::emitFailed); connect(task.get(), &Task::aborted, this, &ModrinthPackExportTask::emitAborted); task->start(); diff --git a/launcher/modplatform/technic/SolderPackInstallTask.cpp b/launcher/modplatform/technic/SolderPackInstallTask.cpp index cef2d5d8f..e7f4b7a55 100644 --- a/launcher/modplatform/technic/SolderPackInstallTask.cpp +++ b/launcher/modplatform/technic/SolderPackInstallTask.cpp @@ -72,24 +72,25 @@ void Technic::SolderPackInstallTask::executeTask() m_filesNetJob.reset(new NetJob(tr("Resolving modpack files"), m_network)); auto sourceUrl = QString("%1/modpack/%2/%3").arg(m_solderUrl.toString(), m_pack, m_version); - m_filesNetJob->addNetAction(Net::ApiDownload::makeByteArray(sourceUrl, m_response.get())); + auto [action, response] = Net::ApiDownload::makeByteArray(sourceUrl); + m_filesNetJob->addNetAction(action); auto job = m_filesNetJob.get(); - connect(job, &NetJob::succeeded, this, &Technic::SolderPackInstallTask::fileListSucceeded); + connect(job, &NetJob::succeeded, this, [this, response] { fileListSucceeded(response); }); connect(job, &NetJob::failed, this, &Technic::SolderPackInstallTask::downloadFailed); connect(job, &NetJob::aborted, this, &Technic::SolderPackInstallTask::downloadAborted); m_filesNetJob->start(); } -void Technic::SolderPackInstallTask::fileListSucceeded() +void Technic::SolderPackInstallTask::fileListSucceeded(QByteArray* response) { setStatus(tr("Downloading modpack")); QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*m_response, &parse_error); + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from Solder at" << parse_error.offset << "reason:" << parse_error.errorString(); - qWarning() << *m_response; + qWarning() << *response; return; } auto obj = doc.object(); diff --git a/launcher/modplatform/technic/SolderPackInstallTask.h b/launcher/modplatform/technic/SolderPackInstallTask.h index ef319e6a5..07cce4644 100644 --- a/launcher/modplatform/technic/SolderPackInstallTask.h +++ b/launcher/modplatform/technic/SolderPackInstallTask.h @@ -40,7 +40,6 @@ #include #include -#include namespace Technic { class SolderPackInstallTask : public InstanceTask { @@ -60,7 +59,7 @@ class SolderPackInstallTask : public InstanceTask { virtual void executeTask() override; private slots: - void fileListSucceeded(); + void fileListSucceeded(QByteArray* response); void downloadSucceeded(); void downloadFailed(QString reason); void downloadProgressChanged(qint64 current, qint64 total); @@ -78,7 +77,6 @@ class SolderPackInstallTask : public InstanceTask { QString m_pack; QString m_version; QString m_minecraftVersion; - std::unique_ptr m_response = std::make_unique(); QTemporaryDir m_outputDir; int m_modCount; QFuture m_extractFuture; diff --git a/launcher/net/ApiDownload.cpp b/launcher/net/ApiDownload.cpp index c0e3d78a2..9a5a44104 100644 --- a/launcher/net/ApiDownload.cpp +++ b/launcher/net/ApiDownload.cpp @@ -29,11 +29,11 @@ Download::Ptr ApiDownload::makeCached(QUrl url, MetaEntryPtr entry, Download::Op return dl; } -Download::Ptr ApiDownload::makeByteArray(QUrl url, QByteArray* output, Download::Options options) +std::pair ApiDownload::makeByteArray(QUrl url, Download::Options options) { - auto dl = Download::makeByteArray(url, output, options); + auto [dl, response] = Download::makeByteArray(url, options); dl->addHeaderProxy(std::make_unique()); - return dl; + return { dl, response }; } Download::Ptr ApiDownload::makeFile(QUrl url, QString path, Download::Options options) diff --git a/launcher/net/ApiDownload.h b/launcher/net/ApiDownload.h index 25d2447e3..01a31eb17 100644 --- a/launcher/net/ApiDownload.h +++ b/launcher/net/ApiDownload.h @@ -25,7 +25,7 @@ namespace Net { namespace ApiDownload { Download::Ptr makeCached(QUrl url, MetaEntryPtr entry, Download::Options options = Download::Option::NoOptions); -Download::Ptr makeByteArray(QUrl url, QByteArray* output, Download::Options options = Download::Option::NoOptions); +std::pair makeByteArray(QUrl url, Download::Options options = Download::Option::NoOptions); Download::Ptr makeFile(QUrl url, QString path, Download::Options options = Download::Option::NoOptions); }; // namespace ApiDownload diff --git a/launcher/net/ApiUpload.cpp b/launcher/net/ApiUpload.cpp index acb7d141f..261558130 100644 --- a/launcher/net/ApiUpload.cpp +++ b/launcher/net/ApiUpload.cpp @@ -22,11 +22,11 @@ namespace Net { -Upload::Ptr ApiUpload::makeByteArray(QUrl url, QByteArray* output, QByteArray m_post_data) +std::pair ApiUpload::makeByteArray(QUrl url, QByteArray m_post_data) { - auto up = Upload::makeByteArray(url, output, m_post_data); + auto [up, response] = Upload::makeByteArray(url, m_post_data); up->addHeaderProxy(std::make_unique()); - return up; + return { up, response }; } } // namespace Net diff --git a/launcher/net/ApiUpload.h b/launcher/net/ApiUpload.h index b473c81c8..3aa4adeab 100644 --- a/launcher/net/ApiUpload.h +++ b/launcher/net/ApiUpload.h @@ -24,7 +24,7 @@ namespace Net { namespace ApiUpload { -Upload::Ptr makeByteArray(QUrl url, QByteArray* output, QByteArray m_post_data); +std::pair makeByteArray(QUrl url, QByteArray m_post_data); }; } // namespace Net diff --git a/launcher/net/ByteArraySink.h b/launcher/net/ByteArraySink.h index 82e3f6592..bf2757440 100644 --- a/launcher/net/ByteArraySink.h +++ b/launcher/net/ByteArraySink.h @@ -41,11 +41,11 @@ namespace Net { /* - * Sink object for downloads that uses an external QByteArray it doesn't own as a target. + * Sink object for downloads that uses an owned QByteArray as a target. */ class ByteArraySink : public Sink { public: - ByteArraySink(QByteArray* output) : m_output(output) {} + ByteArraySink(std::unique_ptr output) : m_output(std::move(output)) {} virtual ~ByteArraySink() = default; @@ -92,6 +92,6 @@ class ByteArraySink : public Sink { auto hasLocalData() -> bool override { return false; } protected: - QByteArray* m_output; + std::unique_ptr m_output; }; } // namespace Net diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp index 8b7bef2d4..3d0191b04 100644 --- a/launcher/net/Download.cpp +++ b/launcher/net/Download.cpp @@ -63,14 +63,17 @@ auto Download::makeCached(QUrl url, MetaEntryPtr entry, Options options) -> Down } #endif -auto Download::makeByteArray(QUrl url, QByteArray* output, Options options) -> Download::Ptr +auto Download::makeByteArray(QUrl url, Options options) -> std::pair { auto dl = makeShared(); dl->m_url = url; dl->setObjectName(QString("BYTES:") + url.toString()); dl->m_options = options; - dl->m_sink.reset(new ByteArraySink(output)); - return dl; + + auto response = new QByteArray(); + dl->m_sink = std::make_unique(std::unique_ptr{ response }); + + return { dl, response }; } auto Download::makeFile(QUrl url, QString path, Options options) -> Download::Ptr diff --git a/launcher/net/Download.h b/launcher/net/Download.h index a571e5b03..60a5b5b64 100644 --- a/launcher/net/Download.h +++ b/launcher/net/Download.h @@ -38,12 +38,16 @@ #pragma once +#include + #include "HttpMetaCache.h" #include "QObjectPtr.h" #include "net/NetRequest.h" namespace Net { +class ByteArraySink; + class Download : public NetRequest { Q_OBJECT public: @@ -54,7 +58,11 @@ class Download : public NetRequest { static auto makeCached(QUrl url, MetaEntryPtr entry, Options options = Option::NoOptions) -> Download::Ptr; #endif - static auto makeByteArray(QUrl url, QByteArray* output, Options options = Option::NoOptions) -> Download::Ptr; + /** + * Creates a request downloading to the returned QByteArray,. + * The QByteArray will live as long as the Download object. + */ + static auto makeByteArray(QUrl url, Options options = Option::NoOptions) -> std::pair; static auto makeFile(QUrl url, QString path, Options options = Option::NoOptions) -> Download::Ptr; protected: diff --git a/launcher/net/PasteUpload.cpp b/launcher/net/PasteUpload.cpp index 672637685..69270bce9 100644 --- a/launcher/net/PasteUpload.cpp +++ b/launcher/net/PasteUpload.cpp @@ -214,5 +214,6 @@ PasteUpload::PasteUpload(const QString& log, QString url, PasteType pasteType) : else m_url = m_baseUrl + base.endpointPath; - m_sink.reset(new Sink(this, m_output.get())); + m_response = new QByteArray(); + m_sink.reset(new Sink(this, std::unique_ptr{ m_response })); } diff --git a/launcher/net/PasteUpload.h b/launcher/net/PasteUpload.h index cb0d2d5c1..f6c4f85a7 100644 --- a/launcher/net/PasteUpload.h +++ b/launcher/net/PasteUpload.h @@ -45,6 +45,7 @@ #include #include +#include class PasteUpload : public Net::NetRequest { public: @@ -71,7 +72,7 @@ class PasteUpload : public Net::NetRequest { class Sink : public Net::ByteArraySink { public: - Sink(PasteUpload* p, QByteArray* output) : Net::ByteArraySink(output), m_d(p) {}; + Sink(PasteUpload* p, std::unique_ptr output) : Net::ByteArraySink(std::move(output)), m_d(p) {}; virtual ~Sink() = default; public: @@ -93,5 +94,5 @@ class PasteUpload : public Net::NetRequest { QString m_pasteLink; QString m_baseUrl; const PasteType m_paste_type; - std::unique_ptr m_output = std::make_unique(); + QByteArray* m_response; }; diff --git a/launcher/net/Upload.cpp b/launcher/net/Upload.cpp index d162051f8..f43d27b5c 100644 --- a/launcher/net/Upload.cpp +++ b/launcher/net/Upload.cpp @@ -51,12 +51,15 @@ QNetworkReply* Upload::getReply(QNetworkRequest& request) return m_network->post(request, m_post_data); } -Upload::Ptr Upload::makeByteArray(QUrl url, QByteArray* output, QByteArray m_post_data) +std::pair Upload::makeByteArray(QUrl url, QByteArray m_post_data) { auto up = makeShared(); up->m_url = std::move(url); - up->m_sink.reset(new ByteArraySink(output)); + + auto response = new QByteArray(); + up->m_sink = std::make_unique(std::unique_ptr{ response }); + up->m_post_data = std::move(m_post_data); - return up; + return { up, response }; } } // namespace Net diff --git a/launcher/net/Upload.h b/launcher/net/Upload.h index 97db89250..0610426a1 100644 --- a/launcher/net/Upload.h +++ b/launcher/net/Upload.h @@ -37,6 +37,8 @@ #pragma once +#include + #include "net/NetRequest.h" namespace Net { @@ -47,7 +49,11 @@ class Upload : public NetRequest { using Ptr = shared_qobject_ptr; explicit Upload() : NetRequest() { logCat = taskUploadLogC; }; - static Upload::Ptr makeByteArray(QUrl url, QByteArray* output, QByteArray m_post_data); + /** + * Creates a request downloading to the returned QByteArray,. + * The QByteArray will live as long as the Upload object. + */ + static std::pair makeByteArray(QUrl url, QByteArray m_post_data); protected: virtual QNetworkReply* getReply(QNetworkRequest&) override; diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index d6c4ccbec..bd6cfb50e 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -957,10 +957,8 @@ void MainWindow::processURLs(QList urls) extra_info.insert("pack_id", addonId); extra_info.insert("pack_version_id", fileId); - auto array = std::make_shared(); - auto api = FlameAPI(); - auto job = api.getFile(addonId, fileId, array.get()); + auto [job, array] = api.getFile(addonId, fileId); connect(job.get(), &Task::failed, this, [this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); diff --git a/launcher/ui/dialogs/ProfileSetupDialog.cpp b/launcher/ui/dialogs/ProfileSetupDialog.cpp index 8e2f2289c..291827b05 100644 --- a/launcher/ui/dialogs/ProfileSetupDialog.cpp +++ b/launcher/ui/dialogs/ProfileSetupDialog.cpp @@ -159,22 +159,23 @@ void ProfileSetupDialog::checkName(const QString& name) { "Accept", "application/json" }, { "Authorization", QString("Bearer %1").arg(m_accountToSetup->accessToken()).toUtf8() } }; - m_check_response.reset(new QByteArray()); if (m_check_task) disconnect(m_check_task.get(), nullptr, this, nullptr); - m_check_task = Net::Download::makeByteArray(url, m_check_response.get()); + auto [task, response] = Net::Download::makeByteArray(url); + + m_check_task = task; m_check_task->addHeaderProxy(std::make_unique(headers)); - connect(m_check_task.get(), &Task::finished, this, &ProfileSetupDialog::checkFinished); + connect(m_check_task.get(), &Task::finished, this, [this, response] { checkFinished(response); }); m_check_task->setNetwork(APPLICATION->network()); m_check_task->start(); } -void ProfileSetupDialog::checkFinished() +void ProfileSetupDialog::checkFinished(QByteArray* response) { if (m_check_task->error() == QNetworkReply::NoError) { - auto doc = QJsonDocument::fromJson(*m_check_response); + auto doc = QJsonDocument::fromJson(*response); auto root = doc.object(); auto statusValue = root.value("status").toString("INVALID"); if (statusValue == "AVAILABLE") { @@ -205,11 +206,11 @@ void ProfileSetupDialog::setupProfile(const QString& profileName) { "Accept", "application/json" }, { "Authorization", QString("Bearer %1").arg(m_accountToSetup->accessToken()).toUtf8() } }; - m_profile_response.reset(new QByteArray()); - m_profile_task = Net::Upload::makeByteArray(url, m_profile_response.get(), payloadTemplate.arg(profileName).toUtf8()); + auto [task, response] = Net::Upload::makeByteArray(url, payloadTemplate.arg(profileName).toUtf8()); + m_profile_task = task; m_profile_task->addHeaderProxy(std::make_unique(headers)); - connect(m_profile_task.get(), &Task::finished, this, &ProfileSetupDialog::setupProfileFinished); + connect(m_profile_task.get(), &Task::finished, this, [this, response] { setupProfileFinished(response); }); m_profile_task->setNetwork(APPLICATION->network()); m_profile_task->start(); @@ -252,7 +253,7 @@ struct MojangError { } // namespace -void ProfileSetupDialog::setupProfileFinished() +void ProfileSetupDialog::setupProfileFinished(QByteArray* response) { isWorking = false; if (m_profile_task->error() == QNetworkReply::NoError) { @@ -262,7 +263,7 @@ void ProfileSetupDialog::setupProfileFinished() */ accept(); } else { - auto parsedError = MojangError::fromJSON(*m_profile_response); + auto parsedError = MojangError::fromJSON(*response); ui->errorLabel->setVisible(true); QString errorMessage = diff --git a/launcher/ui/dialogs/ProfileSetupDialog.h b/launcher/ui/dialogs/ProfileSetupDialog.h index 594ec6d51..1da9c1164 100644 --- a/launcher/ui/dialogs/ProfileSetupDialog.h +++ b/launcher/ui/dialogs/ProfileSetupDialog.h @@ -21,7 +21,6 @@ #include #include -#include #include "net/Download.h" #include "net/Upload.h" @@ -44,8 +43,8 @@ class ProfileSetupDialog : public QDialog { void nameEdited(const QString& name); void startCheck(); - void checkFinished(); - void setupProfileFinished(); + void checkFinished(QByteArray* response); + void setupProfileFinished(QByteArray* response); protected: void scheduleCheck(const QString& name); @@ -70,9 +69,6 @@ class ProfileSetupDialog : public QDialog { QTimer checkStartTimer; - std::unique_ptr m_check_response; Net::Download::Ptr m_check_task; - - std::unique_ptr m_profile_response; Net::Upload::Ptr m_profile_task; }; diff --git a/launcher/ui/dialogs/skins/SkinManageDialog.cpp b/launcher/ui/dialogs/skins/SkinManageDialog.cpp index a3eb8d772..4dfeeaa34 100644 --- a/launcher/ui/dialogs/skins/SkinManageDialog.cpp +++ b/launcher/ui/dialogs/skins/SkinManageDialog.cpp @@ -472,14 +472,11 @@ void SkinManageDialog::on_userBtn_clicked() NetJob::Ptr job{ new NetJob(tr("Download user skin"), APPLICATION->network(), 1) }; job->setAskRetry(false); - auto uuidOut = std::make_shared(); - auto profileOut = std::make_shared(); - auto uuidLoop = makeShared(); auto profileLoop = makeShared(); - auto getUUID = Net::Download::makeByteArray("https://api.minecraftservices.com/minecraft/profile/lookup/name/" + user, uuidOut.get()); - auto getProfile = Net::Download::makeByteArray(QUrl(), profileOut.get()); + auto [getUUID, uuidOut] = Net::Download::makeByteArray("https://api.minecraftservices.com/minecraft/profile/lookup/name/" + user); + auto [getProfile, profileOut] = Net::Download::makeByteArray(QUrl()); auto downloadSkin = Net::Download::makeFile(QUrl(), path); QString failReason; diff --git a/launcher/ui/pages/modplatform/ImportPage.cpp b/launcher/ui/pages/modplatform/ImportPage.cpp index a345f0d41..6e783014f 100644 --- a/launcher/ui/pages/modplatform/ImportPage.cpp +++ b/launcher/ui/pages/modplatform/ImportPage.cpp @@ -131,10 +131,9 @@ void ImportPage::updateState() } auto addonId = query.allQueryItemValues("addonId")[0]; auto fileId = query.allQueryItemValues("fileId")[0]; - auto array = std::make_shared(); auto api = FlameAPI(); - auto job = api.getFile(addonId, fileId, array.get()); + auto [job, array] = api.getFile(addonId, fileId); connect(job.get(), &NetJob::failed, this, [this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp index 3c80b90c9..91668fb84 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp @@ -99,23 +99,26 @@ void ListModel::request() auto netJob = makeShared("Atl::Request", APPLICATION->network()); auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/json/packsnew.json"); - netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(url), response.get())); + auto [action, response] = Net::ApiDownload::makeByteArray(QUrl(url)); + netJob->addNetAction(action); jobPtr = netJob; jobPtr->start(); - connect(netJob.get(), &NetJob::succeeded, this, &ListModel::requestFinished); + connect(netJob.get(), &NetJob::succeeded, this, [this, response] { requestFinished(response); }); connect(netJob.get(), &NetJob::failed, this, &ListModel::requestFailed); } -void ListModel::requestFinished() +void ListModel::requestFinished(QByteArray* responsePtr) { + // NOTE(TheKodeToad): moving the response out to avoid it from being destroyed by jobPtr.reset() + QByteArray response = std::move(*responsePtr); jobPtr.reset(); QJsonParseError parse_error; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from ATL at" << parse_error.offset << "reason:" << parse_error.errorString(); - qWarning() << *response; + qWarning() << response; return; } @@ -130,7 +133,7 @@ void ListModel::requestFinished() try { ATLauncher::loadIndexedPack(pack, packObj); } catch (const JSONValidationError& e) { - qDebug() << QString::fromUtf8(*response); + qDebug() << QString::fromUtf8(response); qWarning() << "Error while reading pack manifest from ATLauncher:" << e.cause(); return; } diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.h b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.h index 7311d787a..51c5c782d 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.h +++ b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.h @@ -43,7 +43,7 @@ class ListModel : public QAbstractListModel { void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback); private slots: - void requestFinished(); + void requestFinished(QByteArray* responsePtr); void requestFailed(QString reason); void logoFailed(QString logo); @@ -61,7 +61,6 @@ class ListModel : public QAbstractListModel { QMap waitingCallbacks; NetJob::Ptr jobPtr; - std::unique_ptr response = std::make_unique(); }; } // namespace Atl diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp index e4e9d4a3b..421060e85 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp @@ -159,23 +159,26 @@ void AtlOptionalModListModel::useShareCode(const QString& code) { m_jobPtr.reset(new NetJob("Atl::Request", APPLICATION->network())); auto url = QString(BuildConfig.ATL_API_BASE_URL + "share-codes/" + code); - m_jobPtr->addNetAction(Net::ApiDownload::makeByteArray(QUrl(url), m_response.get())); + auto [action, response] = Net::ApiDownload::makeByteArray(QUrl(url)); + m_jobPtr->addNetAction(action); - connect(m_jobPtr.get(), &NetJob::succeeded, this, &AtlOptionalModListModel::shareCodeSuccess); + connect(m_jobPtr.get(), &NetJob::succeeded, this, [this, response] { shareCodeSuccess(response); }); connect(m_jobPtr.get(), &NetJob::failed, this, &AtlOptionalModListModel::shareCodeFailure); m_jobPtr->start(); } -void AtlOptionalModListModel::shareCodeSuccess() +void AtlOptionalModListModel::shareCodeSuccess(QByteArray* responsePtr) { + // NOTE(TheKodeToad): moving the response out to avoid it from being destroyed by jobPtr.reset() + QByteArray responseData = *std::move(responsePtr); m_jobPtr.reset(); QJsonParseError parse_error{}; - auto doc = QJsonDocument::fromJson(*m_response, &parse_error); + auto doc = QJsonDocument::fromJson(responseData, &parse_error); if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from ATL at" << parse_error.offset << "reason:" << parse_error.errorString(); - qWarning() << *m_response; + qWarning() << responseData; return; } auto obj = doc.object(); @@ -184,7 +187,7 @@ void AtlOptionalModListModel::shareCodeSuccess() try { ATLauncher::loadShareCodeResponse(response, obj); } catch (const JSONValidationError& e) { - qDebug() << QString::fromUtf8(*m_response); + qDebug() << QString::fromUtf8(responseData); qWarning() << "Error while reading response from ATLauncher:" << e.cause(); return; } diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h index ebd63881b..8c36320e0 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h +++ b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h @@ -71,7 +71,7 @@ class AtlOptionalModListModel : public QAbstractListModel { void useShareCode(const QString& code); public slots: - void shareCodeSuccess(); + void shareCodeSuccess(QByteArray* responsePtr); void shareCodeFailure(const QString& reason); void selectRecommended(); @@ -83,7 +83,6 @@ class AtlOptionalModListModel : public QAbstractListModel { private: NetJob::Ptr m_jobPtr; - std::unique_ptr m_response = std::make_unique(); ATLauncher::PackVersion m_version; QList m_mods; diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index 9a5698a78..336133819 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -330,10 +330,10 @@ void FlamePage::createFilterWidget() connect(m_ui->filterButton, &QPushButton::clicked, this, [this] { m_filterWidget->setHidden(!m_filterWidget->isHidden()); }); connect(m_filterWidget.get(), &ModFilterWidget::filterChanged, this, &FlamePage::triggerSearch); - auto response = std::make_shared(); - m_categoriesTask = FlameAPI::getCategories(response.get(), ModPlatform::ResourceType::Modpack); + auto [task, response] = FlameAPI::getCategories(ModPlatform::ResourceType::Modpack); + m_categoriesTask = task; connect(m_categoriesTask.get(), &Task::succeeded, [this, response]() { - auto categories = FlameAPI::loadModCategories(response.get()); + auto categories = FlameAPI::loadModCategories(*response); m_filterWidget->setCategories(categories); }); m_categoriesTask->start(); diff --git a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp index af2de22ec..99a57f2bf 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourcePages.cpp @@ -247,10 +247,10 @@ std::unique_ptr FlameModPage::createFilterWidget() void FlameModPage::prepareProviderCategories() { - auto response = std::make_shared(); - m_categoriesTask = FlameAPI::getModCategories(response.get()); + auto [task, response] = FlameAPI::getModCategories(); + m_categoriesTask = task; connect(m_categoriesTask.get(), &Task::succeeded, [this, response]() { - auto categories = FlameAPI::loadModCategories(response.get()); + auto categories = FlameAPI::loadModCategories(*response); m_filter_widget->setCategories(categories); }); m_categoriesTask->start(); diff --git a/launcher/ui/pages/modplatform/ftb/FtbListModel.cpp b/launcher/ui/pages/modplatform/ftb/FtbListModel.cpp index f5d026c68..29d73a4a9 100644 --- a/launcher/ui/pages/modplatform/ftb/FtbListModel.cpp +++ b/launcher/ui/pages/modplatform/ftb/FtbListModel.cpp @@ -96,12 +96,12 @@ void ListModel::request() auto netJob = makeShared("Ftb::Request", APPLICATION->network()); auto url = QString(BuildConfig.FTB_API_BASE_URL + "/modpack/all"); - m_response.reset(new QByteArray()); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), m_response.get())); + auto [action, response] = Net::Download::makeByteArray(QUrl(url)); + netJob->addNetAction(action); m_jobPtr = netJob; m_jobPtr->start(); - QObject::connect(netJob.get(), &NetJob::succeeded, this, &ListModel::requestFinished); + QObject::connect(netJob.get(), &NetJob::succeeded, this, [this, response] { requestFinished(response); }); QObject::connect(netJob.get(), &NetJob::failed, this, &ListModel::requestFailed); } @@ -111,16 +111,18 @@ void ListModel::abortRequest() m_jobPtr.reset(); } -void ListModel::requestFinished() +void ListModel::requestFinished(QByteArray* responsePtr) { + // NOTE(TheKodeToad): moving the response out to avoid it from being destroyed by m_jobPtr.reset() + QByteArray response = std::move(*responsePtr); m_jobPtr.reset(); m_remainingPacks.clear(); QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*m_response, &parse_error); + QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from FTB at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << *m_response; + qWarning() << response; return; } @@ -146,29 +148,32 @@ void ListModel::requestPack() { auto netJob = makeShared("Ftb::Search", APPLICATION->network()); auto searchUrl = QString(BuildConfig.FTB_API_BASE_URL + "/modpack/%1").arg(m_currentPack); - m_response.reset(new QByteArray()); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), m_response.get())); + auto [action, response] = Net::Download::makeByteArray(QUrl(searchUrl)); + netJob->addNetAction(action); m_jobPtr = netJob; m_jobPtr->start(); - QObject::connect(netJob.get(), &NetJob::succeeded, this, &ListModel::packRequestFinished); + QObject::connect(netJob.get(), &NetJob::succeeded, this, [this, response] { packRequestFinished(response); }); QObject::connect(netJob.get(), &NetJob::failed, this, &ListModel::packRequestFailed); } -void ListModel::packRequestFinished() +void ListModel::packRequestFinished(QByteArray* responsePtr) { if (!m_jobPtr || m_aborted) return; + // NOTE(TheKodeToad): moving the response out to avoid it from being destroyed by jobPtr.reset() + QByteArray response = std::move(*responsePtr); + m_jobPtr.reset(); m_remainingPacks.removeOne(m_currentPack); QJsonParseError parse_error; - QJsonDocument doc = QJsonDocument::fromJson(*m_response, &parse_error); + QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from FTB at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << *m_response; + qWarning() << response; return; } @@ -178,7 +183,7 @@ void ListModel::packRequestFinished() try { FTB::loadModpack(pack, obj); } catch (const JSONValidationError& e) { - qDebug() << QString::fromUtf8(*m_response); + qDebug() << QString::fromUtf8(response); qWarning() << "Error while reading pack manifest from FTB: " << e.cause(); return; } diff --git a/launcher/ui/pages/modplatform/ftb/FtbListModel.h b/launcher/ui/pages/modplatform/ftb/FtbListModel.h index a7f35f41e..339693c7c 100644 --- a/launcher/ui/pages/modplatform/ftb/FtbListModel.h +++ b/launcher/ui/pages/modplatform/ftb/FtbListModel.h @@ -55,11 +55,11 @@ class ListModel : public QAbstractListModel { [[nodiscard]] bool wasAborted() const { return m_aborted; } private slots: - void requestFinished(); + void requestFinished(QByteArray* responsePtr); void requestFailed(QString reason); void requestPack(); - void packRequestFinished(); + void packRequestFinished(QByteArray* responsePtr); void packRequestFailed(QString reason); void logoFailed(QString logo); @@ -77,7 +77,6 @@ class ListModel : public QAbstractListModel { NetJob::Ptr m_jobPtr; int m_currentPack; QList m_remainingPacks; - std::unique_ptr m_response; }; } // namespace Ftb diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index 0fa8e5b3d..4798583bd 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -372,10 +372,10 @@ void ModrinthPage::createFilterWidget() connect(m_ui->filterButton, &QPushButton::clicked, this, [this] { m_filterWidget->setHidden(!m_filterWidget->isHidden()); }); connect(m_filterWidget.get(), &ModFilterWidget::filterChanged, this, &ModrinthPage::triggerSearch); - auto response = std::make_shared(); - m_categoriesTask = ModrinthAPI::getModCategories(response.get()); + auto [categoriesTask, response] = ModrinthAPI::getModCategories(); + m_categoriesTask = categoriesTask; connect(m_categoriesTask.get(), &Task::succeeded, [this, response]() { - auto categories = ModrinthAPI::loadCategories(response.get(), "modpack"); + auto categories = ModrinthAPI::loadCategories(*response, "modpack"); m_filterWidget->setCategories(categories); }); m_categoriesTask->start(); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp index 0646cbdc9..c290b6715 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourcePages.cpp @@ -165,10 +165,10 @@ std::unique_ptr ModrinthModPage::createFilterWidget() void ModrinthModPage::prepareProviderCategories() { - auto response = std::make_shared(); - m_categoriesTask = ModrinthAPI::getModCategories(response.get()); + auto [categoriesTask, response] = ModrinthAPI::getModCategories(); + m_categoriesTask = categoriesTask; connect(m_categoriesTask.get(), &Task::succeeded, [this, response]() { - auto categories = ModrinthAPI::loadModCategories(response.get()); + auto categories = ModrinthAPI::loadModCategories(*response); m_filter_widget->setCategories(categories); }); m_categoriesTask->start(); diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp index c0d7a90a7..af2aed6d2 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp @@ -35,9 +35,9 @@ #include "TechnicModel.h" #include "Application.h" -#include "settings/SettingsObject.h" #include "BuildConfig.h" #include "Json.h" +#include "settings/SettingsObject.h" #include "net/ApiDownload.h" #include "ui/widgets/ProjectItem.h" @@ -157,23 +157,25 @@ void Technic::ListModel::performSearch() if (!clientId.isEmpty()) { searchUrl += "?cid=" + clientId; } - netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl), response.get())); + auto [action, response] = Net::ApiDownload::makeByteArray(QUrl(searchUrl)); + netJob->addNetAction(action); jobPtr = netJob; jobPtr->start(); - connect(netJob.get(), &NetJob::succeeded, this, &ListModel::searchRequestFinished); + connect(netJob.get(), &NetJob::succeeded, this, [this, response] { searchRequestFinished(response); }); connect(netJob.get(), &NetJob::failed, this, &ListModel::searchRequestFailed); } -void Technic::ListModel::searchRequestFinished() +void Technic::ListModel::searchRequestFinished(QByteArray* responsePtr) { + // NOTE(TheKodeToad): moving the response out to avoid it from being destroyed by jobPtr.reset() + QByteArray response = std::move(*responsePtr); jobPtr.reset(); QJsonParseError parse_error; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from Technic at" << parse_error.offset - << "reason:" << parse_error.errorString(); - qWarning() << *response; + qWarning() << "Error while parsing JSON response from Technic at" << parse_error.offset << "reason:" << parse_error.errorString(); + qWarning() << response; return; } diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.h b/launcher/ui/pages/modplatform/technic/TechnicModel.h index 8ad8b88bb..872f8b5d6 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.h +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.h @@ -62,7 +62,7 @@ class ListModel : public QAbstractListModel { Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? jobPtr : nullptr; } private slots: - void searchRequestFinished(); + void searchRequestFinished(QByteArray* responsePtr); void searchRequestFailed(); void logoFailed(QString logo); @@ -86,7 +86,6 @@ class ListModel : public QAbstractListModel { Single, } searchMode = List; NetJob::Ptr jobPtr; - std::unique_ptr response = std::make_unique(); }; } // namespace Technic diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp index 882e79573..0858d6397 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp @@ -165,9 +165,12 @@ void TechnicPage::suggestCurrent() auto netJob = makeShared(QString("Technic::PackMeta(%1)").arg(current.name), APPLICATION->network()); QString slug = current.slug; - netJob->addNetAction(Net::ApiDownload::makeByteArray( - QString("%1modpack/%2?build=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, slug, BuildConfig.TECHNIC_API_BUILD), response.get())); - connect(netJob.get(), &NetJob::succeeded, this, [this, slug] { + auto [action, responsePtr] = Net::ApiDownload::makeByteArray( + QString("%1modpack/%2?build=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, slug, BuildConfig.TECHNIC_API_BUILD)); + netJob->addNetAction(action); + connect(netJob.get(), &NetJob::succeeded, this, [this, responsePtr, slug] { + // NOTE(TheKodeToad): moving the response out to avoid it from being destroyed by jobPtr.reset() + QByteArray response = std::move(*responsePtr); jobPtr.reset(); if (current.slug != slug) { @@ -175,12 +178,12 @@ void TechnicPage::suggestCurrent() } QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); QJsonObject obj = doc.object(); if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from Technic at" << parse_error.offset << "reason:" << parse_error.errorString(); - qWarning() << *response; + qWarning() << response; return; } if (!obj.contains("url")) { @@ -263,9 +266,10 @@ void TechnicPage::metadataLoaded() auto netJob = makeShared(QString("Technic::SolderMeta(%1)").arg(current.name), APPLICATION->network()); auto url = QString("%1/modpack/%2").arg(current.url, current.slug); - netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(url), response.get())); + auto [action, response] = Net::ApiDownload::makeByteArray(QUrl(url)); + netJob->addNetAction(action); - connect(netJob.get(), &NetJob::succeeded, this, &TechnicPage::onSolderLoaded); + connect(netJob.get(), &NetJob::succeeded, this, [this, response] { onSolderLoaded(response); }); connect(jobPtr.get(), &NetJob::failed, [this](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); }); @@ -296,8 +300,10 @@ void TechnicPage::selectVersion() } } -void TechnicPage::onSolderLoaded() +void TechnicPage::onSolderLoaded(QByteArray* responsePtr) { + // NOTE(TheKodeToad): moving the response out to avoid it from being destroyed by jobPtr.reset() + QByteArray response = std::move(*responsePtr); jobPtr.reset(); auto fallback = [this]() { @@ -310,10 +316,10 @@ void TechnicPage::onSolderLoaded() current.versions.clear(); QJsonParseError parse_error{}; - auto doc = QJsonDocument::fromJson(*response, &parse_error); + auto doc = QJsonDocument::fromJson(response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from Solder at" << parse_error.offset << "reason:" << parse_error.errorString(); - qWarning() << *response; + qWarning() << response; fallback(); return; } diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.h b/launcher/ui/pages/modplatform/technic/TechnicPage.h index 9bde6b78c..466be81d4 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.h +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.h @@ -83,7 +83,7 @@ class TechnicPage : public QWidget, public ModpackProviderBasePage { private slots: void triggerSearch(); void onSelectionChanged(QModelIndex first, QModelIndex second); - void onSolderLoaded(); + void onSolderLoaded(QByteArray* responsePtr); void onVersionSelectionChanged(QString data); private: @@ -95,7 +95,6 @@ class TechnicPage : public QWidget, public ModpackProviderBasePage { QString selectedVersion; NetJob::Ptr jobPtr; - std::unique_ptr response = std::make_unique(); ProgressWidget m_fetch_progress; diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 29e9225f2..a9369d62b 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -1135,8 +1135,7 @@ void PrismUpdaterApp::downloadReleasePage(const QString& api_url, int page) { int per_page = 30; auto page_url = QString("%1?per_page=%2&page=%3").arg(api_url).arg(QString::number(per_page)).arg(QString::number(page)); - auto response = std::make_shared(); - auto download = Net::Download::makeByteArray(page_url, response.get()); + auto [download, response] = Net::Download::makeByteArray(page_url); download->setNetwork(m_network.get()); m_current_url = page_url; @@ -1148,7 +1147,7 @@ void PrismUpdaterApp::downloadReleasePage(const QString& api_url, int page) download->addHeaderProxy(std::move(github_api_headers)); connect(download.get(), &Net::Download::succeeded, this, [this, response, per_page, api_url, page]() { - int num_found = parseReleasePage(response.get()); + int num_found = parseReleasePage(response); if (!(num_found < per_page)) { // there may be more, fetch next page downloadReleasePage(api_url, page + 1); } else {