level_loader.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #include "level_loader.h"
  2. #include "../../render/gl/camera.h"
  3. #include "../../render/scene_renderer.h"
  4. #include "../core/component.h"
  5. #include "../core/world.h"
  6. #include "../systems/nation_registry.h"
  7. #include "../systems/owner_registry.h"
  8. #include "../units/factory.h"
  9. #include "../visuals/visual_catalog.h"
  10. #include "environment.h"
  11. #include "map_definition.h"
  12. #include "map_loader.h"
  13. #include "map_transformer.h"
  14. #include "terrain_service.h"
  15. #include "units/spawn_type.h"
  16. #include "units/troop_type.h"
  17. #include "units/unit.h"
  18. #include "utils/resource_utils.h"
  19. #include <QDebug>
  20. #include <QFile>
  21. #include <memory>
  22. #include <qglobal.h>
  23. #include <qstringliteral.h>
  24. namespace Game::Map {
  25. auto LevelLoader::loadFromAssets(
  26. const QString &map_path, Engine::Core::World &world,
  27. Render::GL::Renderer &renderer, Render::GL::Camera &camera,
  28. bool allow_default_player_barracks) -> LevelLoadResult {
  29. LevelLoadResult res;
  30. auto &owners = Game::Systems::OwnerRegistry::instance();
  31. Game::Visuals::VisualCatalog visual_catalog;
  32. const QString visuals_path = Utils::Resources::resolveResourcePath(
  33. QStringLiteral(":/assets/visuals/unit_visuals.json"));
  34. bool visuals_loaded = false;
  35. if (QFile::exists(visuals_path)) {
  36. QString visuals_err;
  37. visuals_loaded =
  38. visual_catalog.loadFromJsonFile(visuals_path, &visuals_err);
  39. if (!visuals_loaded && !visuals_err.isEmpty()) {
  40. qWarning() << "LevelLoader: Visual catalog parse failed:" << visuals_err;
  41. }
  42. } else {
  43. qInfo() << "LevelLoader: unit visuals catalog not found at" << visuals_path
  44. << "- continuing without overrides.";
  45. }
  46. auto unit_reg = std::make_shared<Game::Units::UnitFactoryRegistry>();
  47. Game::Units::registerBuiltInUnits(*unit_reg);
  48. Game::Map::MapTransformer::setFactoryRegistry(unit_reg);
  49. const QString resolved_map_path =
  50. Utils::Resources::resolveResourcePath(map_path);
  51. Game::Map::MapDefinition def;
  52. QString err;
  53. if (Game::Map::MapLoader::loadFromJsonFile(resolved_map_path, def, &err)) {
  54. res.ok = true;
  55. res.map_name = def.name;
  56. res.rainSettings = def.rain;
  57. res.biome_seed = def.biome.seed;
  58. Game::Map::TerrainService::instance().initialize(def);
  59. Game::Map::Environment::apply(def, renderer, camera);
  60. res.cam_fov = def.camera.fovY;
  61. res.cam_near = def.camera.near_plane;
  62. res.cam_far = def.camera.far_plane;
  63. res.grid_width = def.grid.width;
  64. res.grid_height = def.grid.height;
  65. res.tile_size = def.grid.tile_size;
  66. res.max_troops_per_player = def.max_troops_per_player;
  67. res.victoryConfig = def.victory;
  68. const Game::Visuals::VisualCatalog *catalog_ptr =
  69. visuals_loaded ? &visual_catalog : nullptr;
  70. auto rt =
  71. Game::Map::MapTransformer::apply_to_world(def, world, catalog_ptr);
  72. if (!rt.unit_ids.empty()) {
  73. res.player_unit_id = rt.unit_ids.front();
  74. } else {
  75. auto &nationRegistry = Game::Systems::NationRegistry::instance();
  76. auto reg = Game::Map::MapTransformer::getFactoryRegistry();
  77. if (reg) {
  78. Game::Units::SpawnParams sp;
  79. sp.position = QVector3D(0.0F, 0.0F, 0.0F);
  80. sp.player_id = 0;
  81. sp.spawn_type = Game::Units::SpawnType::Archer;
  82. sp.ai_controlled = !owners.is_player(sp.player_id);
  83. if (const auto *nation =
  84. nationRegistry.get_nation_for_player(sp.player_id)) {
  85. sp.nation_id = nation->id;
  86. } else {
  87. sp.nation_id = nationRegistry.default_nation_id();
  88. }
  89. if (auto unit =
  90. reg->create(Game::Units::SpawnType::Archer, world, sp)) {
  91. res.player_unit_id = unit->id();
  92. } else {
  93. qWarning() << "LevelLoader: Fallback archer spawn failed";
  94. }
  95. }
  96. }
  97. if (allow_default_player_barracks) {
  98. bool has_barracks = false;
  99. for (auto *e : world.get_entities_with<Engine::Core::UnitComponent>()) {
  100. if (auto *u = e->get_component<Engine::Core::UnitComponent>()) {
  101. if (u->spawn_type == Game::Units::SpawnType::Barracks &&
  102. owners.is_player(u->owner_id)) {
  103. has_barracks = true;
  104. break;
  105. }
  106. }
  107. }
  108. if (!has_barracks) {
  109. auto &nationRegistry = Game::Systems::NationRegistry::instance();
  110. auto reg2 = Game::Map::MapTransformer::getFactoryRegistry();
  111. if (reg2) {
  112. Game::Units::SpawnParams sp;
  113. sp.position = QVector3D(-4.0F, 0.0F, -3.0F);
  114. sp.player_id = owners.get_local_player_id();
  115. sp.spawn_type = Game::Units::SpawnType::Barracks;
  116. sp.ai_controlled = !owners.is_player(sp.player_id);
  117. if (const auto *nation =
  118. nationRegistry.get_nation_for_player(sp.player_id)) {
  119. sp.nation_id = nation->id;
  120. } else {
  121. sp.nation_id = nationRegistry.default_nation_id();
  122. }
  123. reg2->create(Game::Units::SpawnType::Barracks, world, sp);
  124. }
  125. }
  126. }
  127. } else {
  128. res.ok = false;
  129. res.errorMessage = QString("Map load failed: %1").arg(err);
  130. qWarning() << "LevelLoader: Map load failed:" << err
  131. << "(path:" << resolved_map_path << ')'
  132. << "- applying default environment";
  133. Game::Map::Environment::applyDefault(renderer, camera);
  134. res.ok = false;
  135. res.cam_fov = camera.get_fov();
  136. res.cam_near = camera.get_near();
  137. res.cam_far = camera.get_far();
  138. res.grid_width = 50;
  139. res.grid_height = 50;
  140. res.tile_size = 1.0F;
  141. auto &nationRegistry = Game::Systems::NationRegistry::instance();
  142. auto reg = Game::Map::MapTransformer::getFactoryRegistry();
  143. if (reg) {
  144. Game::Units::SpawnParams sp;
  145. sp.position = QVector3D(0.0F, 0.0F, 0.0F);
  146. sp.player_id = 0;
  147. sp.spawn_type = Game::Units::SpawnType::Archer;
  148. sp.ai_controlled = !owners.is_player(sp.player_id);
  149. if (const auto *nation =
  150. nationRegistry.get_nation_for_player(sp.player_id)) {
  151. sp.nation_id = nation->id;
  152. } else {
  153. sp.nation_id = nationRegistry.default_nation_id();
  154. }
  155. if (auto unit = reg->create(Game::Units::SpawnType::Archer, world, sp)) {
  156. res.player_unit_id = unit->id();
  157. }
  158. }
  159. }
  160. return res;
  161. }
  162. } // namespace Game::Map