Forráskód Böngészése

GameRes and FileSystem classes added. They contain some functions from Helper class

Ivan Arkhipov 7 éve
szülő
commit
123ed78785
4 módosított fájl, 410 hozzáadás és 0 törlés
  1. 17 0
      filesystem.cpp
  2. 15 0
      filesystem.h
  3. 302 0
      gameres.cpp
  4. 76 0
      gameres.h

+ 17 - 0
filesystem.cpp

@@ -0,0 +1,17 @@
+#include "filesystem.h"
+#include <QFile>
+#include <QFileInfo>
+
+static bool FileSystem::fileExists(QString path) {
+    QFileInfo check_file(path);
+    bool exists = check_file.exists() && check_file.isFile();
+
+    if(exists == false)
+        qWarning("%s:%i: %s%s", __FILE__, __LINE__, "Файл не найден: ", app->helper->stringToChar(path));
+
+    return exists;
+}
+
+static QString FileSystem::fileHash(const QString &fileName, QCryptographicHash::Algorithm hashAlgorithm);
+
+static void FileSystem::clearFolder(QDir &dir);

+ 15 - 0
filesystem.h

@@ -0,0 +1,15 @@
+#ifndef FILESYSTEM_H
+#define FILESYSTEM_H
+
+class FileSystem
+{
+    // Static class, which gives some extra functions for files/folders manipulation
+private:
+    FileSystem() = default;
+public:
+    static bool fileExists(QString path);
+    static QString fileHash(const QString &fileName, QCryptographicHash::Algorithm hashAlgorithm);
+    static void clearFolder(QDir &dir);
+};
+
+#endif // FILESYSTEM_H

+ 302 - 0
gameres.cpp

@@ -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;
+}

+ 76 - 0
gameres.h

@@ -0,0 +1,76 @@
+#ifndef GAMERES_H
+#define GAMERES_H
+
+#include <QObject>
+#include <QThread>
+#include <LotroDat.h>
+using namespace LOTRO_DAT;
+
+class GameRes : public QObject {
+Q_OBJECT
+
+    // Singleton realisation of class
+private:
+    GameRes();
+    GameRes(const GameRes&);
+    GameRes& operator=(GameRes&);
+
+public:
+    GameRes* getInstance() {
+        static GameRes instance;
+        return instance;
+    }
+
+    // Basic public functions
+public:
+    void openDatFile(int id);               // Opens .dat file by its id (0-local_English.dat)
+
+    void closeDatFile(int id);              // Closes .dat file by its id
+
+    void applyPatch(QString name);          // Applies patch by its name (sounds/texts/images/videos/textures/loadscreens)
+
+    void setGameLocale(QString locale);     // Sets locale by its name (Original/RU)
+
+    void startGame();                       // Starts detatched game application process
+
+    void installMicroPatch();               // Installs latest micro-patch
+
+    void applyAll();                        // Installs all patches (applyGlobal)
+
+    bool isBusy() {}                        // !!!!TO BE DONE Returns true if operations with game res are working now
+
+    void checkDatFile();                    // Checks and returns information if dat file is clear/updated
+
+signals:
+    // Signals for every public function finish. Gives result int value.
+    void openDatFileFinished(int result);
+    void closeDatFileFinished(int result);
+    void applyPatchFinished(int result);
+    void setGameLocaleFinished(int result);
+    void startGameFinished(int result);
+    void installMicroPatchFinished(int result);
+    void applyAllFinished(int result);
+    void checkDatFileFinished(int result);
+
+    // Signals for gui updating - describe process of patching.
+    void startedPatching(QString patchname);
+    void updatedPatchPercent(int percent);
+    void finishedPatching(QString patchname, QString result);
+
+private:
+    void processFile();
+    void prepareMicroPatch();
+    void applyMicroPatch();
+    void applyLoadscreens();
+    void saveLocale(int locale, QPushButton *button);
+    bool isDatReady(); // Checks if file is ready to write data
+
+private:
+    QThread *thread_;
+    bool busy_;
+    DatFile datfiles_[5];
+    Database db_;
+    LOCALE locale_;
+};
+
+#endif // GAMERES_H