helper.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * helper.cpp, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #include "StdInc.h"
  11. #include "helper.h"
  12. #include "mapcontroller.h"
  13. #include "../lib/filesystem/Filesystem.h"
  14. #include "../lib/filesystem/CMemoryBuffer.h"
  15. #include "../lib/filesystem/CFilesystemLoader.h"
  16. #include "../lib/filesystem/CZipSaver.h"
  17. #include "../lib/campaign/CampaignHandler.h"
  18. #include "../lib/mapping/CMapService.h"
  19. #include "../lib/mapping/CMap.h"
  20. #include "../lib/mapping/CMap.h"
  21. #include "../lib/mapping/MapFormatJson.h"
  22. #include "../lib/modding/ModIncompatibility.h"
  23. #include "../lib/rmg/CRmgTemplate.h"
  24. #include "../lib/serializer/JsonSerializer.h"
  25. #include "../lib/serializer/JsonDeserializer.h"
  26. #include "../lib/serializer/CSaveFile.h"
  27. std::unique_ptr<CMap> Helper::openMapInternal(const QString & filenameSelect)
  28. {
  29. QFileInfo fi(filenameSelect);
  30. std::string fname = fi.fileName().toStdString();
  31. std::string fdir = fi.dir().path().toStdString();
  32. ResourcePath resId("MAPEDITOR/" + fname, EResType::MAP);
  33. //addFilesystem takes care about memory deallocation if case of failure, no memory leak here
  34. auto mapEditorFilesystem = std::make_unique<CFilesystemLoader>("MAPEDITOR/", fdir, 0);
  35. CResourceHandler::removeFilesystem("local", "mapEditor");
  36. CResourceHandler::addFilesystem("local", "mapEditor", std::move(mapEditorFilesystem));
  37. if(!CResourceHandler::get("mapEditor")->existsResource(resId))
  38. throw std::runtime_error("Cannot open map from this folder");
  39. CMapService mapService;
  40. if(auto header = mapService.loadMapHeader(resId))
  41. {
  42. auto missingMods = CMapService::verifyMapHeaderMods(*header);
  43. ModIncompatibility::ModList modList;
  44. for(const auto & m : missingMods)
  45. modList.push_back(m.second.name);
  46. if(!modList.empty())
  47. throw ModIncompatibility(modList);
  48. return mapService.loadMap(resId, nullptr);
  49. }
  50. else
  51. throw std::runtime_error("Corrupted map");
  52. }
  53. std::shared_ptr<CampaignState> Helper::openCampaignInternal(const QString & filenameSelect)
  54. {
  55. QFileInfo fi(filenameSelect);
  56. std::string fname = fi.fileName().toStdString();
  57. std::string fdir = fi.dir().path().toStdString();
  58. ResourcePath resId("MAPEDITOR/" + fname, EResType::CAMPAIGN);
  59. //addFilesystem takes care about memory deallocation if case of failure, no memory leak here
  60. auto mapEditorFilesystem = std::make_unique<CFilesystemLoader>("MAPEDITOR/", fdir, 0);
  61. CResourceHandler::removeFilesystem("local", "mapEditor");
  62. CResourceHandler::addFilesystem("local", "mapEditor", std::move(mapEditorFilesystem));
  63. if(!CResourceHandler::get("mapEditor")->existsResource(resId))
  64. throw std::runtime_error("Cannot open campaign from this folder");
  65. if(auto campaign = CampaignHandler::getCampaign(resId.getName()))
  66. return campaign;
  67. else
  68. throw std::runtime_error("Corrupted campaign");
  69. }
  70. std::map<std::string, std::shared_ptr<CRmgTemplate>> Helper::openTemplateInternal(const QString & filenameSelect)
  71. {
  72. QFileInfo fi(filenameSelect);
  73. std::string fname = fi.fileName().toStdString();
  74. std::string fdir = fi.dir().path().toStdString();
  75. ResourcePath resId("MAPEDITOR/" + fname, EResType::JSON);
  76. //addFilesystem takes care about memory deallocation if case of failure, no memory leak here
  77. auto mapEditorFilesystem = std::make_unique<CFilesystemLoader>("MAPEDITOR/", fdir, 0);
  78. CResourceHandler::removeFilesystem("local", "mapEditor");
  79. CResourceHandler::addFilesystem("local", "mapEditor", std::move(mapEditorFilesystem));
  80. if(!CResourceHandler::get("mapEditor")->existsResource(resId))
  81. throw std::runtime_error("Cannot open template from this folder");
  82. auto data = CResourceHandler::get()->load(resId)->readAll();
  83. JsonNode nodes(reinterpret_cast<std::byte *>(data.first.get()), data.second, resId.getName());
  84. std::map<std::string, std::shared_ptr<CRmgTemplate>> templates;
  85. for(auto & node : nodes.Struct())
  86. {
  87. JsonDeserializer handler(nullptr, node.second);
  88. auto rmg = std::make_shared<CRmgTemplate>();
  89. rmg->serializeJson(handler);
  90. rmg->validate();
  91. templates[node.first] = rmg;
  92. }
  93. return templates;
  94. }
  95. void Helper::saveCampaign(std::shared_ptr<CampaignState> campaignState, const QString & filename)
  96. {
  97. auto jsonCampaign = CampaignHandler::writeHeaderToJson(*campaignState);
  98. auto io = std::make_shared<CDefaultIOApi>();
  99. auto saver = std::make_shared<CZipSaver>(io, filename.toStdString());
  100. for(auto & scenario : campaignState->allScenarios())
  101. {
  102. auto map = campaignState->getMap(scenario, nullptr);
  103. MapController::repairMap(map.get());
  104. CMemoryBuffer serializeBuffer;
  105. {
  106. CMapSaverJson jsonSaver(&serializeBuffer);
  107. jsonSaver.saveMap(map);
  108. }
  109. auto mapName = boost::algorithm::to_lower_copy(campaignState->scenario(scenario).mapName);
  110. if(!boost::ends_with(mapName, ".vmap"))
  111. mapName = boost::replace_all_copy(mapName, ".h3m", std::string("")) + ".vmap";
  112. auto stream = saver->addFile(mapName);
  113. stream->write(reinterpret_cast<const ui8 *>(serializeBuffer.getBuffer().data()), serializeBuffer.getSize());
  114. jsonCampaign["scenarios"].Vector().push_back(CampaignHandler::writeScenarioToJson(campaignState->scenario(scenario)));
  115. jsonCampaign["scenarios"].Vector().back()["map"].String() = mapName;
  116. }
  117. auto jsonCampaignStr = jsonCampaign.toString();
  118. saver->addFile("header.json")->write(reinterpret_cast<const ui8 *>(jsonCampaignStr.data()), jsonCampaignStr.length());
  119. }
  120. void Helper::saveTemplate(std::map<std::string, std::shared_ptr<CRmgTemplate>> tpl, const QString & filename)
  121. {
  122. JsonMap data;
  123. for(auto & node : tpl)
  124. {
  125. JsonNode actual;
  126. {
  127. JsonSerializer handler(nullptr, actual);
  128. node.second->serializeJson(handler);
  129. }
  130. data[node.first] = actual;
  131. }
  132. auto byteData = JsonNode(data).toBytes();
  133. QByteArray byteDataArray = QByteArray(reinterpret_cast<const char*>(byteData.data()), static_cast<int>(byteData.size()));
  134. QFile file(filename);
  135. if(file.open(QIODevice::WriteOnly))
  136. file.write(byteDataArray);
  137. }