1
Fork 0
mirror of https://github.com/redstrate/Astra.git synced 2025-04-24 05:17:46 +00:00

Add Dalamud asset updating support

Note: Our Dalamud injection DOES not use this yet.
This commit is contained in:
Joshua Goins 2022-02-25 18:08:57 -05:00
parent c081f92d39
commit 511763e33f
6 changed files with 168 additions and 13 deletions

View file

@ -5,14 +5,20 @@
#include <QJsonObject> #include <QJsonObject>
#include <QNetworkReply> #include <QNetworkReply>
#include <QStandardPaths> #include <QStandardPaths>
#include <QJsonArray>
#include <quazip/JlCompress.h> #include <quazip/JlCompress.h>
#include "launchercore.h" #include "launchercore.h"
const QString dalamudRemotePath = "https://goatcorp.github.io/dalamud-distrib/"; const QString baseGoatcorpDomain = "https://goatcorp.github.io";
const QString dalamudVersion = "latest";
const QString dalamudVersionPath = dalamudRemotePath + "version"; const QString dalamudRemotePath = baseGoatcorpDomain + "/dalamud-distrib";
const QString dalamudVersion = "/latest";
const QString dalamudVersionPath = dalamudRemotePath + "/version";
const QString dalamudAssetRemotePath = baseGoatcorpDomain + "/DalamudAssets";
const QString dalamudAssetManifestPath = dalamudAssetRemotePath + "/asset.json";
const QString nativeLauncherRemotePath = const QString nativeLauncherRemotePath =
"https://github.com/redstrate/nativelauncher/releases/download/"; "https://github.com/redstrate/nativelauncher/releases/download/";
@ -26,6 +32,12 @@ AssetUpdater::AssetUpdater(LauncherCore& launcher) : launcher(launcher) {
} }
void AssetUpdater::update(const ProfileSettings& profile) { void AssetUpdater::update(const ProfileSettings& profile) {
// non-dalamud users can bypass this process since it's not needed
if(!profile.enableDalamud) {
finishedUpdating();
return;
}
const QString dataDir = const QString dataDir =
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
@ -54,6 +66,99 @@ void AssetUpdater::update(const ProfileSettings& profile) {
} }
} }
{
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);
auto reply = launcher.mgr->get(request);
connect(reply, &QNetworkReply::finished, [reply, this, profile] {
// lol, they actually provide invalid json. let's fix it if it's borked
QString badJson = reply->readAll();
qInfo() << reply->errorString();
qInfo() << "Got asset manifest: " << badJson;
auto lastCommaLoc = badJson.lastIndexOf(',');
auto lastBracketLoc = badJson.lastIndexOf('{');
qInfo() << "Location of last comma: " << lastCommaLoc;
qInfo() << "Location of last bracket: " << lastBracketLoc;
// basically, if { supersedes the last ,
if (lastCommaLoc > lastBracketLoc) {
qInfo() << "Dalamud server gave bad json, attempting to fix...";
badJson.remove(lastCommaLoc, 1);
} else {
qInfo() << "Got valid json.";
}
QJsonDocument doc = QJsonDocument::fromJson(badJson.toUtf8());
qInfo() << "Dalamud asset remote version" << doc.object()["Version"].toInt();
qInfo() << "Dalamud asset local version" << profile.dalamudAssetVersion;
remoteDalamudAssetVersion = doc.object()["Version"].toInt();
if(remoteDalamudAssetVersion != profile.dalamudAssetVersion) {
qInfo() << "Dalamud assets out of date.";
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();
}
});
}
// first we determine if we need dalamud // first we determine if we need dalamud
const bool needsDalamud = const bool needsDalamud =
profile.enableDalamud && (!hasDalamud || !isDalamudUpdated); profile.enableDalamud && (!hasDalamud || !isDalamudUpdated);
@ -62,6 +167,8 @@ void AssetUpdater::update(const ProfileSettings& profile) {
// ACLs) // ACLs)
{ {
qInfo() << "Downloading NativeLauncher..."; qInfo() << "Downloading NativeLauncher...";
doneDownloadingNativelauncher = false;
needsInstall = true;
QNetworkRequest request(nativeLauncherRemotePath + QNetworkRequest request(nativeLauncherRemotePath +
nativeLauncherVersion + nativeLauncherVersion +
@ -74,6 +181,8 @@ void AssetUpdater::update(const ProfileSettings& profile) {
// download dalamud (... duh) // download dalamud (... duh)
{ {
qInfo() << "Downloading Dalamud..."; qInfo() << "Downloading Dalamud...";
doneDownloadingDalamud = false;
needsInstall = true;
QNetworkRequest request(dalamudRemotePath + dalamudVersion + QNetworkRequest request(dalamudRemotePath + dalamudVersion +
".zip"); ".zip");
@ -81,20 +190,10 @@ void AssetUpdater::update(const ProfileSettings& profile) {
auto reply = launcher.mgr->get(request); auto reply = launcher.mgr->get(request);
reply->setObjectName("Dalamud"); reply->setObjectName("Dalamud");
} }
} else {
// non-dalamud users can bypass this process since it's not needed
finishedUpdating();
} }
} }
void AssetUpdater::finishDownload(QNetworkReply* reply) { void AssetUpdater::finishDownload(QNetworkReply* reply) {
const auto checkIfFinished = [=] {
if (QFile::exists(tempDir.path() + "/NativeLauncher.exe") &&
QFile::exists(tempDir.path() + "/latest.zip")) {
beginInstall();
}
};
if (reply->objectName() == "Dalamud") { if (reply->objectName() == "Dalamud") {
qInfo() << "Dalamud finished downloading!"; qInfo() << "Dalamud finished downloading!";
@ -103,6 +202,7 @@ void AssetUpdater::finishDownload(QNetworkReply* reply) {
file.write(reply->readAll()); file.write(reply->readAll());
file.close(); file.close();
doneDownloadingDalamud = true;
checkIfFinished(); checkIfFinished();
} else if (reply->objectName() == "NativeLauncher") { } else if (reply->objectName() == "NativeLauncher") {
qInfo() << "NativeLauncher finished downloading!"; qInfo() << "NativeLauncher finished downloading!";
@ -112,6 +212,7 @@ void AssetUpdater::finishDownload(QNetworkReply* reply) {
file.write(reply->readAll()); file.write(reply->readAll());
file.close(); file.close();
doneDownloadingNativelauncher = true;
checkIfFinished(); checkIfFinished();
} else if (reply->objectName() == "DalamudVersionCheck") { } else if (reply->objectName() == "DalamudVersionCheck") {
QByteArray str = reply->readAll(); QByteArray str = reply->readAll();
@ -151,3 +252,29 @@ void AssetUpdater::beginInstall() {
// STUB: install failure // STUB: install failure
} }
} }
void AssetUpdater::checkIfDalamudAssetsDone() {
if(dalamudAssetNeededFilenames.empty()) {
qInfo() << "Finished downloading Dalamud assets.";
const QString dataDir =
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/DalamudAssets/";
QFile file(dataDir + "asset.ver");
file.open(QIODevice::WriteOnly | QIODevice::Text);
file.write(QString::number(remoteDalamudAssetVersion).toUtf8());
file.close();
checkIfFinished();
}
}
void AssetUpdater::checkIfFinished() {
if (doneDownloadingDalamud &&
doneDownloadingNativelauncher &&
dalamudAssetNeededFilenames.empty()) {
if(needsInstall)
beginInstall();
else
finishedUpdating();
}
}

View file

@ -16,6 +16,9 @@ public:
void finishDownload(QNetworkReply* reply); void finishDownload(QNetworkReply* reply);
void beginInstall(); void beginInstall();
void checkIfDalamudAssetsDone();
void checkIfFinished();
signals: signals:
void finishedUpdating(); void finishedUpdating();
@ -27,4 +30,11 @@ private:
QString remoteDalamudVersion; QString remoteDalamudVersion;
QTemporaryDir tempDir; QTemporaryDir tempDir;
bool doneDownloadingDalamud = true;
bool doneDownloadingNativelauncher = true;
bool needsInstall = false;
int remoteDalamudAssetVersion;
QList<QString> dalamudAssetNeededFilenames;
}; };

View file

@ -323,6 +323,13 @@ void LauncherCore::readInitialInformation() {
.filter("Dalamud")[0]; .filter("Dalamud")[0];
profile.dalamudVersion = versionString.remove("Dalamud/"); profile.dalamudVersion = versionString.remove("Dalamud/");
} }
if(QFile::exists(dataDir + "/DalamudAssets/asset.ver")) {
QFile assetJson(dataDir + "/DalamudAssets/asset.ver");
assetJson.open(QFile::ReadOnly | QFile::Text);
profile.dalamudAssetVersion = QString(assetJson.readAll()).toInt();
}
} }
if(settings.contains("gamePath") && settings.value("gamePath").canConvert<QString>() && !settings.value("gamePath").toString().isEmpty()) { if(settings.contains("gamePath") && settings.value("gamePath").canConvert<QString>() && !settings.value("gamePath").toString().isEmpty()) {

View file

@ -48,6 +48,7 @@ struct ProfileSettings {
} gamescope; } gamescope;
QString dalamudVersion; // TODO: move out of profile settings QString dalamudVersion; // TODO: move out of profile settings
int dalamudAssetVersion = -1;
// login // login
bool encryptArguments = true; bool encryptArguments = true;

View file

@ -372,6 +372,9 @@ SettingsWindow::SettingsWindow(LauncherWindow& window, LauncherCore& core, QWidg
dalamudVersionLabel = new QLabel(); dalamudVersionLabel = new QLabel();
dalamudBoxLayout->addRow("Dalamud Version", dalamudVersionLabel); dalamudBoxLayout->addRow("Dalamud Version", dalamudVersionLabel);
dalamudAssetVersionLabel = new QLabel();
dalamudBoxLayout->addRow("Dalamud Asset Version", dalamudAssetVersionLabel);
} }
reloadControls(); reloadControls();
@ -478,6 +481,12 @@ void SettingsWindow::reloadControls() {
dalamudVersionLabel->setText(profile.dalamudVersion); dalamudVersionLabel->setText(profile.dalamudVersion);
} }
if(profile.dalamudAssetVersion == -1) {
dalamudAssetVersionLabel->setText("Dalamud assets are not installed.");
} else {
dalamudAssetVersionLabel->setText(QString::number(profile.dalamudAssetVersion));
}
window.reloadControls(); window.reloadControls();
currentlyReloadingControls = false; currentlyReloadingControls = false;

View file

@ -54,6 +54,7 @@ private:
// dalamud // dalamud
QCheckBox* enableDalamudBox = nullptr; QCheckBox* enableDalamudBox = nullptr;
QLabel* dalamudVersionLabel = nullptr; QLabel* dalamudVersionLabel = nullptr;
QLabel* dalamudAssetVersionLabel = nullptr;
bool currentlyReloadingControls = false; bool currentlyReloadingControls = false;