|
@@ -21,38 +21,58 @@ QString getComponentNameFromId(int id) {
|
|
|
case 202: return "textures";
|
|
|
case 300: return "sounds";
|
|
|
case 301: return "videos";
|
|
|
+ case 500: return "fonts";
|
|
|
}
|
|
|
return "none";
|
|
|
}
|
|
|
|
|
|
-PatchInstaller::PatchInstaller(QObject *parent) : QObject(parent) {
|
|
|
- client_local_file_ = new LOTRO_DAT::DatFile(100);
|
|
|
- client_general_file_ = new LOTRO_DAT::DatFile(101);
|
|
|
+void PatchInstaller::createDatFile(int id, QString name, int component, QString path){
|
|
|
+ datfiles[id] = datfile();
|
|
|
+ datfiles[id].id = id;
|
|
|
+ datfiles[id].name = name;
|
|
|
+ datfiles[id].path = path;
|
|
|
+ datfiles[id].file = new LOTRO_DAT::DatFile(component);
|
|
|
+ datfiles[id].file->Init(path.toStdString());// инициализируем
|
|
|
+ datfiles[id].init = datfiles[id].file->Initialized(); // проверяем инициализацию
|
|
|
+ if(datfiles[id].init){
|
|
|
+ datfiles[id].maxiter = datfiles[id].file->GetDatFileMaxIteration();
|
|
|
+ qInfo() << "Init" << datfiles[id].name << ", result" << datfiles[id].init << ", iterations - " << datfiles[id].maxiter;
|
|
|
+ } else {
|
|
|
+ qCritical() << "Failed CheckAppPrerequisities: initialization of " + name + " dat file failed!";
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const QMap<int, PatchInstaller::datfile>& PatchInstaller::getDatFiles(){
|
|
|
+ return this->datfiles;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+PatchInstaller::PatchInstaller(QObject *parent) : QObject(parent){
|
|
|
connect(&PatchDownloader::instance(), &PatchDownloader::finished, this, [this](){startPatchInstallationChain();});
|
|
|
}
|
|
|
|
|
|
-bool PatchInstaller::initialised() {
|
|
|
- return client_general_file_->Initialized() && client_local_file_->Initialized();
|
|
|
+bool PatchInstaller::initialised(){
|
|
|
+ foreach(datfile file, datfiles){
|
|
|
+ if(file.init == false) return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
-void PatchInstaller::checkIfUpdatedByGame()
|
|
|
-{
|
|
|
- const int client_local_maxiter = client_local_file_->GetDatFileMaxIteration();
|
|
|
- const int client_general_maxiter = client_general_file_->GetDatFileMaxIteration();
|
|
|
+void PatchInstaller::checkIfUpdatedByGame(){
|
|
|
|
|
|
const int client_local_saved_maxiter = _current_applied_patches_info.client_local_header_maxiter;
|
|
|
const int client_general_saved_maxiter = _current_applied_patches_info.client_general_header_maxiter;
|
|
|
+ const int client_surface_saved_maxiter = _current_applied_patches_info.client_surface_header_maxiter;
|
|
|
|
|
|
emit updatedByGameStatusChanged(
|
|
|
- (client_local_saved_maxiter != -1 && client_local_maxiter != client_local_saved_maxiter) ||
|
|
|
- (client_general_saved_maxiter != -1 && client_general_maxiter != client_general_saved_maxiter)
|
|
|
+ (client_local_saved_maxiter != -1 && datfiles[0].maxiter != client_local_saved_maxiter) ||
|
|
|
+ (client_general_saved_maxiter != -1 && datfiles[1].maxiter != client_general_saved_maxiter) ||
|
|
|
+ (client_surface_saved_maxiter != -1 && datfiles[3].maxiter != client_surface_saved_maxiter)
|
|
|
);
|
|
|
}
|
|
|
|
|
|
PatchInstaller::~PatchInstaller() {
|
|
|
deinit();
|
|
|
- delete client_local_file_;
|
|
|
- delete client_general_file_;
|
|
|
}
|
|
|
|
|
|
// ############## PRIVATE ############## //
|
|
@@ -63,17 +83,34 @@ bool PatchInstaller::datPathIsRelevant() {
|
|
|
|
|
|
QString client_local_filepath = game_folder + "/client_local_" + locale_prefix + ".dat";
|
|
|
QString client_general_filepath = game_folder + "/client_general.dat";
|
|
|
+ QString client_surface_filepath = game_folder + "/client_surface.dat";
|
|
|
|
|
|
- QString client_local_current_path = QString::fromStdString(client_local_file_->GetFilename());
|
|
|
- QString client_general_current_path = QString::fromStdString(client_general_file_->GetFilename());
|
|
|
+ QString client_local_current_path = QString::fromStdString(datfiles[0].file->GetFilename());
|
|
|
+ QString client_general_current_path = QString::fromStdString(datfiles[1].file->GetFilename());
|
|
|
+ QString client_surface_current_path = QString::fromStdString(datfiles[3].file->GetFilename());
|
|
|
|
|
|
return QFileInfo(client_local_filepath) != QFileInfo(client_local_current_path)
|
|
|
- || QFileInfo(client_general_filepath) != QFileInfo(client_general_current_path);
|
|
|
+ || QFileInfo(client_general_filepath) != QFileInfo(client_general_current_path)
|
|
|
+ || QFileInfo(client_surface_filepath) != QFileInfo(client_surface_current_path);
|
|
|
}
|
|
|
|
|
|
void PatchInstaller::deinit() {
|
|
|
- client_local_file_->Deinit();
|
|
|
- client_general_file_->Deinit();
|
|
|
+ if (datfiles.find(0) != datfiles.end() && datfiles[0].file) {
|
|
|
+ datfiles[0].file->Deinit(); // Сначала деинициализируем сам dat-файл
|
|
|
+ delete datfiles[0].file; // Чистим память за объектом dat-файла
|
|
|
+ datfiles.remove(0); // Удаляем служебную инфу по dat-файлу
|
|
|
+ }
|
|
|
+ if (datfiles.find(1) != datfiles.end() && datfiles[1].file) {
|
|
|
+ datfiles[1].file->Deinit();
|
|
|
+ delete datfiles[1].file;
|
|
|
+ datfiles.remove(1);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (datfiles.find(3) != datfiles.end() && datfiles[3].file) {
|
|
|
+ datfiles[3].file->Deinit();
|
|
|
+ delete datfiles[3].file;
|
|
|
+ datfiles.remove(3);
|
|
|
+ }
|
|
|
emit deinitialized();
|
|
|
}
|
|
|
|
|
@@ -111,7 +148,7 @@ void PatchInstaller::installPatch(QString patch_name, LOTRO_DAT::Database* datab
|
|
|
}
|
|
|
|
|
|
const int dat_id = file.options["did"] ? file.options["did"].as<int>() : E_CLIENT_LOCAL;
|
|
|
- if (dat_id != E_CLIENT_LOCAL && dat_id != E_CLIENT_GENERAL) {
|
|
|
+ if (dat_id != E_CLIENT_LOCAL && dat_id != E_CLIENT_GENERAL && dat_id != E_CLIENT_SURFACE) {
|
|
|
qWarning() << "Unknown dat id parameter for file " << file.options["fid"].as<long long>() << " (dat id value = " << dat_id << "), SKIPPING!";
|
|
|
continue;
|
|
|
}
|
|
@@ -120,34 +157,24 @@ void PatchInstaller::installPatch(QString patch_name, LOTRO_DAT::Database* datab
|
|
|
int file_version = -1;
|
|
|
int file_iteration = -1;
|
|
|
|
|
|
- if (dat_id == E_CLIENT_LOCAL) {
|
|
|
- file_version = client_local_file_->GetFileVersion(file_id);
|
|
|
- file_iteration = client_local_file_->getSubfileInfo(file_id).iteration;
|
|
|
- } else if (dat_id == E_CLIENT_GENERAL) {
|
|
|
- file_version = client_general_file_->GetFileVersion(file_id);
|
|
|
- file_iteration = client_general_file_->getSubfileInfo(file_id).iteration;
|
|
|
- }
|
|
|
+ file_version = datfiles[dat_id].file->GetFileVersion(file_id);
|
|
|
+ file_iteration = datfiles[dat_id].file->getSubfileInfo(file_id).iteration;
|
|
|
|
|
|
// qDebug() << "File" << file_id << "version:" << file_version << "iteration:" << file_iteration;
|
|
|
if (file_version != _patch_files_versions && file_version != 0) {
|
|
|
LOTRO_DAT::SubfileData data;
|
|
|
- if (dat_id == E_CLIENT_LOCAL) {
|
|
|
- data = client_local_file_->GetFile(file_id);
|
|
|
- } else if (dat_id == E_CLIENT_GENERAL) {
|
|
|
- data = client_general_file_->GetFile(file_id);
|
|
|
+
|
|
|
+ data = datfiles[dat_id].file->GetFile(file_id);
|
|
|
+
|
|
|
+ // тут у нас только текстуры шрифтов, их отменять не нужно
|
|
|
+ if (dat_id != E_CLIENT_SURFACE){
|
|
|
+ orig_files_db.addFile(file_id, dat_id, file_version, file_iteration, data);
|
|
|
}
|
|
|
- orig_files_db.addFile(file_id, dat_id, file_version, file_iteration, data);
|
|
|
+
|
|
|
}
|
|
|
|
|
|
- //if (file.options["ext"].as<std::string>() == ".txt") {
|
|
|
- // file.text_data = QString::fromStdU16String(file.text_data).replace("[", "[ he" + QString::number(file_id) + "he ").toStdU16String();
|
|
|
- //}
|
|
|
+ datfiles[dat_id].file->PatchFile(file, _patch_files_versions);
|
|
|
|
|
|
- if (dat_id == E_CLIENT_LOCAL) {
|
|
|
- client_local_file_->PatchFile(file, _patch_files_versions);
|
|
|
- } else if (dat_id == E_CLIENT_GENERAL) {
|
|
|
- client_general_file_->PatchFile(file, _patch_files_versions);
|
|
|
- }
|
|
|
}
|
|
|
const QString hashsum = Settings::getValue("PatchDatabases/" + patch_name + "/hashsum").toString();
|
|
|
if (patch_name == "text") {
|
|
@@ -199,18 +226,13 @@ void PatchInstaller::installOriginalPatch(QString patch_name)
|
|
|
qDebug() << "Files in database: " << orig_db.getRowsCount();
|
|
|
DatOriginalFilesDatabase::FileOperation operation = [this](int file_id, int dat_id, int version, int iteration, const LOTRO_DAT::SubfileData& data) {
|
|
|
int original_file_version = 0;
|
|
|
- if (dat_id == E_CLIENT_LOCAL) {
|
|
|
- original_file_version = client_local_file_->GetFileVersion(file_id);
|
|
|
- } else if (dat_id == E_CLIENT_GENERAL) {
|
|
|
- original_file_version = client_general_file_->GetFileVersion(file_id);
|
|
|
- }
|
|
|
|
|
|
+ original_file_version = datfiles[dat_id].file->GetFileVersion(file_id);
|
|
|
|
|
|
- if (original_file_version == _patch_files_versions && dat_id == E_CLIENT_LOCAL) {
|
|
|
- client_local_file_->PatchFile(data, version, iteration);
|
|
|
- } else if (original_file_version == _patch_files_versions && dat_id == E_CLIENT_GENERAL) {
|
|
|
- client_general_file_->PatchFile(data, version, iteration);
|
|
|
+ if (original_file_version == _patch_files_versions){
|
|
|
+ datfiles[dat_id].file->PatchFile(data, version, iteration);
|
|
|
}
|
|
|
+
|
|
|
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) {
|
|
@@ -340,17 +362,25 @@ void PatchInstaller::installVideos(LOTRO_DAT::Database* database) {
|
|
|
qInfo() << "PatchInstaller: finished downloading videos";
|
|
|
}
|
|
|
|
|
|
-PatchInstaller::AppliedPatchesInfo PatchInstaller::getAppliedPatchesInfoFromDatFile() {
|
|
|
+PatchInstaller::AppliedPatchesInfo PatchInstaller::getAppliedPatchesInfoFromDatFile(){
|
|
|
+
|
|
|
PatchInstaller::AppliedPatchesInfo result;
|
|
|
- const LOTRO_DAT::SubfileData patch_versions_file = client_local_file_->GetFile(_applied_patches_file_id);
|
|
|
- if (patch_versions_file.Empty()) {
|
|
|
- result.has_no_patch_mark = true;
|
|
|
- } else {
|
|
|
+ const LOTRO_DAT::SubfileData patch_versions_file = datfiles[0].file->GetFile(_applied_patches_file_id);
|
|
|
+ result.has_no_patch_mark = true;
|
|
|
+
|
|
|
+ std::string schar = (char*)patch_versions_file.binary_data.data();
|
|
|
+ QString sstr = QString::fromStdString(schar);
|
|
|
+ qInfo() << sstr;
|
|
|
+
|
|
|
+ if(!patch_versions_file.Empty() && sstr != "" && sstr.indexOf("HI_FROM_ENDEVIR")) {
|
|
|
+
|
|
|
const QString text_data = QString::fromUtf8(reinterpret_cast<const char*>(patch_versions_file.binary_data.data() + 4), patch_versions_file.binary_data.size() - 4);
|
|
|
const QStringList text_data_splitted = text_data.split("\n");
|
|
|
- if (text_data_splitted.length() < 0 || text_data_splitted[0] != _patch_mark_header) {
|
|
|
+qInfo() << text_data;
|
|
|
+ if (text_data_splitted.length() < 0 || text_data_splitted[0] != _patch_mark_header){
|
|
|
return result;
|
|
|
}
|
|
|
+
|
|
|
for (const QString& str: text_data_splitted) {
|
|
|
if (str.startsWith("TEXTS:")) {
|
|
|
result.texts_patch_hashsum = QString(str).remove(0, 6);
|
|
@@ -370,8 +400,11 @@ PatchInstaller::AppliedPatchesInfo PatchInstaller::getAppliedPatchesInfoFromDatF
|
|
|
result.client_local_header_maxiter = QString(str).remove(0, 28).toInt();
|
|
|
} else if (str.startsWith("CLIENT_GENERAL_HEADER_MAXITER:")) {
|
|
|
result.client_general_header_maxiter = QString(str).remove(0, 30).toInt();
|
|
|
+ } else if (str.startsWith("CLIENT_SURFACE_HEADER_MAXITER:")) {
|
|
|
+ result.client_surface_header_maxiter = QString(str).remove(0, 30).toInt();
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
if (result.texts_patch_hashsum != "" || result.images_patch_hashsum != "" || result.textures_patch_hashsum != "" ||
|
|
|
result.sounds_patch_hashsum != "" || result.videos_patch_hashsum != "" || result.fonts_patch_hashsum != "" ||
|
|
|
result.loadscreens_patch_hashsum != "")
|
|
@@ -379,10 +412,12 @@ PatchInstaller::AppliedPatchesInfo PatchInstaller::getAppliedPatchesInfoFromDatF
|
|
|
result.has_no_patch_mark = false;
|
|
|
}
|
|
|
}
|
|
|
+ qInfo() << "Dat is modified: " << result.has_no_patch_mark;
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
-void PatchInstaller::insertPatchesInfoInDatFile(const PatchInstaller::AppliedPatchesInfo& info) {
|
|
|
+void PatchInstaller::insertPatchesInfoInDatFile(const PatchInstaller::AppliedPatchesInfo& info){
|
|
|
+
|
|
|
LOTRO_DAT::SubfileData file_data;
|
|
|
file_data.options["fid"] = _applied_patches_file_id;
|
|
|
file_data.options["ext"] = LOTRO_DAT::StringFromFileType(LOTRO_DAT::TEXT);
|
|
@@ -395,16 +430,15 @@ void PatchInstaller::insertPatchesInfoInDatFile(const PatchInstaller::AppliedPat
|
|
|
patches_info_data += "TEXTURES:" + info.textures_patch_hashsum + "\n";
|
|
|
patches_info_data += "FONTS:" + info.fonts_patch_hashsum + "\n";
|
|
|
patches_info_data += "VIDEOS:" + info.videos_patch_hashsum + "\n";
|
|
|
-
|
|
|
- const int client_local_maxiter = client_local_file_->GetDatFileMaxIteration();
|
|
|
- const int client_general_maxiter = client_general_file_->GetDatFileMaxIteration();
|
|
|
-
|
|
|
- patches_info_data += "CLIENT_LOCAL_HEADER_MAXITER:" + QString::number(client_local_maxiter) + "\n";
|
|
|
- patches_info_data += "CLIENT_GENERAL_HEADER_MAXITER:" + QString::number(client_general_maxiter) + "\n";
|
|
|
+ patches_info_data += "CLIENT_LOCAL_HEADER_MAXITER:" + QString::number(datfiles[0].file->GetDatFileMaxIteration()) + "\n";
|
|
|
+ patches_info_data += "CLIENT_GENERAL_HEADER_MAXITER:" + QString::number(datfiles[1].file->GetDatFileMaxIteration()) + "\n";
|
|
|
+ patches_info_data += "CLIENT_SURFACE_HEADER_MAXITER:" + QString::number(datfiles[3].file->GetDatFileMaxIteration()) + "\n";
|
|
|
|
|
|
QByteArray data = QByteArray((char*)&_applied_patches_file_id, 4) + patches_info_data.toUtf8();
|
|
|
+ qInfo() << "Set info to dat-file: " << data;
|
|
|
file_data.binary_data = LOTRO_DAT::BinaryData(data.data(), data.size());
|
|
|
- client_local_file_->PatchFile(file_data, _patch_files_versions, 1, true);
|
|
|
+ datfiles[0].file->PatchFile(file_data, _patch_files_versions, 1, true);
|
|
|
+
|
|
|
}
|
|
|
|
|
|
|
|
@@ -413,27 +447,19 @@ void PatchInstaller::insertPatchesInfoInDatFile(const PatchInstaller::AppliedPat
|
|
|
void PatchInstaller::init()
|
|
|
{
|
|
|
emit initializationStarted();
|
|
|
- if (client_local_file_->Initialized() || client_general_file_->Initialized()) {
|
|
|
- // Firstly - deinitializing existing client_local files.
|
|
|
- deinit();
|
|
|
- }
|
|
|
qInfo() << "PatchInstaller: Starting initialisation of LotroDatManager";
|
|
|
qRegisterMetaType<PatchInstaller::Status>();
|
|
|
|
|
|
+ // Деинициализируем старые файлы, если они были
|
|
|
+ deinit();
|
|
|
+
|
|
|
+ // Создаем массив нужных нам dat-файлов
|
|
|
QString game_folder = Settings::getValue("Lotro/game_path").toString();
|
|
|
QString locale_prefix = Settings::getValue("Lotro/original_locale").toString();
|
|
|
-
|
|
|
- QString client_local_filepath = game_folder + "/client_local_" + locale_prefix + ".dat";
|
|
|
- QString client_general_filepath = game_folder + "/client_general.dat";
|
|
|
-
|
|
|
- // Initialising client_local_*.dat file and client_general.dat
|
|
|
-
|
|
|
- client_local_file_->Init(client_local_filepath.toStdString());
|
|
|
- client_general_file_->Init(client_general_filepath.toStdString());
|
|
|
-
|
|
|
- qInfo() << "PatchInstaller: initialisation successfull! Dat files: "
|
|
|
- << QString::fromStdString(client_general_file_->GetFilename())
|
|
|
- << QString::fromStdString(client_local_file_->GetFilename());
|
|
|
+ createDatFile(0, "client_local", 100, game_folder + "/client_local_" + locale_prefix + ".dat");
|
|
|
+ createDatFile(1, "client_general", 101, game_folder + "/client_general.dat");
|
|
|
+ createDatFile(3, "client_surface", 0, game_folder + "/client_surface.dat");
|
|
|
+ // Создаем массив нужных нам dat-файлов
|
|
|
|
|
|
_current_applied_patches_info = getAppliedPatchesInfoFromDatFile();
|
|
|
checkIfUpdatedByGame();
|
|
@@ -460,17 +486,10 @@ void PatchInstaller::startGame(bool remove_dat_files) {
|
|
|
args << "-skiprawdownload";
|
|
|
}
|
|
|
|
|
|
- client_general_file_->Deinit();
|
|
|
- client_local_file_->Deinit();
|
|
|
-
|
|
|
- if (remove_dat_files) {
|
|
|
- QString game_folder = Settings::getValue("Lotro/game_path").toString();
|
|
|
- QString locale_prefix = Settings::getValue("Lotro/original_locale").toString();
|
|
|
-
|
|
|
- QString client_local_filepath = game_folder + "/client_local_" + locale_prefix + ".dat";
|
|
|
- QString client_general_filepath = game_folder + "/client_general.dat";
|
|
|
- QFile::remove(client_local_filepath);
|
|
|
- QFile::remove(client_general_filepath);
|
|
|
+ deinit();
|
|
|
+ if (remove_dat_files){
|
|
|
+ QFile::remove(datfiles[0].path);
|
|
|
+ QFile::remove(datfiles[1].path);
|
|
|
}
|
|
|
|
|
|
QString username = Settings::getValue("Account/username").toString();
|
|
@@ -481,7 +500,6 @@ void PatchInstaller::startGame(bool remove_dat_files) {
|
|
|
|
|
|
qInfo() << "Starting LOTRO. Path =" << game_folder;
|
|
|
|
|
|
- deinit();
|
|
|
|
|
|
QProcess process;
|
|
|
process.startDetached(game_folder + "/LotroLauncher.exe", args, game_folder);
|