CModInfo.cpp 4.9 KB

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