CModInfo.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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. checksum(0),
  23. explicitlyEnabled(false),
  24. implicitlyEnabled(true),
  25. validation(PENDING)
  26. {
  27. }
  28. CModInfo::CModInfo(const std::string & identifier, const JsonNode & local, const JsonNode & config):
  29. identifier(identifier),
  30. name(config["name"].String()),
  31. description(config["description"].String()),
  32. dependencies(config["depends"].convertTo<std::set<std::string>>()),
  33. conflicts(config["conflicts"].convertTo<std::set<std::string>>()),
  34. checksum(0),
  35. explicitlyEnabled(false),
  36. implicitlyEnabled(true),
  37. validation(PENDING),
  38. config(addMeta(config, identifier))
  39. {
  40. version = CModVersion::fromString(config["version"].String());
  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') << 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. std::string CModInfo::getModFile(const std::string & name)
  67. {
  68. return 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 != checksum)
  74. {
  75. 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. checksum = 0;
  85. if (data.getType() == JsonNode::JsonType::DATA_BOOL)
  86. {
  87. explicitlyEnabled = data.Bool();
  88. }
  89. if (data.getType() == JsonNode::JsonType::DATA_STRUCT)
  90. {
  91. explicitlyEnabled = data["active"].Bool();
  92. validated = data["validated"].Bool();
  93. checksum = strtol(data["checksum"].String().c_str(), nullptr, 16);
  94. }
  95. //check compatibility
  96. implicitlyEnabled &= (vcmiCompatibleMin.isNull() || CModVersion::GameVersion().compatible(vcmiCompatibleMin));
  97. implicitlyEnabled &= (vcmiCompatibleMax.isNull() || vcmiCompatibleMax.compatible(CModVersion::GameVersion()));
  98. if(!implicitlyEnabled)
  99. logGlobal->warn("Mod %s is incompatible with current version of VCMI and cannot be enabled", name);
  100. if (boost::iequals(config["modType"].String(), "translation")) // compatibility code - mods use "Translation" type at the moment
  101. {
  102. if (baseLanguage != VLC->generaltexth->getPreferredLanguage())
  103. {
  104. logGlobal->warn("Translation mod %s was not loaded: language mismatch!", name);
  105. implicitlyEnabled = false;
  106. }
  107. }
  108. if (isEnabled())
  109. validation = validated ? PASSED : PENDING;
  110. else
  111. validation = validated ? PASSED : FAILED;
  112. }
  113. bool CModInfo::checkModGameplayAffecting() const
  114. {
  115. if (modGameplayAffecting.has_value())
  116. return *modGameplayAffecting;
  117. static const std::vector<std::string> keysToTest = {
  118. "heroClasses",
  119. "artifacts",
  120. "creatures",
  121. "factions",
  122. "objects",
  123. "heroes",
  124. "spells",
  125. "skills",
  126. "templates",
  127. "scripts",
  128. "battlefields",
  129. "terrains",
  130. "rivers",
  131. "roads",
  132. "obstacles"
  133. };
  134. ResourceID modFileResource(CModInfo::getModFile(identifier));
  135. if(CResourceHandler::get("initial")->existsResource(modFileResource))
  136. {
  137. const JsonNode modConfig(modFileResource);
  138. for(const auto & key : keysToTest)
  139. {
  140. if (!modConfig[key].isNull())
  141. {
  142. modGameplayAffecting = true;
  143. return *modGameplayAffecting;
  144. }
  145. }
  146. }
  147. modGameplayAffecting = false;
  148. return *modGameplayAffecting;
  149. }
  150. bool CModInfo::isEnabled() const
  151. {
  152. return implicitlyEnabled && explicitlyEnabled;
  153. }
  154. void CModInfo::setEnabled(bool on)
  155. {
  156. explicitlyEnabled = on;
  157. }
  158. VCMI_LIB_NAMESPACE_END