ObjectConfig.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /*
  2. * ObjectConfig.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 <boost/bimap.hpp>
  12. #include <boost/assign.hpp>
  13. #include "ObjectInfo.h"
  14. #include "ObjectConfig.h"
  15. #include "../GameLibrary.h"
  16. #include "../mapObjectConstructors/CObjectClassesHandler.h"
  17. #include "../mapObjectConstructors/AObjectTypeHandler.h"
  18. #include "../serializer/JsonSerializeFormat.h"
  19. VCMI_LIB_NAMESPACE_BEGIN
  20. void ObjectConfig::addBannedObject(const CompoundMapObjectID & objid)
  21. {
  22. // FIXME: We do not need to store the object info, just the id
  23. bannedObjects.push_back(objid);
  24. logGlobal->info("Banned object of type %d.%d", objid.primaryID, objid.secondaryID);
  25. }
  26. void ObjectConfig::addCustomObject(const ObjectInfo & object)
  27. {
  28. customObjects.push_back(object);
  29. auto & lastObject = customObjects.back();
  30. lastObject.setAllTemplates(object.primaryID, object.secondaryID);
  31. // also ban object to prevent default configuration from being used in this zone
  32. bannedObjects.push_back(CompoundMapObjectID(object.primaryID, object.secondaryID));
  33. assert(lastObject.templates.size() > 0);
  34. logGlobal->info("Added custom object of type %d.%d", object.primaryID, object.secondaryID);
  35. }
  36. void ObjectConfig::serializeJson(JsonSerializeFormat & handler)
  37. {
  38. static const std::map<std::string, EObjectCategory> OBJECT_CATEGORY_STRINGS = {
  39. { "other", EObjectCategory::OTHER},
  40. { "all", EObjectCategory::ALL},
  41. { "none", EObjectCategory::NONE},
  42. { "creatureBank", EObjectCategory::CREATURE_BANK},
  43. { "bonus", EObjectCategory::BONUS},
  44. { "dwelling", EObjectCategory::DWELLING},
  45. { "resource", EObjectCategory::RESOURCE},
  46. { "resourceGenerator", EObjectCategory::RESOURCE_GENERATOR},
  47. { "spellScroll", EObjectCategory::SPELL_SCROLL},
  48. { "randomArtifact", EObjectCategory::RANDOM_ARTIFACT},
  49. { "pandorasBox", EObjectCategory::PANDORAS_BOX},
  50. { "questArtifact", EObjectCategory::QUEST_ARTIFACT},
  51. { "seerHut", EObjectCategory::SEER_HUT}
  52. };
  53. // Serialize banned categories
  54. if (handler.saving)
  55. {
  56. auto categoriesArray = handler.enterArray("bannedCategories");
  57. categoriesArray.syncSize(bannedObjectCategories, JsonNode::JsonType::DATA_STRING);
  58. for(size_t i = 0; i < bannedObjectCategories.size(); ++i)
  59. {
  60. for(const auto & [key, value] : OBJECT_CATEGORY_STRINGS)
  61. {
  62. if(value == bannedObjectCategories[i])
  63. {
  64. std::string categoryName = key;
  65. categoriesArray.serializeString(i, categoryName);
  66. break;
  67. }
  68. }
  69. }
  70. }
  71. else
  72. {
  73. const JsonNode & config = handler.getCurrent();
  74. const JsonNode & configBannedCategories = config["bannedCategories"];
  75. for(const auto & node : configBannedCategories.Vector())
  76. {
  77. auto it = OBJECT_CATEGORY_STRINGS.find(node.String());
  78. if(it != OBJECT_CATEGORY_STRINGS.end())
  79. bannedObjectCategories.push_back(it->second);
  80. }
  81. }
  82. // Serialize banned objects
  83. if (handler.saving)
  84. {
  85. // Group banned objects by primary ID
  86. std::map<int, std::set<int>> groupedBanned;
  87. for(const auto & objid : bannedObjects)
  88. {
  89. groupedBanned[objid.primaryID].insert(objid.secondaryID);
  90. }
  91. auto bannedObjectsStruct = handler.enterStruct("bannedObjects");
  92. for(const auto & [primaryID, secondaryIDs] : groupedBanned)
  93. {
  94. const std::string jsonKey = LIBRARY->objtypeh->getJsonKey(primaryID);
  95. if(secondaryIDs.size() == 1 && *secondaryIDs.begin() == -1)
  96. {
  97. // Ban entire object type - write as boolean true
  98. bool allBanned = true;
  99. bannedObjectsStruct->serializeBool(jsonKey, allBanned);
  100. }
  101. else
  102. {
  103. // Ban specific subtypes
  104. auto objStruct = bannedObjectsStruct->enterStruct(jsonKey);
  105. for(int secondaryID : secondaryIDs)
  106. {
  107. if(secondaryID != -1)
  108. {
  109. auto handler = LIBRARY->objtypeh->getHandlerFor(MapObjectID(primaryID), MapObjectSubID(secondaryID));
  110. const std::string subtypeKey = handler->getSubTypeName();
  111. bool banned = true;
  112. objStruct->serializeBool(subtypeKey, banned);
  113. }
  114. }
  115. }
  116. }
  117. }
  118. else
  119. {
  120. const JsonNode & config = handler.getCurrent();
  121. const JsonNode & configBannedObjects = config["bannedObjects"];
  122. if(configBannedObjects.isVector())
  123. {
  124. // MOD COMPATIBILITY - 1.6 format
  125. for(const auto & node : configBannedObjects.Vector())
  126. {
  127. LIBRARY->objtypeh->resolveObjectCompoundId(node.String(),
  128. [this](CompoundMapObjectID objid)
  129. {
  130. addBannedObject(objid);
  131. }
  132. );
  133. }
  134. }
  135. else
  136. {
  137. for(const auto & node : configBannedObjects.Struct())
  138. {
  139. LIBRARY->identifiers()->requestIdentifierIfFound(node.second.getModScope(), "object", node.first, [this, node](int primaryID)
  140. {
  141. if (node.second.isBool())
  142. {
  143. if (node.second.Bool())
  144. addBannedObject(CompoundMapObjectID(primaryID, -1));
  145. }
  146. else
  147. {
  148. for (const auto & subNode : node.second.Struct())
  149. {
  150. const std::string jsonKey = LIBRARY->objtypeh->getJsonKey(primaryID);
  151. LIBRARY->identifiers()->requestIdentifierIfFound(node.second.getModScope(), jsonKey, subNode.first, [this, primaryID](int secondaryID)
  152. {
  153. addBannedObject(CompoundMapObjectID(primaryID, secondaryID));
  154. });
  155. }
  156. }
  157. });
  158. }
  159. }
  160. }
  161. // Serialize common objects
  162. if (handler.saving)
  163. {
  164. auto commonObjectsArray = handler.enterArray("commonObjects");
  165. commonObjectsArray.syncSize(customObjects, JsonNode::JsonType::DATA_STRUCT);
  166. for(size_t i = 0; i < customObjects.size(); ++i)
  167. {
  168. auto objectStruct = commonObjectsArray.enterStruct(i);
  169. const auto & object = customObjects[i];
  170. // Serialize object type/subtype
  171. std::string objectType = LIBRARY->objtypeh->getJsonKey(object.primaryID);
  172. objectStruct->serializeString("type", objectType);
  173. if(object.secondaryID != 0)
  174. {
  175. auto handler = LIBRARY->objtypeh->getHandlerFor(MapObjectID(object.primaryID), MapObjectSubID(object.secondaryID));
  176. std::string subtypeName = handler->getSubTypeName();
  177. objectStruct->serializeString("subtype", subtypeName);
  178. }
  179. // Serialize RMG properties
  180. {
  181. auto rmgStruct = objectStruct->enterStruct("rmg");
  182. int value = object.value;
  183. int rarity = object.probability;
  184. int zoneLimit = (object.maxPerZone == std::numeric_limits<int>::max()) ? 0 : object.maxPerZone;
  185. rmgStruct->serializeInt("value", value);
  186. rmgStruct->serializeInt("rarity", rarity);
  187. rmgStruct->serializeInt("zoneLimit", zoneLimit);
  188. }
  189. }
  190. }
  191. else
  192. {
  193. const JsonNode & config = handler.getCurrent();
  194. const JsonNode & configCommonObjects = config["commonObjects"];
  195. for (const auto & objectConfig : configCommonObjects.Vector())
  196. {
  197. auto rmg = objectConfig["rmg"].Struct();
  198. // TODO: Use common code with default rmg config
  199. ObjectInfo object;
  200. // TODO: Configure basic generateObject function
  201. object.value = rmg["value"].Integer();
  202. object.probability = rmg["rarity"].Integer();
  203. object.maxPerZone = rmg["zoneLimit"].Integer();
  204. if (object.maxPerZone == 0)
  205. object.maxPerZone = std::numeric_limits<int>::max();
  206. if (objectConfig["id"].isNull())
  207. {
  208. LIBRARY->identifiers()->requestIdentifierIfFound("object", objectConfig["type"], [this, object, objectConfig](int primaryID)
  209. {
  210. if (objectConfig["subtype"].isNull())
  211. {
  212. auto objectWithID = object;
  213. objectWithID.primaryID = primaryID;
  214. objectWithID.secondaryID = 0;
  215. addCustomObject(objectWithID);
  216. }
  217. else
  218. {
  219. const std::string jsonKey = LIBRARY->objtypeh->getJsonKey(primaryID);
  220. LIBRARY->identifiers()->requestIdentifierIfFound(jsonKey, objectConfig["subtype"], [this, primaryID, object](int secondaryID)
  221. {
  222. auto objectWithID = object;
  223. objectWithID.primaryID = primaryID;
  224. objectWithID.secondaryID = secondaryID;
  225. addCustomObject(objectWithID);
  226. });
  227. }
  228. });
  229. }
  230. else
  231. {
  232. // MOD COMPATIBILITY - 1.6 format
  233. auto objectName = objectConfig["id"].String();
  234. LIBRARY->objtypeh->resolveObjectCompoundId(objectName, [this, object](CompoundMapObjectID objid)
  235. {
  236. auto objectWithID = object;
  237. objectWithID.primaryID = objid.primaryID;
  238. objectWithID.secondaryID = objid.secondaryID;
  239. if (objectWithID.secondaryID == -1)
  240. objectWithID.secondaryID = 0;
  241. addCustomObject(objectWithID);
  242. });
  243. }
  244. }
  245. }
  246. }
  247. const std::vector<ObjectInfo> & ObjectConfig::getConfiguredObjects() const
  248. {
  249. return customObjects;
  250. }
  251. const std::vector<CompoundMapObjectID> & ObjectConfig::getBannedObjects() const
  252. {
  253. return bannedObjects;
  254. }
  255. const std::vector<ObjectConfig::EObjectCategory> & ObjectConfig::getBannedObjectCategories() const
  256. {
  257. return bannedObjectCategories;
  258. }
  259. VCMI_LIB_NAMESPACE_END