|
@@ -1,6 +1,5 @@
|
|
|
#include "patchinstaller.h"
|
|
|
#include "models/filesystem.h"
|
|
|
-#include "models/downloader.h"
|
|
|
#include "models/settings.h"
|
|
|
|
|
|
#include <QDebug>
|
|
@@ -48,13 +47,17 @@ bool PatchInstaller::datPathIsRelevant() {
|
|
|
}
|
|
|
|
|
|
void PatchInstaller::deinit() {
|
|
|
- emit operationStarted("deinitializeManager");
|
|
|
+ emit started();
|
|
|
client_local_file_->Deinit();
|
|
|
client_general_file_->Deinit();
|
|
|
- emit operationFinished("deinitializeManager");
|
|
|
+ emit finished();
|
|
|
}
|
|
|
|
|
|
-void PatchInstaller::installPatch(QString patch_name, LOTRO_DAT::Database& database) {
|
|
|
+void PatchInstaller::installPatch(QString patch_name, LOTRO_DAT::Database* database) {
|
|
|
+ if (!Settings::getValue("DatabaseNeedInstall/" + patch_name).toBool()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
if (patch_name == "loadscreen") {
|
|
|
installLoadscreens(database);
|
|
|
return;
|
|
@@ -70,17 +73,17 @@ void PatchInstaller::installPatch(QString patch_name, LOTRO_DAT::Database& datab
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- size_t patched_files_num = 0;
|
|
|
-
|
|
|
LOTRO_DAT::SubfileData file;
|
|
|
- int i = 0;
|
|
|
- const int total_files = database.CountRows();
|
|
|
- qDebug() << "Patching all files from database...";
|
|
|
- while (!(file = database.GetNextFile()).Empty()) {
|
|
|
- if (i * 100 / total_files != (i - 1) * 100 / total_files) {
|
|
|
- qDebug() << "Completed " << i * 100 / total_files << "%";
|
|
|
+ qDebug() << "Total files in database " << database->CountRows();
|
|
|
+ qDebug() << "Patching all files from database..." << database;
|
|
|
+ while (!(file = database->GetNextFile()).Empty()) {
|
|
|
+
|
|
|
+ current_status.finished_parts++;
|
|
|
+ if (current_status.finished_parts * 100 / current_status.total_parts !=
|
|
|
+ (current_status.finished_parts - 1) * 100 * 10 / current_status.total_parts) {
|
|
|
+
|
|
|
+ emit progressChanged(current_status);
|
|
|
}
|
|
|
- ++i;
|
|
|
|
|
|
if (!file.options["fid"]) {
|
|
|
continue;
|
|
@@ -91,8 +94,7 @@ void PatchInstaller::installPatch(QString patch_name, LOTRO_DAT::Database& datab
|
|
|
if (!Settings::getValue("Components/" + component_name).toBool()) {
|
|
|
continue;
|
|
|
}
|
|
|
-
|
|
|
- const int dat_id = file.options["fid"].as<int>();
|
|
|
+ const int dat_id = file.options["did"] ? file.options["did"].as<int>() : 0;
|
|
|
|
|
|
if (dat_id == E_CLIENT_LOCAL) {
|
|
|
client_local_file_->PatchFile(file);
|
|
@@ -101,17 +103,15 @@ void PatchInstaller::installPatch(QString patch_name, LOTRO_DAT::Database& datab
|
|
|
} else {
|
|
|
qWarning() << "Unknown dat id parameter for file " << file.options["fid"].as<long long>() << " (dat id value = " << dat_id << "), SKIPPING!";
|
|
|
}
|
|
|
- ++patched_files_num;
|
|
|
}
|
|
|
Settings::setValue("DatabaseNeedInstall/" + patch_name, false);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-void PatchInstaller::installLoadscreens(LOTRO_DAT::Database& database) {
|
|
|
- if (!Settings::getValue("DatabaseNeedInstall/loadscreen").toBool() ||
|
|
|
- !Settings::getValue("Components/loadscreens").toBool())
|
|
|
- {
|
|
|
+void PatchInstaller::installLoadscreens(LOTRO_DAT::Database* database) {
|
|
|
+ if (!Settings::getValue("Components/loadscreens").toBool()) {
|
|
|
+ current_status.finished_parts += database->CountRows();
|
|
|
+ emit progressChanged(current_status);
|
|
|
Settings::setValue("DatabaseNeedInstall/loadscreen", false);
|
|
|
return;
|
|
|
}
|
|
@@ -136,31 +136,81 @@ void PatchInstaller::installLoadscreens(LOTRO_DAT::Database& database) {
|
|
|
|
|
|
QString logo_path = Settings::getValue("Lotro/game_path").toString() + "/raw/" + (locale_prefix == "English" ? "en" : locale_prefix) + "/logo/";
|
|
|
|
|
|
- for (size_t i = 0; i < qMin(size_t(loadscreens_filenames.size()), database.CountRows()); ++i) {
|
|
|
- data = database.GetNextFile();
|
|
|
+ for (size_t i = 0; i < qMin(size_t(loadscreens_filenames.size()), database->CountRows()); ++i) {
|
|
|
+ data = database->GetNextFile();
|
|
|
QFile::remove(logo_path + loadscreens_filenames[i]);
|
|
|
|
|
|
if (!data.binary_data.WriteToFile((logo_path + loadscreens_filenames[i]).toLocal8Bit())) {
|
|
|
qWarning() << "InstallLoadscreens: Cannot write to file " << logo_path + loadscreens_filenames[i];
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
+ current_status.finished_parts++;
|
|
|
+ if (current_status.finished_parts * 100 / current_status.total_parts !=
|
|
|
+ (current_status.finished_parts - 1) * 100 * 10 / current_status.total_parts) {
|
|
|
+
|
|
|
+ emit progressChanged(current_status);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
Settings::setValue("DatabaseNeedInstall/loadscreen", false);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-void PatchInstaller::installVideos(LOTRO_DAT::Database& database) {
|
|
|
+void PatchInstaller::installVideos(LOTRO_DAT::Database* database) {
|
|
|
+ current_status.finished_parts += database->CountRows();
|
|
|
+ emit progressChanged(current_status);
|
|
|
+
|
|
|
+ if (!Settings::getValue("Components/videos").toBool()) {
|
|
|
+ Settings::setValue("DatabaseNeedInstall/video", false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ video_downloaders_status.clear();
|
|
|
+ QVector<Downloader*> video_downloaders;
|
|
|
+
|
|
|
+ LOTRO_DAT::SubfileData file;
|
|
|
+ while (!(file = database->GetNextFile()).Empty()) {
|
|
|
+ if (!file.options["name"] || !file.options["url"] || !file.options["hash"] || !file.options["folder"]) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ const QString filename = QString::fromStdString(file.options["name"].as<std::string>());
|
|
|
+ const QString url = QString::fromStdString(file.options["url"].as<std::string>());
|
|
|
+ const QString hash = QString::fromStdString(file.options["hash"].as<std::string>());
|
|
|
+ const QString folder = QString::fromStdString(file.options["folder"].as<std::string>());
|
|
|
+
|
|
|
+ const QString full_filename = Settings::getValue("Lotro/game_path").toString() + "/" + folder + "/" + filename;
|
|
|
+ FileSystem::createFilePath(full_filename);
|
|
|
+ if (FileSystem::fileExists(full_filename) && FileSystem::fileHash(full_filename) == hash) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ QFile target_file(full_filename);
|
|
|
+ target_file.open(QIODevice::WriteOnly);
|
|
|
+
|
|
|
+ Downloader* video_downloader = new Downloader(this);
|
|
|
+ video_downloaders_status[video_downloader] = Downloader::Status();
|
|
|
+ video_downloader->setUrl(url);
|
|
|
+ video_downloader->targetFile = &target_file;
|
|
|
+ video_downloader->start();
|
|
|
+ video_downloaders.push_back(video_downloader);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (Downloader* downloader: video_downloaders) {
|
|
|
+ downloader->waitForDownloaded();
|
|
|
+ downloader->targetFile->close();
|
|
|
+ downloader->targetFile = nullptr;
|
|
|
+ downloader->deleteLater();
|
|
|
+ }
|
|
|
+
|
|
|
+ Settings::setValue("DatabaseNeedInstall/video", false);
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PatchInstaller::init()
|
|
|
{
|
|
|
- emit operationStarted("initializeManager");
|
|
|
+ emit started();
|
|
|
qDebug() << __FUNCTION__ << "Starting initialisation of LotroDatManager";
|
|
|
+ qRegisterMetaType<PatchInstaller::Status>();
|
|
|
|
|
|
QString game_folder = Settings::getValue("Lotro/game_path").toString();
|
|
|
QString locale_prefix = Settings::getValue("Lotro/original_locale").toString();
|
|
@@ -169,8 +219,8 @@ void PatchInstaller::init()
|
|
|
QString client_general_filepath = game_folder + "/client_general.dat";
|
|
|
|
|
|
if (!FileSystem::fileExists(client_local_filepath) || !FileSystem::fileExists(client_general_filepath)) {
|
|
|
- emit errorOccured("initializeManager", {}, "DatFilesNotFound");
|
|
|
- emit operationFinished("initializeManager", {}, false);
|
|
|
+ qCritical() << __FUNCTION__ << "DatFiles do not exist!" << client_local_filepath << " " << client_general_filepath;
|
|
|
+ emit finished();
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -196,10 +246,8 @@ void PatchInstaller::init()
|
|
|
client_local_file_->Deinit();
|
|
|
client_general_file_->Deinit();
|
|
|
|
|
|
- qDebug() << __FUNCTION__ << "Finished LotroDatManager initialisation - error: DatFile initialisation error!";
|
|
|
-
|
|
|
- emit errorOccured("initializeManager", {}, "DatInitError");
|
|
|
- emit operationFinished("initializeManager", {}, false);
|
|
|
+ qCritical() << __FUNCTION__ << "Finished LotroDatManager initialisation - error: DatFile initialisation error!";
|
|
|
+ emit finished();
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -207,45 +255,41 @@ void PatchInstaller::init()
|
|
|
<< QString::fromStdString(client_general_file_->GetFilename())
|
|
|
<< QString::fromStdString(client_local_file_->GetFilename());
|
|
|
|
|
|
- emit operationFinished("initializeManager", {}, true);
|
|
|
+ emit finished();
|
|
|
}
|
|
|
|
|
|
void PatchInstaller::startGame(bool freeze_updates) {
|
|
|
|
|
|
|
|
|
|
|
|
- emit operationStarted("startGame");
|
|
|
+ emit started();
|
|
|
|
|
|
QString game_folder = Settings::getValue("Lotro/game_path").toString();
|
|
|
|
|
|
if (game_folder == "none") {
|
|
|
- qDebug() << __FUNCTION__ << "Starting game FAILED - game folder wasnt set!";
|
|
|
- emit errorOccured("startGame", {}, "GameFolderNotSet");
|
|
|
- emit operationFinished("startGame", {}, false);
|
|
|
+ qCritical() << __FUNCTION__ << "Starting game FAILED - game folder wasnt set!";
|
|
|
+ emit finished();
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (!FileSystem::fileExists(QApplication::applicationDirPath() + "/Launcher.exe")) {
|
|
|
- qDebug() << __FUNCTION__ << "Starting game FAILED - no game launcher in legacy directory found!";
|
|
|
- emit errorOccured("startGame", {}, "NoGameLauncherInLegacyDir");
|
|
|
- emit operationFinished("startGame", {}, false);
|
|
|
+ qCritical() << __FUNCTION__ << "Starting game FAILED - no game launcher in legacy directory found!";
|
|
|
+ emit finished();
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (freeze_updates) {
|
|
|
QFile::remove(game_folder + "/lotro_ru.exe");
|
|
|
if (!QFile::copy(QApplication::applicationDirPath() + "/LotroLauncher.exe", game_folder + "/lotro_ru.exe")) {
|
|
|
- qDebug() << __FUNCTION__ << "Starting game FAILED - cannot copy LotroLauncher to lotro_ru.exe!!";
|
|
|
- emit errorOccured("startGame", {}, "LauncherCopyFailed");
|
|
|
- emit operationFinished("startGame", {}, false);
|
|
|
+ qCritical() << __FUNCTION__ << "Starting game FAILED - cannot copy LotroLauncher to lotro_ru.exe!!";
|
|
|
+ emit finished();
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
QFile::remove(game_folder + "/LotroLauncher.exe");
|
|
|
if (!QFile::copy(QApplication::applicationDirPath() + "/Launcher.exe", game_folder + "/LotroLauncher.exe")) {
|
|
|
- qDebug() << __FUNCTION__ << "Starting game FAILED - cannot copy GameLauncher to LotroLauncher!!";
|
|
|
- emit errorOccured("startGame", {}, "NoAccessToGameLauncher");
|
|
|
- emit operationFinished("startGame", {}, false);
|
|
|
+ qCritical() << __FUNCTION__ << "Starting game FAILED - cannot copy GameLauncher to LotroLauncher!!";
|
|
|
+ emit finished();
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -257,9 +301,8 @@ void PatchInstaller::startGame(bool freeze_updates) {
|
|
|
} else {
|
|
|
QFile::remove(game_folder + "/LotroLauncher.exe");
|
|
|
if (!QFile::copy(QApplication::applicationDirPath() + "/LotroLauncher.exe", game_folder + "/LotroLauncher.exe")) {
|
|
|
- qDebug() << __FUNCTION__ << "Starting game FAILED - cannot copy LotroLauncher from working dir to LotroLauncher in lotro dir!!";
|
|
|
- emit errorOccured("startGame", {}, "NoAccessToGameLauncher");
|
|
|
- emit operationFinished("startGame", {}, false);
|
|
|
+ qCritical() << __FUNCTION__ << "Starting game FAILED - cannot copy LotroLauncher from working dir to LotroLauncher in lotro dir!!";
|
|
|
+ emit finished();
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
@@ -301,11 +344,62 @@ void PatchInstaller::startGame(bool freeze_updates) {
|
|
|
QApplication::quit();
|
|
|
}
|
|
|
|
|
|
- emit operationFinished("startGame");
|
|
|
+ emit finished();
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
void PatchInstaller::startPatchInstallationChain() {
|
|
|
+ emit started();
|
|
|
+ qInfo() << "PatchInstaller: Starting installation chain...";
|
|
|
+ const QVector<QString> patches = {"text", "font", "image", "loadscreen", "texture", "sound", "video", "micro"};
|
|
|
+ QMap<QString, LOTRO_DAT::Database*> patch_databases;
|
|
|
+
|
|
|
+ current_status.total_parts = 0;
|
|
|
+ current_status.finished_parts = 0;
|
|
|
+
|
|
|
+ for (const QString& patch: patches) {
|
|
|
+ if (!Settings::getValue("DatabaseNeedInstall/" + patch).toBool()) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ const QString patch_hashsum = Settings::getValue("PatchDatabases/" + patch + "/hashsum").toString();
|
|
|
+ const QString patch_filename = Settings::getValue("PatchDatabases/" + patch + "/path").toString();
|
|
|
+
|
|
|
+ const QString real_file_hashsum = FileSystem::fileHash(patch_filename);
|
|
|
+ if (!FileSystem::fileExists(patch_filename) || real_file_hashsum != patch_hashsum) {
|
|
|
+ qCritical() << "PatchInstallation: Incorrect patch file: " << patch_filename << ", hashsum: " << real_file_hashsum << ", expected: " << patch_hashsum;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
|
|
|
+ LOTRO_DAT::Database* db = new LOTRO_DAT::Database();
|
|
|
+ if (!db->InitDatabase(patch_filename.toStdString())) {
|
|
|
+ qCritical() << "PatchInstallation: failed to initialize db " << patch_filename;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ LOTRO_DAT::SubfileData data = db->GetNextFile();
|
|
|
+ patch_databases[patch] = db;
|
|
|
+ current_status.total_parts += db->CountRows();
|
|
|
+ }
|
|
|
+
|
|
|
+ emit progressChanged(current_status);
|
|
|
+ for (const QString patch_name: patch_databases.keys()) {
|
|
|
+ qInfo() << "PatchInstaller: Installing patch " << patch_name;
|
|
|
+ installPatch(patch_name, patch_databases[patch_name]);
|
|
|
+ patch_databases[patch_name]->CloseDatabase();
|
|
|
+ delete patch_databases[patch_name];
|
|
|
+ }
|
|
|
+
|
|
|
+ qInfo() << "PatchInstaller: Finished installation chain...";
|
|
|
+ emit finished();
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void PatchInstaller::onDownloaderProgressChanged(Downloader* context, Downloader::Status progress) {
|
|
|
+ video_downloaders_status[context] = progress;
|
|
|
+
|
|
|
+ Downloader::Status cumulative_status;
|
|
|
+ for (const Downloader::Status& status: video_downloaders_status.values()) {
|
|
|
+ cumulative_status = cumulative_status + status;
|
|
|
+ }
|
|
|
+ emit videosDownloadProgressChanged(cumulative_status);
|
|
|
}
|