CModInfo.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * CModInfo.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 "CModInfo.h"
  12. #include "../CGeneralTextHandler.h"
  13. #include "../VCMI_Lib.h"
  14. #include "../filesystem/Filesystem.h"
  15. VCMI_LIB_NAMESPACE_BEGIN
  16. static JsonNode addMeta(JsonNode config, const std::string & meta)
  17. {
  18. config.setMeta(meta);
  19. return config;
  20. }
  21. CModInfo::CModInfo():
  22. explicitlyEnabled(false),
  23. implicitlyEnabled(true),
  24. validation(PENDING)
  25. {
  26. }
  27. CModInfo::CModInfo(const std::string & identifier, const JsonNode & local, const JsonNode & config):
  28. identifier(identifier),
  29. description(config["description"].String()),
  30. dependencies(config["depends"].convertTo<std::set<std::string>>()),
  31. conflicts(config["conflicts"].convertTo<std::set<std::string>>()),
  32. explicitlyEnabled(false),
  33. implicitlyEnabled(true),
  34. validation(PENDING),
  35. config(addMeta(config, identifier))
  36. {
  37. verificationInfo.name = config["name"].String();
  38. verificationInfo.version = CModVersion::fromString(config["version"].String());
  39. verificationInfo.parent = identifier.substr(0, identifier.find_last_of('.'));
  40. if(verificationInfo.parent == identifier)
  41. verificationInfo.parent.clear();
  42. if(!config["compatibility"].isNull())
  43. {
  44. vcmiCompatibleMin = CModVersion::fromString(config["compatibility"]["min"].String());
  45. vcmiCompatibleMax = CModVersion::fromString(config["compatibility"]["max"].String());
  46. }
  47. if (!config["language"].isNull())
  48. baseLanguage = config["language"].String();
  49. else
  50. baseLanguage = "english";
  51. loadLocalData(local);
  52. }
  53. JsonNode CModInfo::saveLocalData() const
  54. {
  55. std::ostringstream stream;
  56. stream << std::noshowbase << std::hex << std::setw(8) << std::setfill('0') << verificationInfo.checksum;
  57. JsonNode conf;
  58. conf["active"].Bool() = explicitlyEnabled;
  59. conf["validated"].Bool() = validation != FAILED;
  60. conf["checksum"].String() = stream.str();
  61. return conf;
  62. }
  63. std::string CModInfo::getModDir(const std::string & name)
  64. {
  65. return "MODS/" + boost::algorithm::replace_all_copy(name, ".", "/MODS/");
  66. }
  67. JsonPath CModInfo::getModFile(const std::string & name)
  68. {
  69. return JsonPath::builtinTODO(getModDir(name) + "/mod.json");
  70. }
  71. void CModInfo::updateChecksum(ui32 newChecksum)
  72. {
  73. // comment-out next line to force validation of all mods ignoring checksum
  74. if (newChecksum != verificationInfo.checksum)
  75. {
  76. verificationInfo.checksum = newChecksum;
  77. validation = PENDING;
  78. }
  79. }
  80. void CModInfo::loadLocalData(const JsonNode & data)
  81. {
  82. bool validated = false;
  83. implicitlyEnabled = true;
  84. explicitlyEnabled = !config["keepDisabled"].Bool();
  85. verificationInfo.checksum = 0;
  86. if (data.getType() == JsonNode::JsonType::DATA_BOOL)
  87. {
  88. explicitlyEnabled = data.Bool();
  89. }
  90. if (data.getType() == JsonNode::JsonType::DATA_STRUCT)
  91. {
  92. explicitlyEnabled = data["active"].Bool();
  93. validated = data["validated"].Bool();
  94. updateChecksum(strtol(data["checksum"].String().c_str(), nullptr, 16));
  95. }
  96. //check compatibility
  97. implicitlyEnabled &= (vcmiCompatibleMin.isNull() || CModVersion::GameVersion().compatible(vcmiCompatibleMin, true, true));
  98. implicitlyEnabled &= (vcmiCompatibleMax.isNull() || vcmiCompatibleMax.compatible(CModVersion::GameVersion(), true, true));
  99. if(!implicitlyEnabled)
  100. logGlobal->warn("Mod %s is incompatible with current version of VCMI and cannot be enabled", verificationInfo.name);
  101. if (boost::iequals(config["modType"].String(), "translation")) // compatibility code - mods use "Translation" type at the moment
  102. {
  103. if (baseLanguage != VLC->generaltexth->getPreferredLanguage())
  104. {
  105. logGlobal->warn("Translation mod %s was not loaded: language mismatch!", verificationInfo.name);
  106. implicitlyEnabled = false;
  107. }
  108. }
  109. if (isEnabled())
  110. validation = validated ? PASSED : PENDING;
  111. else
  112. validation = validated ? PASSED : FAILED;
  113. verificationInfo.impactsGameplay = checkModGameplayAffecting();
  114. }
  115. bool CModInfo::checkModGameplayAffecting() const
  116. {
  117. if (modGameplayAffecting.has_value())
  118. return *modGameplayAffecting;
  119. static const std::vector<std::string> keysToTest = {
  120. "heroClasses",
  121. "artifacts",
  122. "creatures",
  123. "factions",
  124. "objects",
  125. "heroes",
  126. "spells",
  127. "skills",
  128. "templates",
  129. "scripts",
  130. "battlefields",
  131. "terrains",
  132. "rivers",
  133. "roads",
  134. "obstacles"
  135. };
  136. JsonPath modFileResource(CModInfo::getModFile(identifier));
  137. if(CResourceHandler::get("initial")->existsResource(modFileResource))
  138. {
  139. const JsonNode modConfig(modFileResource);
  140. for(const auto & key : keysToTest)
  141. {
  142. if (!modConfig[key].isNull())
  143. {
  144. modGameplayAffecting = true;
  145. return *modGameplayAffecting;
  146. }
  147. }
  148. }
  149. modGameplayAffecting = false;
  150. return *modGameplayAffecting;
  151. }
  152. const CModInfo::VerificationInfo & CModInfo::getVerificationInfo() const
  153. {
  154. return verificationInfo;
  155. }
  156. bool CModInfo::isEnabled() const
  157. {
  158. return implicitlyEnabled && explicitlyEnabled;
  159. }
  160. void CModInfo::setEnabled(bool on)
  161. {
  162. explicitlyEnabled = on;
  163. }
  164. VCMI_LIB_NAMESPACE_END