game_state_restorer.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. #include "game_state_restorer.h"
  2. #include "game/core/component.h"
  3. #include "game/core/world.h"
  4. #include "game/game_config.h"
  5. #include "game/map/environment.h"
  6. #include "game/map/map_loader.h"
  7. #include "game/map/terrain_service.h"
  8. #include "game/map/visibility_service.h"
  9. #include "game/systems/building_collision_registry.h"
  10. #include "game/systems/command_service.h"
  11. #include "game/systems/game_state_serializer.h"
  12. #include "game/systems/global_stats_registry.h"
  13. #include "game/systems/owner_registry.h"
  14. #include "game/systems/troop_count_registry.h"
  15. #include "game/units/troop_config.h"
  16. #include "game/units/troop_type.h"
  17. #include "game_engine.h"
  18. #include "minimap_manager.h"
  19. #include "render/gl/camera.h"
  20. #include "render/ground/biome_renderer.h"
  21. #include "render/ground/bridge_renderer.h"
  22. #include "render/ground/firecamp_renderer.h"
  23. #include "render/ground/fog_renderer.h"
  24. #include "render/ground/ground_renderer.h"
  25. #include "render/ground/olive_renderer.h"
  26. #include "render/ground/pine_renderer.h"
  27. #include "render/ground/plant_renderer.h"
  28. #include "render/ground/river_renderer.h"
  29. #include "render/ground/riverbank_renderer.h"
  30. #include "render/ground/road_renderer.h"
  31. #include "render/ground/stone_renderer.h"
  32. #include "render/ground/terrain_renderer.h"
  33. #include "render/scene_renderer.h"
  34. #include <QDebug>
  35. void GameStateRestorer::rebuild_entity_cache(Engine::Core::World *world,
  36. EntityCache &entity_cache,
  37. int local_owner_id) {
  38. if (!world) {
  39. entity_cache.reset();
  40. return;
  41. }
  42. entity_cache.reset();
  43. auto &owners = Game::Systems::OwnerRegistry::instance();
  44. auto entities = world->get_entities_with<Engine::Core::UnitComponent>();
  45. for (auto *e : entities) {
  46. auto *unit = e->get_component<Engine::Core::UnitComponent>();
  47. if ((unit == nullptr) || unit->health <= 0) {
  48. continue;
  49. }
  50. if (unit->owner_id == local_owner_id) {
  51. if (unit->spawn_type == Game::Units::SpawnType::Barracks) {
  52. entity_cache.player_barracks_alive = true;
  53. } else {
  54. int const production_cost =
  55. Game::Units::TroopConfig::instance().getProductionCost(
  56. unit->spawn_type);
  57. entity_cache.player_troop_count += production_cost;
  58. }
  59. } else if (owners.is_ai(unit->owner_id)) {
  60. if (unit->spawn_type == Game::Units::SpawnType::Barracks) {
  61. entity_cache.enemy_barracks_count++;
  62. entity_cache.enemy_barracks_alive = true;
  63. }
  64. }
  65. }
  66. }
  67. void GameStateRestorer::rebuild_registries_after_load(
  68. Engine::Core::World *world, int &selected_player_id,
  69. Game::Systems::LevelSnapshot &level, int local_owner_id) {
  70. if (!world) {
  71. return;
  72. }
  73. auto &owner_registry = Game::Systems::OwnerRegistry::instance();
  74. auto &troops = Game::Systems::TroopCountRegistry::instance();
  75. troops.rebuild_from_world(*world);
  76. auto &stats_registry = Game::Systems::GlobalStatsRegistry::instance();
  77. stats_registry.rebuild_from_world(*world);
  78. const auto &all_owners = owner_registry.get_all_owners();
  79. for (const auto &owner : all_owners) {
  80. if (owner.type == Game::Systems::OwnerType::Player ||
  81. owner.type == Game::Systems::OwnerType::AI) {
  82. stats_registry.mark_game_start(owner.owner_id);
  83. }
  84. }
  85. rebuild_building_collisions(world);
  86. level.player_unit_id = 0;
  87. auto units = world->get_entities_with<Engine::Core::UnitComponent>();
  88. for (auto *entity : units) {
  89. auto *unit = entity->get_component<Engine::Core::UnitComponent>();
  90. if (unit == nullptr) {
  91. continue;
  92. }
  93. if (unit->owner_id == local_owner_id) {
  94. level.player_unit_id = entity->get_id();
  95. break;
  96. }
  97. }
  98. if (selected_player_id != local_owner_id) {
  99. selected_player_id = local_owner_id;
  100. }
  101. }
  102. void GameStateRestorer::rebuild_building_collisions(
  103. Engine::Core::World *world) {
  104. auto &registry = Game::Systems::BuildingCollisionRegistry::instance();
  105. registry.clear();
  106. if (!world) {
  107. return;
  108. }
  109. auto buildings = world->get_entities_with<Engine::Core::BuildingComponent>();
  110. for (auto *entity : buildings) {
  111. auto *transform = entity->get_component<Engine::Core::TransformComponent>();
  112. auto *unit = entity->get_component<Engine::Core::UnitComponent>();
  113. if ((transform == nullptr) || (unit == nullptr)) {
  114. continue;
  115. }
  116. registry.register_building(
  117. entity->get_id(), Game::Units::spawn_typeToString(unit->spawn_type),
  118. transform->position.x, transform->position.z, unit->owner_id);
  119. }
  120. }
  121. void GameStateRestorer::restore_environment_from_metadata(
  122. const QJsonObject &metadata, Engine::Core::World *world,
  123. const RendererRefs &renderers, Game::Systems::LevelSnapshot &level,
  124. int local_owner_id, const ViewportState &viewport) {
  125. if (!world) {
  126. return;
  127. }
  128. const auto fallback_grid_width = metadata.value("grid_width").toInt(50);
  129. const auto fallback_grid_height = metadata.value("grid_height").toInt(50);
  130. const float fallback_tile_size =
  131. static_cast<float>(metadata.value("tile_size").toDouble(1.0));
  132. auto &terrain_service = Game::Map::TerrainService::instance();
  133. bool const terrain_already_restored = terrain_service.is_initialized();
  134. Game::Map::MapDefinition def;
  135. QString map_error;
  136. bool loaded_definition = false;
  137. const QString &map_path = level.map_path;
  138. if (!terrain_already_restored && !map_path.isEmpty()) {
  139. loaded_definition =
  140. Game::Map::MapLoader::loadFromJsonFile(map_path, def, &map_error);
  141. if (!loaded_definition) {
  142. qWarning() << "GameStateRestorer: Failed to load map definition from"
  143. << map_path << "during save load:" << map_error;
  144. }
  145. }
  146. if (!terrain_already_restored && loaded_definition) {
  147. terrain_service.initialize(def);
  148. if (!def.name.isEmpty()) {
  149. level.map_name = def.name;
  150. }
  151. level.cam_fov = def.camera.fovY;
  152. level.cam_near = def.camera.near_plane;
  153. level.cam_far = def.camera.far_plane;
  154. }
  155. if (renderers.renderer && renderers.camera) {
  156. if (loaded_definition) {
  157. Game::Map::Environment::apply(def, *renderers.renderer,
  158. *renderers.camera);
  159. } else {
  160. Game::Map::Environment::applyDefault(*renderers.renderer,
  161. *renderers.camera);
  162. }
  163. }
  164. if (terrain_service.is_initialized()) {
  165. const auto *height_map = terrain_service.get_height_map();
  166. const int grid_width =
  167. (height_map != nullptr) ? height_map->getWidth() : fallback_grid_width;
  168. const int grid_height = (height_map != nullptr) ? height_map->getHeight()
  169. : fallback_grid_height;
  170. const float tile_size = (height_map != nullptr) ? height_map->getTileSize()
  171. : fallback_tile_size;
  172. if (renderers.ground) {
  173. renderers.ground->configure(tile_size, grid_width, grid_height);
  174. renderers.ground->set_biome(terrain_service.biome_settings());
  175. }
  176. if (height_map != nullptr) {
  177. if (renderers.terrain) {
  178. renderers.terrain->configure(*height_map,
  179. terrain_service.biome_settings());
  180. }
  181. if (renderers.river) {
  182. renderers.river->configure(height_map->getRiverSegments(),
  183. height_map->getTileSize());
  184. }
  185. if (renderers.road) {
  186. renderers.road->configure(terrain_service.road_segments(),
  187. height_map->getTileSize());
  188. }
  189. if (renderers.riverbank) {
  190. renderers.riverbank->configure(height_map->getRiverSegments(),
  191. *height_map);
  192. }
  193. if (renderers.bridge) {
  194. renderers.bridge->configure(height_map->getBridges(),
  195. height_map->getTileSize());
  196. }
  197. if (renderers.biome) {
  198. renderers.biome->configure(*height_map,
  199. terrain_service.biome_settings());
  200. }
  201. if (renderers.stone) {
  202. renderers.stone->configure(*height_map,
  203. terrain_service.biome_settings());
  204. }
  205. if (renderers.plant) {
  206. renderers.plant->configure(*height_map,
  207. terrain_service.biome_settings());
  208. }
  209. if (renderers.pine) {
  210. renderers.pine->configure(*height_map,
  211. terrain_service.biome_settings());
  212. }
  213. if (renderers.olive) {
  214. renderers.olive->configure(*height_map,
  215. terrain_service.biome_settings());
  216. }
  217. if (renderers.firecamp) {
  218. renderers.firecamp->configure(*height_map,
  219. terrain_service.biome_settings());
  220. }
  221. }
  222. Game::Systems::CommandService::initialize(grid_width, grid_height);
  223. auto &visibility_service = Game::Map::VisibilityService::instance();
  224. visibility_service.initialize(grid_width, grid_height, tile_size);
  225. visibility_service.computeImmediate(*world, local_owner_id);
  226. if (renderers.fog && visibility_service.is_initialized()) {
  227. renderers.fog->update_mask(
  228. visibility_service.getWidth(), visibility_service.getHeight(),
  229. visibility_service.getTileSize(), visibility_service.snapshotCells());
  230. }
  231. } else {
  232. Game::Map::MapDefinition fallback_def;
  233. fallback_def.grid.width = fallback_grid_width;
  234. fallback_def.grid.height = fallback_grid_height;
  235. fallback_def.grid.tile_size = fallback_tile_size;
  236. Game::Systems::CommandService::initialize(fallback_grid_width,
  237. fallback_grid_height);
  238. auto &visibility_service = Game::Map::VisibilityService::instance();
  239. visibility_service.initialize(fallback_grid_width, fallback_grid_height,
  240. fallback_tile_size);
  241. visibility_service.computeImmediate(*world, local_owner_id);
  242. if (renderers.fog && visibility_service.is_initialized()) {
  243. renderers.fog->update_mask(
  244. visibility_service.getWidth(), visibility_service.getHeight(),
  245. visibility_service.getTileSize(), visibility_service.snapshotCells());
  246. }
  247. }
  248. }