graphicspatch.cpp 14 KB

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