graphicspatch.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. #include "graphicspatch.h"
  2. #include "LotroDat/LotroDat.h"
  3. #include "LotroDat/Database.h"
  4. #include "models/lotrodatmanager.h"
  5. #include <QUrlQuery>
  6. #include <QSet>
  7. GraphicsPatch::GraphicsPatch(LotroDatManager *mgr, QObject *parent) : Patch("GraphicsPatch", mgr, parent)
  8. {
  9. connect(lotro_mgr_, &LotroDatManager::operationStarted, this, &GraphicsPatch::onLotroDatManagerOperationStarted);
  10. connect(lotro_mgr_, &LotroDatManager::operationFinished, this, &GraphicsPatch::onLotroDatManagerOperationFinished);
  11. connect(lotro_mgr_, &LotroDatManager::statusChanged, this, &GraphicsPatch::onLotroDatManagerStatusChanged);
  12. }
  13. void GraphicsPatch::checkForUpdates()
  14. {
  15. QUrlQuery query; // query for building GET-request aka patch-version
  16. foreach (QString db_name, databases_names) {
  17. query.addQueryItem(db_name, "100");
  18. }
  19. QUrl target_url;
  20. target_url.setUrl(Settings::getValue("Network/patch_updates_url").toString());
  21. target_url.setQuery(query);
  22. QByteArray target_array;
  23. Downloader downloader;
  24. downloader.setUrl(target_url);
  25. downloader.targetBytearray = &target_array;
  26. downloader.start();
  27. downloader.waitForDownloaded();
  28. if (target_array.isEmpty()) {
  29. qWarning() << *this << "Cannot check for updates, target_array is empty!";
  30. emit errorOccured(E_CHECKFORUPDATES, this, "");
  31. emit operationFinished(E_CHECKFORUPDATES, this);
  32. return;
  33. }
  34. QStringList patch_info = QString(target_array).split('|');
  35. if (patch_info.size() != databases_names.size()) {
  36. qCritical() << __FUNCTION__ << "Incorrect patches number! Data: " << patch_info;
  37. emit errorOccured(E_CHECKFORUPDATES, this, "");
  38. emit operationFinished(E_CHECKFORUPDATES, this);
  39. return;
  40. }
  41. for (int i = 0; i < databases_names.size(); ++i) {
  42. QStringList patch_data = patch_info[i].split(":::");
  43. if (patch_data.size() != 3) {
  44. qCritical() << __FUNCTION__ << "Incorrect patch entry size! Entry: " << patch_data;
  45. emit errorOccured(E_CHECKFORUPDATES, this, "");
  46. emit operationFinished(E_CHECKFORUPDATES, this);
  47. return;
  48. }
  49. QString patch_filename = Settings::getValue("General/PatchDownloadDir").toString() + "/" + QUrl(patch_data[0]).fileName();
  50. Settings::setValue("PatchDatabases/" + databases_names[i] + "/url", patch_data[0]);
  51. Settings::setValue("PatchDatabases/" + databases_names[i] + "/hashsum", patch_data[1]);
  52. Settings::setValue("PatchDatabases/" + databases_names[i] + "/datetime", patch_data[2]);
  53. Settings::setValue("PatchDatabases/" + databases_names[i] + "/path", patch_filename);
  54. }
  55. emit operationFinished(E_CHECKFORUPDATES, this);
  56. }
  57. void GraphicsPatch::download()
  58. {
  59. foreach (QString db_name, databases_names) {
  60. QString settings_prefix = "PatchDatabases/" + db_name;
  61. QString target_filename = QApplication::applicationDirPath() + "/" + Settings::getValue(settings_prefix + "/path").toString();
  62. qDebug() << patch_name_ << ": Checking if file " << target_filename << " matches its hashsum";
  63. if (FileSystem::fileHash(target_filename) == Settings::getValue(settings_prefix + "/hashsum").toString()) {
  64. qInfo() << *this << ": file " << target_filename << " is up-to-date, no need to download";
  65. continue;
  66. }
  67. FileSystem::createFilePath(target_filename);
  68. QFile* target_file = new QFile(target_filename);
  69. if (!target_file->open(QIODevice::ReadWrite | QIODevice::Truncate)) {
  70. qWarning() << *this << "Cannot open file " << target_filename;
  71. continue;
  72. }
  73. qInfo() << *this << ": beginning download of file " << target_filename;
  74. Settings::setValue("DatabaseNeedInstall/" + db_name, true);
  75. Downloader* downloader = new Downloader();
  76. downloader->setUrl(Settings::getValue(settings_prefix + "/url").toUrl());
  77. downloader->targetFile = target_file;
  78. connect(downloader, &Downloader::progressChanged, this, &GraphicsPatch::onDownloaderProgressChanged);
  79. connect(downloader, &Downloader::downloadFinished, this, &GraphicsPatch::onDownloaderFinished);
  80. downloaders_.insert(downloader);
  81. downloader->start();
  82. }
  83. if (downloaders_.empty()) {
  84. emit operationFinished(E_DOWNLOAD, this);
  85. }
  86. }
  87. void GraphicsPatch::install()
  88. {
  89. installLoadscreens();
  90. foreach (QString db_name, QStringList({"image", "texture"})) {
  91. ++elapsed_patches_to_install_;
  92. QMetaObject::invokeMethod(lotro_mgr_, "installPatch", Qt::QueuedConnection,
  93. Q_ARG(QString, getPatchName() + "_" + db_name),
  94. Q_ARG(QString, Settings::getValue("PatchDatabases/" + db_name + "/path").toString())
  95. );
  96. }
  97. }
  98. void GraphicsPatch::activate()
  99. {
  100. emit operationFinished(E_ACTIVATE, this);
  101. return;
  102. if (Settings::getValue("Components/loadscreens").toBool()) {
  103. enableLoadscreens();
  104. } else {
  105. disableLoadscreens();
  106. }
  107. QString operation_name;
  108. operation_name = Settings::getValue("Components/maps").toBool() ? "enableCategory" : "disableCategory";
  109. ++elapsed_patches_to_install_;
  110. QMetaObject::invokeMethod(lotro_mgr_, operation_name.toLocal8Bit().constData(), Qt::QueuedConnection,
  111. Q_ARG(QString, getPatchName() + "_maps"),
  112. Q_ARG(LotroDatManager::Category, LotroDatManager::Category::E_MAPS_COMMON)
  113. );
  114. operation_name = Settings::getValue("Components/textures").toBool() ? "enableCategory" : "disableCategory";
  115. ++elapsed_patches_to_install_;
  116. QMetaObject::invokeMethod(lotro_mgr_, operation_name.toLocal8Bit().constData(), Qt::QueuedConnection,
  117. Q_ARG(QString, getPatchName() + "_textures"),
  118. Q_ARG(LotroDatManager::Category, LotroDatManager::Category::E_TEXTURES_COMMON)
  119. );
  120. }
  121. void GraphicsPatch::onDownloaderProgressChanged(Downloader *, Downloader::Status)
  122. {
  123. Downloader::Status all_downloads_status;
  124. foreach (Downloader* downloader, downloaders_) {
  125. all_downloads_status = all_downloads_status + downloader->getDownloadStatus();
  126. }
  127. emit progressChanged(OperationProgress(all_downloads_status), this);
  128. }
  129. void GraphicsPatch::onDownloaderFinished(Downloader *ptr)
  130. {
  131. ptr->targetFile->close();
  132. ptr->targetFile->deleteLater();
  133. Downloader::Status all_downloads_status;
  134. for (const Downloader* downloader : downloaders_) {
  135. all_downloads_status = all_downloads_status + downloader->getDownloadStatus();
  136. }
  137. if (!all_downloads_status.running) {
  138. for (Downloader* downloader : downloaders_) {
  139. downloader->deleteLater();
  140. }
  141. downloaders_.clear();
  142. emit operationFinished(E_DOWNLOAD, this);
  143. }
  144. }
  145. void GraphicsPatch::onLotroDatManagerOperationFinished(QString operation_name, QVector<QVariant> args, bool successful)
  146. {
  147. if (args.size() == 0 || !args[0].toString().contains(getPatchName())) {
  148. return; // This means, that message from LotroManager is addressed to another patchset
  149. }
  150. if (operation_name.contains("installPatch")) {
  151. QString db_name = args[0].toString().split('_').at(1);
  152. qDebug() << "DATABASE NAME: " << db_name;
  153. if (!successful) {
  154. qCritical() << *this << "Database " + args[0].toString() + " (" + args[1].toString() + ") was not installed due to Legacy core error.";
  155. emit errorOccured(E_INSTALL, this, "Database " + args[0].toString() + " (" + args[1].toString() + ") was not installed due to Legacy core error.");
  156. }
  157. --elapsed_patches_to_install_;
  158. if (!elapsed_patches_to_install_) {
  159. is_being_patched_by_lotro_dat_manager_ = false;
  160. emit operationFinished(E_INSTALL, this);
  161. }
  162. }
  163. if (operation_name.contains("enableCategory") || operation_name.contains("disableCategory")) {
  164. if (!successful) {
  165. qCritical() << *this << "Error in patch " + args[0].toString() + ": activating category " + QString::number(args[1].toInt()) + " failed.";
  166. emit errorOccured(E_ACTIVATE, this, "Error in patch " + args[0].toString() + ": activating category " + QString::number(args[1].toInt()) + " failed.");
  167. }
  168. --elapsed_patches_to_install_;
  169. if (!elapsed_patches_to_install_) {
  170. is_being_patched_by_lotro_dat_manager_ = false;
  171. emit operationFinished(E_ACTIVATE, this);
  172. }
  173. }
  174. }
  175. void GraphicsPatch::onLotroDatManagerOperationStarted(QString operation_name, QVector<QVariant> args)
  176. {
  177. if (args.size() == 0 || !args[0].toString().contains(getPatchName())) {
  178. return;
  179. }
  180. is_being_patched_by_lotro_dat_manager_ = true;
  181. }
  182. void GraphicsPatch::onLotroDatManagerStatusChanged(LotroDatManager::Status status)
  183. {
  184. if (!is_being_patched_by_lotro_dat_manager_) {
  185. return;
  186. }
  187. emit progressChanged(OperationProgress(status), this);
  188. }
  189. void GraphicsPatch::installLoadscreens()
  190. {
  191. QString locale_prefix = Settings::getValue("Lotro/original_locale").toString();
  192. const QStringList loadscreens_filenames = {
  193. locale_prefix == "English" ? "lotro_ad_pregame.jpg" : "lotro_ad_pregame_" + locale_prefix + ".jpg",
  194. "lotro_generic_teleport_screen_01.jpg",
  195. "lotro_generic_teleport_screen_02.jpg",
  196. "lotro_generic_teleport_screen_03.jpg",
  197. "lotro_generic_teleport_screen_04.jpg",
  198. "lotro_generic_teleport_screen_05.jpg",
  199. "lotro_generic_teleport_screen_06.jpg",
  200. "lotro_generic_teleport_screen_07.jpg",
  201. "lotro_generic_teleport_screen_08.jpg",
  202. "lotro_generic_teleport_screen_09.jpg",
  203. "lotro_generic_teleport_screen_10.jpg"
  204. };
  205. OperationProgress progress;
  206. progress.install_finished_parts = 0;
  207. progress.install_total_parts = loadscreens_filenames.size() * 2;
  208. LOTRO_DAT::Database database;
  209. if (!database.InitDatabase(Settings::getValue("PatchDatabases/Loadscreen/path").toString().toStdString())) {
  210. qCritical() << *this << "database.InitDatabase() of " << Settings::getValue("PatchDatabases/Loadscreen/path").toString() << " FAILED!";
  211. return;
  212. }
  213. LOTRO_DAT::SubfileData data;
  214. QString logo_path = Settings::getValue("Lotro/game_path").toString() + "/raw/" + (locale_prefix == "English" ? "en" : locale_prefix) + "/logo/";
  215. for (size_t i = 0; i < qMin(size_t(loadscreens_filenames.size()), database.CountRows()); ++i) {
  216. data = database.GetNextFile();
  217. QFile::remove(logo_path + loadscreens_filenames[i] + "_ru");
  218. if (!data.binary_data.WriteToFile((logo_path + loadscreens_filenames[i] + "_ru").toLocal8Bit())) {
  219. qWarning() << patch_name_ << "Cannot write to file " << logo_path + loadscreens_filenames[i];
  220. }
  221. progress.install_finished_parts++;
  222. emit progressChanged(progress, this);
  223. }
  224. for (int i = 0; i < loadscreens_filenames.size(); ++i) {
  225. QFile::copy(logo_path + loadscreens_filenames[i], logo_path + loadscreens_filenames[i] + "_orig"); // Will not copy if _orig file already exists
  226. progress.install_finished_parts++;
  227. emit progressChanged(progress, this);
  228. }
  229. }
  230. void GraphicsPatch::enableLoadscreens()
  231. {
  232. QString locale_prefix = Settings::getValue("Lotro/original_locale").toString();
  233. QString logo_path = Settings::getValue("Lotro/game_path").toString() + "/raw/" + (locale_prefix == "English" ? "en" : locale_prefix) + "/logo/";
  234. const QStringList loadscreens_filenames = {
  235. locale_prefix == "English" ? "lotro_ad_pregame.jpg" : "lotro_ad_pregame_" + locale_prefix + ".jpg",
  236. "lotro_generic_teleport_screen_01.jpg",
  237. "lotro_generic_teleport_screen_02.jpg",
  238. "lotro_generic_teleport_screen_03.jpg",
  239. "lotro_generic_teleport_screen_04.jpg",
  240. "lotro_generic_teleport_screen_05.jpg",
  241. "lotro_generic_teleport_screen_06.jpg",
  242. "lotro_generic_teleport_screen_07.jpg",
  243. "lotro_generic_teleport_screen_08.jpg",
  244. "lotro_generic_teleport_screen_09.jpg",
  245. "lotro_generic_teleport_screen_10.jpg"
  246. };
  247. OperationProgress progress;
  248. progress.install_total_parts = loadscreens_filenames.size();
  249. for (int i = 0; i < loadscreens_filenames.size(); ++i) {
  250. QFile::remove(logo_path + loadscreens_filenames[i]);
  251. QFile::copy(logo_path + loadscreens_filenames[i] + "_ru", logo_path + loadscreens_filenames[i]);
  252. progress.install_finished_parts++;
  253. emit progressChanged(progress, this);
  254. }
  255. }
  256. void GraphicsPatch::disableLoadscreens()
  257. {
  258. QString locale_prefix = Settings::getValue("Lotro/original_locale").toString();
  259. QString logo_path = Settings::getValue("Lotro/game_path").toString() + "/raw/" + (locale_prefix == "English" ? "en" : locale_prefix) + "/logo/";
  260. const QStringList loadscreens_filenames = {
  261. locale_prefix == "English" ? "lotro_ad_pregame.jpg" : "lotro_ad_pregame_" + locale_prefix + ".jpg",
  262. "lotro_generic_teleport_screen_01.jpg",
  263. "lotro_generic_teleport_screen_02.jpg",
  264. "lotro_generic_teleport_screen_03.jpg",
  265. "lotro_generic_teleport_screen_04.jpg",
  266. "lotro_generic_teleport_screen_05.jpg",
  267. "lotro_generic_teleport_screen_06.jpg",
  268. "lotro_generic_teleport_screen_07.jpg",
  269. "lotro_generic_teleport_screen_08.jpg",
  270. "lotro_generic_teleport_screen_09.jpg",
  271. "lotro_generic_teleport_screen_10.jpg"
  272. };
  273. OperationProgress progress;
  274. progress.install_total_parts = loadscreens_filenames.size();
  275. for (int i = 0; i < loadscreens_filenames.size(); ++i) {
  276. QFile::remove(logo_path + loadscreens_filenames[i]);
  277. QFile::copy(logo_path + loadscreens_filenames[i] + "_orig", logo_path + loadscreens_filenames[i]);
  278. progress.install_finished_parts++;
  279. emit progressChanged(progress, this);
  280. }
  281. }