ObstacleSetHandler.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. /*
  2. * ObstacleSetHandler.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 "ObstacleSetHandler.h"
  12. #include "../modding/IdentifierStorage.h"
  13. VCMI_LIB_NAMESPACE_BEGIN
  14. ObstacleSet::ObstacleSet():
  15. type(INVALID),
  16. terrain(TerrainId::NONE)
  17. {
  18. }
  19. ObstacleSet::ObstacleSet(EObstacleType type, TerrainId terrain):
  20. type(type),
  21. terrain(terrain)
  22. {
  23. }
  24. void ObstacleSet::addObstacle(std::shared_ptr<const ObjectTemplate> obstacle)
  25. {
  26. obstacles.push_back(obstacle);
  27. }
  28. ObstacleSetFilter::ObstacleSetFilter(std::vector<ObstacleSet::EObstacleType> allowedTypes, TerrainId terrain = TerrainId::ANY_TERRAIN):
  29. allowedTypes(allowedTypes),
  30. terrain(terrain)
  31. {
  32. }
  33. ObstacleSetFilter::ObstacleSetFilter(ObstacleSet::EObstacleType allowedType, TerrainId terrain = TerrainId::ANY_TERRAIN):
  34. allowedTypes({allowedType}),
  35. terrain(terrain)
  36. {
  37. }
  38. bool ObstacleSetFilter::filter(const ObstacleSet &set) const
  39. {
  40. return (set.getTerrain() == terrain) || (terrain == TerrainId::ANY_TERRAIN);
  41. }
  42. TerrainId ObstacleSetFilter::getTerrain() const
  43. {
  44. return terrain;
  45. }
  46. TerrainId ObstacleSet::getTerrain() const
  47. {
  48. return terrain;
  49. }
  50. void ObstacleSet::setTerrain(TerrainId terrain)
  51. {
  52. this->terrain = terrain;
  53. }
  54. ObstacleSet::EObstacleType ObstacleSet::getType() const
  55. {
  56. return type;
  57. }
  58. void ObstacleSet::setType(EObstacleType type)
  59. {
  60. this->type = type;
  61. }
  62. std::vector<std::shared_ptr<const ObjectTemplate>> ObstacleSet::getObstacles() const
  63. {
  64. return obstacles;
  65. }
  66. ObstacleSet::EObstacleType ObstacleSetHandler::convertObstacleClass(MapObjectID id)
  67. {
  68. switch (id)
  69. {
  70. case Obj::MOUNTAIN:
  71. case Obj::VOLCANIC_VENT:
  72. case Obj::VOLCANO:
  73. case Obj::REEF:
  74. return ObstacleSet::MOUNTAINS;
  75. case Obj::OAK_TREES:
  76. case Obj::PINE_TREES:
  77. case Obj::TREES:
  78. case Obj::DEAD_VEGETATION:
  79. case Obj::HEDGE:
  80. case Obj::KELP:
  81. case Obj::WILLOW_TREES:
  82. case Obj::YUCCA_TREES:
  83. return ObstacleSet::TREES;
  84. case Obj::FROZEN_LAKE:
  85. case Obj::LAKE:
  86. case Obj::LAVA_FLOW:
  87. case Obj::LAVA_LAKE:
  88. return ObstacleSet::LAKES;
  89. case Obj::CANYON:
  90. case Obj::CRATER:
  91. case Obj::SAND_PIT:
  92. case Obj::TAR_PIT:
  93. return ObstacleSet::CRATERS;
  94. case Obj::HILL:
  95. case Obj::MOUND:
  96. case Obj::OUTCROPPING:
  97. case Obj::ROCK:
  98. case Obj::SAND_DUNE:
  99. case Obj::STALAGMITE:
  100. return ObstacleSet::ROCKS;
  101. case Obj::BUSH:
  102. case Obj::CACTUS:
  103. case Obj::FLOWERS:
  104. case Obj::MUSHROOMS:
  105. case Obj::LOG:
  106. case Obj::MANDRAKE:
  107. case Obj::MOSS:
  108. case Obj::PLANT:
  109. case Obj::SHRUB:
  110. case Obj::STUMP:
  111. case Obj::VINE:
  112. return ObstacleSet::PLANTS;
  113. case Obj::SKULL:
  114. return ObstacleSet::ANIMALS;
  115. default:
  116. return ObstacleSet::OTHER;
  117. }
  118. }
  119. ObstacleSet::EObstacleType ObstacleSet::typeFromString(const std::string &str)
  120. {
  121. static const std::map<std::string, EObstacleType> OBSTACLE_TYPE_NAMES =
  122. {
  123. {"mountain", MOUNTAINS},
  124. {"tree", TREES},
  125. {"lake", LAKES},
  126. {"crater", CRATERS},
  127. {"rock", ROCKS},
  128. {"plant", PLANTS},
  129. {"structure", STRUCTURES},
  130. {"animal", ANIMALS},
  131. {"other", OTHER}
  132. };
  133. if (OBSTACLE_TYPE_NAMES.find(str) != OBSTACLE_TYPE_NAMES.end())
  134. {
  135. return OBSTACLE_TYPE_NAMES.at(str);
  136. }
  137. // TODO: How to handle that?
  138. throw std::runtime_error("Invalid obstacle type: " + str);
  139. }
  140. std::string ObstacleSet::toString() const
  141. {
  142. static const std::map<EObstacleType, std::string> OBSTACLE_TYPE_STRINGS =
  143. {
  144. {MOUNTAINS, "mountain"},
  145. {TREES, "tree"},
  146. {LAKES, "lake"},
  147. {CRATERS, "crater"},
  148. {ROCKS, "rock"},
  149. {PLANTS, "plant"},
  150. {STRUCTURES, "structure"},
  151. {ANIMALS, "animal"},
  152. {OTHER, "other"}
  153. };
  154. return OBSTACLE_TYPE_STRINGS.at(type);
  155. }
  156. std::vector<ObstacleSet::EObstacleType> ObstacleSetFilter::getAllowedTypes() const
  157. {
  158. return allowedTypes;
  159. }
  160. std::vector<JsonNode> ObstacleSetHandler::loadLegacyData()
  161. {
  162. // TODO: Where to load objects.json?
  163. return {};
  164. }
  165. void ObstacleSetHandler::loadObject(std::string scope, std::string name, const JsonNode & data)
  166. {
  167. auto os = loadFromJson(scope, data, name, biomes.size());
  168. if(os)
  169. {
  170. addObstacleSet(os);
  171. }
  172. else
  173. {
  174. logMod->error("Failed to load obstacle set: %s", name);
  175. }
  176. // TODO: Define some const array of object types ("biome" etc.)
  177. VLC->identifiersHandler->registerObject(scope, "biome", name, biomes.back()->id);
  178. }
  179. void ObstacleSetHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index)
  180. {
  181. assert(objects.at(index) == nullptr); // ensure that this id was not loaded before
  182. auto os = loadFromJson(scope, data, name, index);
  183. if(os)
  184. {
  185. addObstacleSet(os);
  186. }
  187. else
  188. {
  189. logMod->error("Failed to load obstacle set: %s", name);
  190. }
  191. // TODO:
  192. VLC->identifiersHandler->registerObject(scope, "biome", name, biomes.at(index)->id);
  193. }
  194. std::shared_ptr<ObstacleSet> ObstacleSetHandler::loadFromJson(const std::string & scope, const JsonNode & json, const std::string & name, size_t index)
  195. {
  196. auto os = std::make_shared<ObstacleSet>();
  197. // TODO: Register ObstacleSet by its name
  198. auto biome = json["biome"].Struct();
  199. os->setType(ObstacleSet::typeFromString(biome["objectType"].String()));
  200. auto terrainName = biome["terrain"].String();
  201. VLC->identifiers()->requestIdentifier(scope, "terrain", terrainName, [os](si32 id)
  202. {
  203. os->setTerrain(TerrainId(id));
  204. });
  205. auto templates = json["templates"].Vector();
  206. for (const auto & node : templates)
  207. {
  208. // TODO: We need to store all the templates by their name
  209. // TODO: We need to store all the templates by their id
  210. logGlobal->info("Registering obstacle template: %s", node.String());
  211. /*
  212. FIXME:
  213. Warning: identifier AVXplns0 is not in camelCase!
  214. registered biome.templateSet1 as core:1701602145
  215. */
  216. VLC->identifiers()->requestIdentifier(scope, "obstacleTemplate", node.String(), [this, os](si32 id)
  217. {
  218. logGlobal->info("Resolved obstacle id: %d", id);
  219. os->addObstacle(obstacleTemplates[id]);
  220. });
  221. }
  222. return os;
  223. }
  224. void ObstacleSetHandler::addTemplate(const std::string & scope, const std::string &name, std::shared_ptr<const ObjectTemplate> tmpl)
  225. {
  226. auto id = obstacleTemplates.size();
  227. auto strippedName = name;
  228. auto pos = strippedName.find(".def");
  229. if(pos != std::string::npos)
  230. strippedName.erase(pos, 4);
  231. // TODO: Consider converting to lowercase?
  232. // Save by name
  233. VLC->identifiersHandler->registerObject(scope, "obstacleTemplate", strippedName, id);
  234. // Index by id
  235. obstacleTemplates[id] = tmpl;
  236. }
  237. void ObstacleSetHandler::addObstacleSet(std::shared_ptr<ObstacleSet> os)
  238. {
  239. // TODO: Allow to refer to existing obstacle set by its id (name)
  240. obstacleSets[os->getType()].push_back(os);
  241. biomes.push_back(os);
  242. }
  243. TObstacleTypes ObstacleSetHandler::getObstacles( const ObstacleSetFilter &filter) const
  244. {
  245. TObstacleTypes result;
  246. for (const auto &allowedType : filter.getAllowedTypes())
  247. {
  248. auto it = obstacleSets.find(allowedType);
  249. if(it != obstacleSets.end())
  250. {
  251. for (const auto &os : it->second)
  252. {
  253. if (filter.filter(*os))
  254. {
  255. result.push_back(os);
  256. }
  257. }
  258. }
  259. }
  260. return result;
  261. }
  262. VCMI_LIB_NAMESPACE_END