|
@@ -0,0 +1,302 @@
|
|
|
+#include "gameres.h"
|
|
|
+#include "config.h"
|
|
|
+#include "filesystem.h"
|
|
|
+
|
|
|
+#include <QString>
|
|
|
+#include <QDir>
|
|
|
+#include <QFile>
|
|
|
+#include <QTime>
|
|
|
+#include <string>
|
|
|
+
|
|
|
+GameRes::GameRes() {}
|
|
|
+GameRes::GameRes(const GameRes&) {}
|
|
|
+GameRes& GameRes::operator=(GameRes&) {}
|
|
|
+
|
|
|
+// Public functions
|
|
|
+
|
|
|
+void GameRes::openDatFile(int id) {
|
|
|
+ QStringList dat_files;
|
|
|
+ dat_files << AConfig::getInstance()->getValue("Local", "file")
|
|
|
+ << "client_general.dat"
|
|
|
+ << "client_sound.dat"
|
|
|
+ << "client_surface.dat"
|
|
|
+ << "client_highres.dat";
|
|
|
+
|
|
|
+ if (dat_files[id] == nullptr) {
|
|
|
+ emit openDatFileFinished(-100); // -100 = incorrect id
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::string filename = (app->config->getValue("Local", "folder") + "/" + dat_files[id]).toStdString();
|
|
|
+
|
|
|
+ qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Инициализация dat-файла. Открываем файл ", filename);
|
|
|
+ int dat_state = app->datfiles[id].InitDatFile(file, 0);
|
|
|
+ qDebug("%s:%i: %s%d", __FILE__, __LINE__, "Состояние dat-файла: ", dat_state);
|
|
|
+
|
|
|
+ emit openDatFileFinished(dat_state);
|
|
|
+}
|
|
|
+
|
|
|
+void GameRes::closeDatFile(int id) {
|
|
|
+ int result = datfiles[id].CloseDatFile();
|
|
|
+ emit closeDatFileFinished(result);
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+void GameRes::applyPatch(QString name) {
|
|
|
+ emit startedPatching(name);
|
|
|
+
|
|
|
+ qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Начинаем применение патча ", app->helper->stringToChar(name));
|
|
|
+ QLabel* label = app->window->findChild<QLabel*>(name + "Status");
|
|
|
+ QDir dir(QApplication::applicationDirPath() + "/data");
|
|
|
+
|
|
|
+ if (!dir.exists()) {
|
|
|
+ emit applyAllFinished(-100); // -100 - not found data folder
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ QStringList paths = dir.entryList(QStringList(name + "*"));
|
|
|
+ qDebug() << ("data/" + paths.first()).toStdString();
|
|
|
+
|
|
|
+ if(!paths.empty()) {
|
|
|
+ db_.InitDatabase(("data/" + paths.first()).toStdString());
|
|
|
+ int indb = db_.CountRows();
|
|
|
+ qInfo("%s:%i: %s%d", __FILE__, __LINE__, "Файлов в обновлении: ", indb);
|
|
|
+ int percent = -1;
|
|
|
+
|
|
|
+ for (int i = 0; i <= indb; i++) {
|
|
|
+ if (i * 100 / indb > percent) {
|
|
|
+ percent = i * 100 / indb;
|
|
|
+ qInfo("%s:%i: %s%d%s", __FILE__, __LINE__, "Применение обновления: ", percent, "%");
|
|
|
+ emit updatedPatchPercent(percent);
|
|
|
+ }
|
|
|
+ processFile();
|
|
|
+ }
|
|
|
+
|
|
|
+ AConfig::getInstance()->setValue("Applied", name, paths.first());
|
|
|
+ db_.CloseDatabase();
|
|
|
+ }
|
|
|
+
|
|
|
+ emit applyPatchFinished(0);
|
|
|
+}
|
|
|
+
|
|
|
+void GameRes::setGameLocale(QString locale) {
|
|
|
+ openDatFile(0);
|
|
|
+ locale_ = app->datfiles[0].current_locale();
|
|
|
+
|
|
|
+ if(locale_ == PATCHED) qDebug() << "Starting " + locale + " version. Current locale is PATCHED";
|
|
|
+ if(locale_ == ORIGINAL) qDebug() << "Starting " + locale + " version. Current locale is ORIGINAL";
|
|
|
+ if(locale_ != ORIGINAL && loc != PATCHED) qDebug() << "Starting " + locale + " version. Current locale is UNKNOWN";
|
|
|
+
|
|
|
+ if(locale == "RU" && loc != PATCHED) {qDebug()<< "Current locale Original"; app->datfiles[0].SetLocale(PATCHED); dat_locale = PATCHED;}
|
|
|
+ if(locale == "Original" && loc != ORIGINAL) {qDebug()<< "Current locale RU"; app->datfiles[0].SetLocale(ORIGINAL); dat_locale = ORIGINAL;}
|
|
|
+ closeDatFile(0);
|
|
|
+ emit setGameLocaleFinished(0);
|
|
|
+}
|
|
|
+
|
|
|
+void GameRes::startGame() {
|
|
|
+ AConfig::getInstance()->saveAllDatFiles();
|
|
|
+
|
|
|
+ QStringList args;
|
|
|
+ args << "-skiprawdownload" << "-nosplash";
|
|
|
+ if (locale_ == PATCHED)
|
|
|
+ args << "-disablePatch";
|
|
|
+
|
|
|
+ QFile f(app->config->getValue("Local", "folder") + "/TurbineLauncher.exe");
|
|
|
+ QProcess process;
|
|
|
+ if(fileExists(f.fileName())){
|
|
|
+ if (f.fileName().contains(" "))
|
|
|
+ f.setFileName("\"" + f.fileName() + "\"");
|
|
|
+
|
|
|
+ process.startDetached(f.fileName(), args);
|
|
|
+ process.waitForFinished(-1);
|
|
|
+ process.deleteLater();
|
|
|
+ QApplication::quit();
|
|
|
+ emit startGameFinished(0);
|
|
|
+ } else {
|
|
|
+ //QString text = "Запуск не удался";
|
|
|
+ //QString info = "Не удалось запустить игру. Во время запуска произшла непредвиденная ошибка (возможно, не найден файл TurbineLauncher.exe в папке с игрой. Проверьте в 'Настройках', что у вас указан верный путь к игре, и повторите попытку запуска).";
|
|
|
+ //app->helper->myDialogBox(text, info, "OK", "Отмена", "gandalf.png", "", "", 400, 160, true, false);
|
|
|
+ emit startGameFinished(-100);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void GameRes::installMicroPatch() {
|
|
|
+ prepareMicroPatch();
|
|
|
+ applyMicroPatch();
|
|
|
+ QDir dir("/data/micro");
|
|
|
+ FileSystem::clearFolder(dir);
|
|
|
+ emit installMicroPatchFinished(0);
|
|
|
+}
|
|
|
+
|
|
|
+void GameRes::applyAll() {
|
|
|
+ // Применяем патч с заставочными экранами
|
|
|
+ if(AConfig::getInstance()->getValue("Editor", "screens") == "true") {
|
|
|
+ applyLoadscreens();
|
|
|
+ }
|
|
|
+
|
|
|
+ // Применяем остальные патчи
|
|
|
+ QStringList names;
|
|
|
+ names << "fonts" << "sounds" << "texts" << "images" << "videos" << "textures";
|
|
|
+
|
|
|
+ QDir dir(QApplication::applicationDirPath() + "/data");
|
|
|
+ QStringList need;
|
|
|
+
|
|
|
+ foreach(QString name, names){
|
|
|
+ QStringList list = dir.entryList(QStringList(name + "*"));
|
|
|
+ if(list.size() > 0 && list.first() != ""){
|
|
|
+ QString isset = app->config->getValue("Applied", name);
|
|
|
+ if(list.first() != isset && app->config->getValue("Editor", name) == "true") {
|
|
|
+ need.append(name);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(need.size() > 0){
|
|
|
+ openDatFile(0);
|
|
|
+ foreach(QString name, need) {
|
|
|
+ applyPatch(name);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(app->config->getValue("Updates", "micro") == "true")
|
|
|
+ installMicroPatch();
|
|
|
+
|
|
|
+ emit applyAllFinished(0);
|
|
|
+}
|
|
|
+
|
|
|
+void GameRes::checkDatFile() {
|
|
|
+ openDatFile(0);
|
|
|
+ if(datfiles_[0].CheckIfUpdatedByGame()){
|
|
|
+ emit checkDatFileFinished(1);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(datfiles_[0].CheckIfNotPatched() && AConfig::getInstance()->getValue("Local", "runfirst") == "1"){
|
|
|
+ emit checkDatFileFinished(2);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(datfiles_[0].CheckIfPatchedByOldLauncher()){
|
|
|
+ emit checkDatFileFinished(3);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// Private functions
|
|
|
+
|
|
|
+void GameRes::processFile() {
|
|
|
+ SubfileData subfile;
|
|
|
+ subfile = app->db->GetNextFile();
|
|
|
+ if (subfile.Empty()){
|
|
|
+ qInfo("%s:%i: %s", __FILE__, __LINE__, "Достигнут конец файла.");
|
|
|
+ } else {
|
|
|
+ int dat_id = subfile.options["did"].as<int>();
|
|
|
+ int dat_state = datfiles_[dat_id].InitDatFile(AConfig::getInstance()->getDatPath(dat_id), dat_id);
|
|
|
+ if(dat_state > 0)
|
|
|
+ datfiles_[dat_id].PatchFile(subfile);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void GameRes::prepareMicroPatch() {
|
|
|
+ QString date = AConfig::getInstance()->getValue("Updates", "update");
|
|
|
+
|
|
|
+ if(date == "false")
|
|
|
+ date = QDate::currentDate().toString("yyyy-MM-dd");
|
|
|
+
|
|
|
+ QTime time = QTime::currentTime();
|
|
|
+ int seconds = QTime(0, 0, 0).secsTo(time);
|
|
|
+ int timestamp = app->helper->dateToTimestamp(date + " " + time.toString("hh:mm:ss"), "yyyy-MM-dd hh:mm:ss") - 2592000;
|
|
|
+
|
|
|
+ qInfo("%s:%i: %s", __FILE__, __LINE__, "Опция активна. Начинаем загрузку обновлений");
|
|
|
+ app->network->micropatch = QApplication::applicationDirPath() + "/data/micro/" + QString::number(timestamp + seconds) + ".db";
|
|
|
+
|
|
|
+ if(!app->helper->fileExists(app->network->micropatch)){
|
|
|
+ qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Файл патча: ", app->helper->stringToChar(app->network->micropatch));
|
|
|
+ app->network->micropatch = app->network->getMicroPath(timestamp);
|
|
|
+ }
|
|
|
+ qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
|
|
|
+}
|
|
|
+
|
|
|
+void GameRes::applyMicroPatch() {
|
|
|
+ emit startedPatching(" новые переводы");
|
|
|
+
|
|
|
+ db_.InitDatabase(app->helper->stringToChar(app->network->micropatch));
|
|
|
+ qInfo("%s:%i: %s%d", __FILE__, __LINE__, "Файлов в обновлении: ", indb);
|
|
|
+ int indb = app->db->CountRows();
|
|
|
+ int percent = -1;
|
|
|
+
|
|
|
+ for(int i = 0; i <= indb; i++) {
|
|
|
+ if (i * 100 / indb > percent) {
|
|
|
+ percent = i * 100 / indb;
|
|
|
+ qInfo("%s:%i: %s%d%s", __FILE__, __LINE__, "Применение обновления: ", percent, "%");
|
|
|
+ emit updatedPatchPercent(percent);
|
|
|
+ }
|
|
|
+ processFile();
|
|
|
+ }
|
|
|
+
|
|
|
+ db_.CloseDatabase();
|
|
|
+ qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
|
|
|
+}
|
|
|
+
|
|
|
+void GameRes::applyLoadscreens() {
|
|
|
+ QString datafolder = QApplication::applicationDirPath() + "/data";
|
|
|
+ QDir dir(datafolder);
|
|
|
+ if (!dir.exists())
|
|
|
+ return;
|
|
|
+
|
|
|
+ QStringList paths = dir.entryList(QStringList("loadscreens*"));
|
|
|
+
|
|
|
+ if(!paths.empty()){
|
|
|
+ if(paths.first() == AConfig::getInstance()->getValue("Applied", "screens")){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ QString lang = AConfig::getInstance()->getValue("Local", "lang");
|
|
|
+ QString folder = AConfig::getInstance()->getValue("Local", "folder") + "/raw/" + lang + "/logo/";
|
|
|
+ SubfileData subfile;
|
|
|
+ QStringList filenames;
|
|
|
+ QString mainscreen = (lang == "en" ? "lotro_ad_pregame.jpg" : "lotro_ad_pregame_" + lang + ".jpg");
|
|
|
+ filenames << mainscreen << "lotro_generic_teleport_screen_01.jpg" << "lotro_generic_teleport_screen_02.jpg"
|
|
|
+ << "lotro_generic_teleport_screen_03.jpg" << "lotro_generic_teleport_screen_04.jpg" << "lotro_generic_teleport_screen_05.jpg"
|
|
|
+ << "lotro_generic_teleport_screen_06.jpg" << "lotro_generic_teleport_screen_07.jpg" << "lotro_generic_teleport_screen_08.jpg"
|
|
|
+ << "lotro_generic_teleport_screen_09.jpg" << "lotro_generic_teleport_screen_10.jpg";
|
|
|
+
|
|
|
+ QString basename = datafolder + "/" + paths.first();
|
|
|
+ db_.InitDatabase(basename.toStdString());
|
|
|
+ int indb = db_.CountRows();
|
|
|
+ qInfo("%s:%i: %s%d", __FILE__, __LINE__, "Файлы загрузочных экранов: ", indb);
|
|
|
+
|
|
|
+ for (int i = 0; i < indb; i++) {
|
|
|
+ subfile = db_.GetNextFile();
|
|
|
+ qDebug() << i;
|
|
|
+ if (!subfile.Empty()){
|
|
|
+ qInfo("%s:%i: %s", __FILE__, __LINE__, (folder + filenames[i]).toStdString().c_str());
|
|
|
+ QFile::remove(folder + filenames[i]);
|
|
|
+ subfile.binary_data.WriteToFile((folder + filenames[i]).toStdString());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ db_.CloseDatabase();
|
|
|
+ }
|
|
|
+ qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
|
|
|
+}
|
|
|
+
|
|
|
+bool GameRes::isDatReady() { // Checks if file is ready to write data
|
|
|
+ bool free = false;
|
|
|
+ QString dir = AConfig::getInstance()->getValue("Local", "folder");
|
|
|
+ QString file = AConfig::getInstance()->getValue("Local", "file");
|
|
|
+ QFile fl(dir+"/" + file);
|
|
|
+ qDebug() << fl.fileName();
|
|
|
+
|
|
|
+ if(FileSystem::fileExists(fl.fileName())){
|
|
|
+ QDir game_dir(dir);
|
|
|
+ free = game_dir.rename(fl.fileName(), fl.fileName() + "99");
|
|
|
+ game_dir.rename(fl.fileName() + "99", fl.fileName());
|
|
|
+ } else {
|
|
|
+ free = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (free == true)
|
|
|
+ qDebug() << "Dat is FREE"; else qDebug() << "Dat is BUSY";
|
|
|
+
|
|
|
+ return free;
|
|
|
+}
|