mirror of
https://github.com/redstrate/Astra.git
synced 2025-04-20 11:47:46 +00:00
Overhauled asset updating process (again)
Now the code is much cleaner, should be less error prone. And best of all, the process is now user-visible in a nice progress box.
This commit is contained in:
parent
065580583d
commit
d939d26280
2 changed files with 246 additions and 220 deletions
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QTemporaryDir>
|
||||
#include <QProgressDialog>
|
||||
#include <QJsonArray>
|
||||
|
||||
class LauncherCore;
|
||||
class QNetworkReply;
|
||||
|
@ -13,9 +15,9 @@ public:
|
|||
AssetUpdater(LauncherCore& launcher);
|
||||
|
||||
void update(const ProfileSettings& profile);
|
||||
void finishDownload(QNetworkReply* reply);
|
||||
void beginInstall();
|
||||
|
||||
void checkIfCheckingIsDone();
|
||||
void checkIfDalamudAssetsDone();
|
||||
void checkIfFinished();
|
||||
|
||||
|
@ -25,6 +27,8 @@ signals:
|
|||
private:
|
||||
LauncherCore& launcher;
|
||||
|
||||
QProgressDialog* dialog;
|
||||
|
||||
const ProfileSettings* currentSettings = nullptr;
|
||||
|
||||
QString remoteDalamudVersion;
|
||||
|
@ -40,6 +44,9 @@ private:
|
|||
bool needsDalamudInstall = false;
|
||||
bool needsNativeInstall = false;
|
||||
|
||||
int remoteDalamudAssetVersion;
|
||||
int remoteDalamudAssetVersion = -1;
|
||||
QList<QString> dalamudAssetNeededFilenames;
|
||||
QJsonArray remoteDalamudAssetArray;
|
||||
|
||||
QString dataDir;
|
||||
};
|
||||
|
|
|
@ -11,24 +11,32 @@
|
|||
|
||||
#include "launchercore.h"
|
||||
|
||||
const QString baseGoatcorpDomain = "https://goatcorp.github.io";
|
||||
const QString baseGoatDomain = "https://goatcorp.github.io";
|
||||
|
||||
const QString dalamudRemotePath = baseGoatcorpDomain + "/dalamud-distrib";
|
||||
const QString dalamudVersion = "/latest";
|
||||
const QString dalamudVersionPath = dalamudRemotePath + "/version";
|
||||
const QString baseDalamudDistribution = baseGoatDomain + "/dalamud-distrib";
|
||||
const QString dalamudLatestPackageURL = baseDalamudDistribution + "/latest.zip";
|
||||
const QString dalamudVersionManifestURL = baseDalamudDistribution + "/version";
|
||||
|
||||
const QString dalamudAssetRemotePath = baseGoatcorpDomain + "/DalamudAssets";
|
||||
const QString dalamudAssetManifestPath = dalamudAssetRemotePath + "/asset.json";
|
||||
const QString baseDalamudAssetDistribution = baseGoatDomain + "/DalamudAssets";
|
||||
const QString dalamudAssetManifestURL = baseDalamudAssetDistribution + "/asset.json";
|
||||
|
||||
const QString nativeLauncherRemotePath =
|
||||
const QString baseNativeLauncherDistribution =
|
||||
"https://github.com/redstrate/nativelauncher/releases/download/";
|
||||
const QString nativeLauncherVersion = "v1.0.0";
|
||||
const QString nativeLauncherLatestPackageURL =
|
||||
baseNativeLauncherDistribution + "/latest/NativeLauncher.exe";
|
||||
|
||||
const QString dotnetRuntimePackageURL =
|
||||
"https://dotnetcli.azureedge.net/dotnet/Runtime/%1/dotnet-runtime-%1-win-x64.zip";
|
||||
const QString dotnetDesktopPackageURL =
|
||||
"https://dotnetcli.azureedge.net/dotnet/WindowsDesktop/%1/windowsdesktop-runtime-%1-win-x64.zip";
|
||||
|
||||
AssetUpdater::AssetUpdater(LauncherCore& launcher) : launcher(launcher) {
|
||||
connect(launcher.mgr, &QNetworkAccessManager::finished, this,
|
||||
&AssetUpdater::finishDownload);
|
||||
|
||||
launcher.mgr->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy);
|
||||
|
||||
dialog = new QProgressDialog("Updating assets...", "Cancel", 0, 0);
|
||||
|
||||
dataDir =
|
||||
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
}
|
||||
|
||||
void AssetUpdater::update(const ProfileSettings& profile) {
|
||||
|
@ -38,71 +46,23 @@ void AssetUpdater::update(const ProfileSettings& profile) {
|
|||
return;
|
||||
}
|
||||
|
||||
const QString dataDir =
|
||||
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
// first, we want to collect all of the remote versions
|
||||
|
||||
qInfo() << "Starting update sequence...";
|
||||
dialog->setLabelText("Checking for updates...");
|
||||
|
||||
bool isDalamudUpdated = false;
|
||||
if (remoteDalamudVersion.isEmpty()) {
|
||||
QNetworkRequest request(dalamudVersionPath);
|
||||
|
||||
auto reply = launcher.mgr->get(request);
|
||||
reply->setObjectName("DalamudVersionCheck");
|
||||
currentSettings = &profile; // TODO: this is dirty, should change
|
||||
|
||||
return;
|
||||
} else {
|
||||
if (launcher.dalamudVersion != remoteDalamudVersion) {
|
||||
isDalamudUpdated = false;
|
||||
} else {
|
||||
qInfo() << "No need to update Dalamud.";
|
||||
isDalamudUpdated = true;
|
||||
}
|
||||
|
||||
if(launcher.runtimeVersion != remoteRuntimeVersion) {
|
||||
doneDownloadingRuntimeCore = false;
|
||||
doneDownloadingRuntimeDesktop = false;
|
||||
needsRuntimeInstall = true;
|
||||
|
||||
// core
|
||||
// dalamud assets
|
||||
{
|
||||
QNetworkRequest request(
|
||||
QString("https://dotnetcli.azureedge.net/dotnet/Runtime/%1/dotnet-runtime-%1-win-x64.zip")
|
||||
.arg(remoteRuntimeVersion));
|
||||
|
||||
auto reply = launcher.mgr->get(request);
|
||||
reply->setObjectName("Dotnet-core");
|
||||
}
|
||||
|
||||
// desktop
|
||||
{
|
||||
QNetworkRequest request(
|
||||
QString("https://dotnetcli.azureedge.net/dotnet/WindowsDesktop/%1/windowsdesktop-runtime-%1-win-x64.zip")
|
||||
.arg(remoteRuntimeVersion));
|
||||
|
||||
auto reply = launcher.mgr->get(request);
|
||||
reply->setObjectName("Dotnet-desktop");
|
||||
}
|
||||
} else {
|
||||
qInfo() << "No need to update Runtime.";
|
||||
doneDownloadingRuntimeCore = true;
|
||||
doneDownloadingRuntimeDesktop = true;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
qInfo() << "Checking Dalamud assets...";
|
||||
|
||||
// we want to prevent logging in before we actually check the version
|
||||
dalamudAssetNeededFilenames.append("dummy");
|
||||
|
||||
// first we want to fetch the list of assets required
|
||||
QNetworkRequest request(dalamudAssetManifestPath);
|
||||
QNetworkRequest request(dalamudAssetManifestURL);
|
||||
|
||||
auto reply = launcher.mgr->get(request);
|
||||
|
||||
connect(reply, &QNetworkReply::finished, [reply, this, profile] {
|
||||
dialog->setLabelText("Checking for Dalamud asset updates...");
|
||||
|
||||
// lol, they actually provide invalid json. let's fix it if it's borked
|
||||
QString badJson = reply->readAll();
|
||||
|
||||
|
@ -130,117 +90,21 @@ void AssetUpdater::update(const ProfileSettings& profile) {
|
|||
|
||||
remoteDalamudAssetVersion = doc.object()["Version"].toInt();
|
||||
|
||||
if(remoteDalamudAssetVersion != launcher.dalamudAssetVersion) {
|
||||
qInfo() << "Dalamud assets out of date.";
|
||||
remoteDalamudAssetArray = doc.object()["Assets"].toArray();
|
||||
|
||||
dalamudAssetNeededFilenames.clear();
|
||||
|
||||
for(auto assetObject : doc.object()["Assets"].toArray()) {
|
||||
{
|
||||
qInfo() << "Starting download for " << assetObject.toObject()["FileName"];
|
||||
|
||||
dalamudAssetNeededFilenames.append(assetObject.toObject()["FileName"].toString());
|
||||
|
||||
QNetworkRequest assetRequest(assetObject.toObject()["Url"].toString());
|
||||
auto assetReply = launcher.mgr->get(assetRequest);
|
||||
|
||||
connect(assetReply, &QNetworkReply::finished, [this, assetReply, assetObject = assetObject.toObject()] {
|
||||
const QString dataDir =
|
||||
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/DalamudAssets/";
|
||||
|
||||
if (!QDir().exists(dataDir))
|
||||
QDir().mkdir(dataDir);
|
||||
|
||||
const QString fileName = assetObject["FileName"].toString();
|
||||
const QList<QString> dirPath = fileName.left(fileName.lastIndexOf("/")).split('/');
|
||||
|
||||
qInfo() << "Needed directories: " << dirPath;
|
||||
|
||||
QString build = dataDir;
|
||||
for(auto dir : dirPath) {
|
||||
if (!QDir().exists(build + dir))
|
||||
QDir().mkdir(build + dir);
|
||||
|
||||
build += dir + "/";
|
||||
}
|
||||
|
||||
QFile file(dataDir + assetObject["FileName"].toString());
|
||||
file.open(QIODevice::WriteOnly);
|
||||
file.write(assetReply->readAll());
|
||||
file.close();
|
||||
|
||||
dalamudAssetNeededFilenames.removeOne(assetObject["FileName"].toString());
|
||||
checkIfDalamudAssetsDone();
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dalamudAssetNeededFilenames.clear();
|
||||
|
||||
qInfo() << "Dalamud assets up to date.";
|
||||
|
||||
checkIfFinished();
|
||||
}
|
||||
checkIfCheckingIsDone();
|
||||
});
|
||||
}
|
||||
|
||||
if(remoteDalamudVersion != launcher.dalamudVersion) {
|
||||
qInfo() << "Downloading Dalamud...";
|
||||
doneDownloadingDalamud = false;
|
||||
needsDalamudInstall = true;
|
||||
|
||||
QNetworkRequest request(dalamudRemotePath + dalamudVersion +
|
||||
".zip");
|
||||
|
||||
auto reply = launcher.mgr->get(request);
|
||||
reply->setObjectName("Dalamud");
|
||||
}
|
||||
|
||||
const bool hasNative = QFile::exists(dataDir + "/NativeLauncher.exe");
|
||||
if (!hasNative) {
|
||||
// download nativelauncher release (needed to launch the game with fixed
|
||||
// ACLs)
|
||||
// dalamud injector / net runtime / nativelauncher
|
||||
// they're all updated in unison, so there's no reason to have multiple checks
|
||||
{
|
||||
qInfo() << "Downloading NativeLauncher...";
|
||||
doneDownloadingNativelauncher = false;
|
||||
needsNativeInstall = true;
|
||||
|
||||
QNetworkRequest request(nativeLauncherRemotePath +
|
||||
nativeLauncherVersion +
|
||||
"/NativeLauncher.exe");
|
||||
QNetworkRequest request(dalamudVersionManifestURL);
|
||||
|
||||
auto reply = launcher.mgr->get(request);
|
||||
reply->setObjectName("NativeLauncher");
|
||||
}
|
||||
}
|
||||
}
|
||||
connect(reply, &QNetworkReply::finished, [this, profile, reply] {
|
||||
dialog->setLabelText("Checking for Dalamud updates...");
|
||||
|
||||
void AssetUpdater::finishDownload(QNetworkReply* reply) {
|
||||
if (reply->objectName() == "Dalamud") {
|
||||
qInfo() << "Dalamud finished downloading!";
|
||||
|
||||
QFile file(tempDir.path() + "/latest.zip");
|
||||
file.open(QIODevice::WriteOnly);
|
||||
file.write(reply->readAll());
|
||||
file.close();
|
||||
|
||||
doneDownloadingDalamud = true;
|
||||
|
||||
launcher.dalamudVersion = remoteDalamudVersion;
|
||||
|
||||
checkIfFinished();
|
||||
} else if (reply->objectName() == "NativeLauncher") {
|
||||
qInfo() << "NativeLauncher finished downloading!";
|
||||
|
||||
QFile file(tempDir.path() + "/NativeLauncher.exe");
|
||||
file.open(QIODevice::WriteOnly);
|
||||
file.write(reply->readAll());
|
||||
file.close();
|
||||
|
||||
doneDownloadingNativelauncher = true;
|
||||
|
||||
checkIfFinished();
|
||||
} else if (reply->objectName() == "DalamudVersionCheck") {
|
||||
QByteArray str = reply->readAll();
|
||||
// for some god forsaken reason, the version string comes back as raw
|
||||
// bytes, ex: \xFF\xFE{\x00\"\x00""A\x00s\x00s\x00""e\x00m\x00 so we
|
||||
|
@ -259,37 +123,12 @@ void AssetUpdater::finishDownload(QNetworkReply* reply) {
|
|||
qInfo() << "Latest Dalamud version reported: " << remoteDalamudVersion;
|
||||
qInfo() << "Latest NET runtime reported: " << remoteRuntimeVersion;
|
||||
|
||||
update(*currentSettings);
|
||||
currentSettings = nullptr;
|
||||
} else if(reply->objectName() == "Dotnet-core") {
|
||||
qInfo() << "Dotnet-core finished downloading!";
|
||||
|
||||
QFile file(tempDir.path() + "/dotnet-core.zip");
|
||||
file.open(QIODevice::WriteOnly);
|
||||
file.write(reply->readAll());
|
||||
file.close();
|
||||
|
||||
doneDownloadingRuntimeCore = true;
|
||||
|
||||
checkIfFinished();
|
||||
} else if(reply->objectName() == "Dotnet-desktop") {
|
||||
qInfo() << "Dotnet-desktop finished downloading!";
|
||||
|
||||
QFile file(tempDir.path() + "/dotnet-desktop.zip");
|
||||
file.open(QIODevice::WriteOnly);
|
||||
file.write(reply->readAll());
|
||||
file.close();
|
||||
|
||||
doneDownloadingRuntimeDesktop = true;
|
||||
|
||||
checkIfFinished();
|
||||
checkIfCheckingIsDone();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void AssetUpdater::beginInstall() {
|
||||
const QString dataDir =
|
||||
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
|
||||
if(needsDalamudInstall) {
|
||||
bool success = !JlCompress::extractDir(tempDir.path() + "/latest.zip",
|
||||
dataDir + "/Dalamud")
|
||||
|
@ -339,10 +178,7 @@ void AssetUpdater::checkIfDalamudAssetsDone() {
|
|||
|
||||
launcher.dalamudAssetVersion = remoteDalamudAssetVersion;
|
||||
|
||||
const QString dataDir =
|
||||
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/DalamudAssets/";
|
||||
|
||||
QFile file(dataDir + "asset.ver");
|
||||
QFile file(dataDir + "/DalamudAssets/" + "asset.ver");
|
||||
file.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
file.write(QString::number(remoteDalamudAssetVersion).toUtf8());
|
||||
file.close();
|
||||
|
@ -357,9 +193,192 @@ void AssetUpdater::checkIfFinished() {
|
|||
doneDownloadingRuntimeCore &&
|
||||
doneDownloadingRuntimeDesktop &&
|
||||
dalamudAssetNeededFilenames.empty()) {
|
||||
if(needsRuntimeInstall || needsNativeInstall || needsDalamudInstall)
|
||||
if (needsRuntimeInstall || needsNativeInstall || needsDalamudInstall) {
|
||||
beginInstall();
|
||||
else
|
||||
} else {
|
||||
dialog->setLabelText("Finished!");
|
||||
dialog->close();
|
||||
|
||||
finishedUpdating();
|
||||
}
|
||||
}
|
||||
}
|
||||
void AssetUpdater::checkIfCheckingIsDone() {
|
||||
if(remoteDalamudVersion.isEmpty() || remoteRuntimeVersion.isEmpty() || remoteDalamudAssetVersion == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// now that we got all the information we need, let's check if anything is
|
||||
// updateable
|
||||
|
||||
dialog->setLabelText("Starting update...");
|
||||
|
||||
// dalamud injector / net runtime
|
||||
if(launcher.runtimeVersion != remoteRuntimeVersion) {
|
||||
doneDownloadingRuntimeCore = false;
|
||||
doneDownloadingRuntimeDesktop = false;
|
||||
needsRuntimeInstall = true;
|
||||
|
||||
// core
|
||||
{
|
||||
QNetworkRequest request(dotnetRuntimePackageURL.arg(remoteRuntimeVersion));
|
||||
|
||||
auto reply = launcher.mgr->get(request);
|
||||
connect(reply, &QNetworkReply::finished, [this, reply] {
|
||||
qInfo() << "Dotnet-core finished downloading!";
|
||||
|
||||
dialog->setLabelText("Updating Dotnet-core...");
|
||||
|
||||
QFile file(tempDir.path() + "/dotnet-core.zip");
|
||||
file.open(QIODevice::WriteOnly);
|
||||
file.write(reply->readAll());
|
||||
file.close();
|
||||
|
||||
doneDownloadingRuntimeCore = true;
|
||||
|
||||
checkIfFinished();
|
||||
});
|
||||
}
|
||||
|
||||
// desktop
|
||||
{
|
||||
QNetworkRequest request(dotnetDesktopPackageURL.arg(remoteRuntimeVersion));
|
||||
|
||||
auto reply = launcher.mgr->get(request);
|
||||
connect(reply, &QNetworkReply::finished, [this, reply] {
|
||||
qInfo() << "Dotnet-desktop finished downloading!";
|
||||
|
||||
dialog->setLabelText("Updating Dotnet-desktop...");
|
||||
|
||||
QFile file(tempDir.path() + "/dotnet-desktop.zip");
|
||||
file.open(QIODevice::WriteOnly);
|
||||
file.write(reply->readAll());
|
||||
file.close();
|
||||
|
||||
doneDownloadingRuntimeDesktop = true;
|
||||
|
||||
checkIfFinished();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
doneDownloadingRuntimeCore = true;
|
||||
doneDownloadingRuntimeDesktop = true;
|
||||
needsRuntimeInstall = false;
|
||||
|
||||
checkIfFinished();
|
||||
}
|
||||
|
||||
if(remoteDalamudVersion != launcher.dalamudVersion) {
|
||||
qInfo() << "Downloading Dalamud...";
|
||||
doneDownloadingDalamud = false;
|
||||
needsDalamudInstall = true;
|
||||
|
||||
QNetworkRequest request(dalamudLatestPackageURL);
|
||||
|
||||
auto reply = launcher.mgr->get(request);
|
||||
connect(reply, &QNetworkReply::finished, [this, reply] {
|
||||
qInfo() << "Dalamud finished downloading!";
|
||||
|
||||
dialog->setLabelText("Updating Dalamud...");
|
||||
|
||||
QFile file(tempDir.path() + "/latest.zip");
|
||||
file.open(QIODevice::WriteOnly);
|
||||
file.write(reply->readAll());
|
||||
file.close();
|
||||
|
||||
doneDownloadingDalamud = true;
|
||||
|
||||
launcher.dalamudVersion = remoteDalamudVersion;
|
||||
|
||||
checkIfFinished();
|
||||
});
|
||||
} else {
|
||||
qInfo() << "No need to update Dalamud.";
|
||||
|
||||
doneDownloadingDalamud = true;
|
||||
needsDalamudInstall = false;
|
||||
|
||||
checkIfFinished();
|
||||
}
|
||||
|
||||
// dalamud assets
|
||||
if(remoteDalamudAssetVersion != launcher.dalamudAssetVersion) {
|
||||
qInfo() << "Dalamud assets out of date.";
|
||||
|
||||
dialog->setLabelText("Updating Dalamud assets...");
|
||||
|
||||
dalamudAssetNeededFilenames.clear();
|
||||
|
||||
for(auto assetObject : remoteDalamudAssetArray) {
|
||||
{
|
||||
qInfo() << "Starting download for " << assetObject.toObject()["FileName"];
|
||||
|
||||
dalamudAssetNeededFilenames.append(assetObject.toObject()["FileName"].toString());
|
||||
|
||||
QNetworkRequest assetRequest(assetObject.toObject()["Url"].toString());
|
||||
auto assetReply = launcher.mgr->get(assetRequest);
|
||||
|
||||
connect(assetReply, &QNetworkReply::finished, [this, assetReply, assetObject = assetObject.toObject()] {
|
||||
if (!QDir().exists(dataDir + "/DalamudAssets/"))
|
||||
QDir().mkdir(dataDir + "/DalamudAssets/");
|
||||
|
||||
const QString fileName = assetObject["FileName"].toString();
|
||||
const QList<QString> dirPath = fileName.left(fileName.lastIndexOf("/")).split('/');
|
||||
|
||||
qInfo() << "Needed directories: " << dirPath;
|
||||
|
||||
QString build = dataDir + "/DalamudAssets/";
|
||||
for(auto dir : dirPath) {
|
||||
if (!QDir().exists(build + dir))
|
||||
QDir().mkdir(build + dir);
|
||||
|
||||
build += dir + "/";
|
||||
}
|
||||
|
||||
QFile file(dataDir + "/DalamudAssets/" + assetObject["FileName"].toString());
|
||||
file.open(QIODevice::WriteOnly);
|
||||
file.write(assetReply->readAll());
|
||||
file.close();
|
||||
|
||||
dalamudAssetNeededFilenames.removeOne(assetObject["FileName"].toString());
|
||||
checkIfDalamudAssetsDone();
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dalamudAssetNeededFilenames.clear();
|
||||
|
||||
qInfo() << "Dalamud assets up to date.";
|
||||
|
||||
checkIfFinished();
|
||||
}
|
||||
|
||||
// nativelauncher
|
||||
const bool hasNative = QFile::exists(dataDir + "/NativeLauncher.exe");
|
||||
if (!hasNative) {
|
||||
// download nativelauncher release (needed to launch the game with fixed
|
||||
// ACLs)
|
||||
|
||||
qInfo() << "Downloading NativeLauncher...";
|
||||
doneDownloadingNativelauncher = false;
|
||||
needsNativeInstall = true;
|
||||
|
||||
QNetworkRequest request(nativeLauncherLatestPackageURL);
|
||||
|
||||
auto reply = launcher.mgr->get(request);
|
||||
connect(reply, &QNetworkReply::finished, [this, reply] {
|
||||
qInfo() << "NativeLauncher finished downloading!";
|
||||
|
||||
dialog->setLabelText("Updating Nativelauncher...");
|
||||
|
||||
QFile file(tempDir.path() + "/NativeLauncher.exe");
|
||||
file.open(QIODevice::WriteOnly);
|
||||
file.write(reply->readAll());
|
||||
file.close();
|
||||
|
||||
doneDownloadingNativelauncher = true;
|
||||
|
||||
checkIfFinished();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue