game_state_serializer.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #include "game_state_serializer.h"
  2. #include "app/utils/json_vec_utils.h"
  3. #include "game/game_config.h"
  4. #include "game/map/terrain_service.h"
  5. #include "render/gl/camera.h"
  6. #include <algorithm>
  7. #include <qglobal.h>
  8. #include <qjsonobject.h>
  9. #include <qvectornd.h>
  10. namespace Game::Systems {
  11. auto GameStateSerializer::build_metadata(
  12. const Engine::Core::World &, const Render::GL::Camera *camera,
  13. const LevelSnapshot &level, const RuntimeSnapshot &runtime) -> QJsonObject {
  14. QJsonObject metadata;
  15. metadata["map_path"] = level.map_path;
  16. metadata["map_name"] = level.map_name;
  17. metadata["max_troops_per_player"] = level.max_troops_per_player;
  18. metadata["local_owner_id"] = runtime.local_owner_id;
  19. metadata["player_unit_id"] = static_cast<qint64>(level.player_unit_id);
  20. metadata["gameMaxTroopsPerPlayer"] =
  21. Game::GameConfig::instance().get_max_troops_per_player();
  22. const auto &terrain_service = Game::Map::TerrainService::instance();
  23. if (const auto *height_map = terrain_service.get_height_map()) {
  24. metadata["grid_width"] = height_map->getWidth();
  25. metadata["grid_height"] = height_map->getHeight();
  26. metadata["tile_size"] = height_map->getTileSize();
  27. }
  28. if (camera != nullptr) {
  29. QJsonObject camera_obj;
  30. camera_obj["position"] =
  31. App::JsonUtils::vec3ToJsonArray(camera->get_position());
  32. camera_obj["target"] =
  33. App::JsonUtils::vec3ToJsonArray(camera->get_target());
  34. camera_obj["distance"] = camera->get_distance();
  35. camera_obj["pitch_deg"] = camera->get_pitch_deg();
  36. camera_obj["fov"] = camera->get_fov();
  37. camera_obj["near"] = camera->get_near();
  38. camera_obj["far"] = camera->get_far();
  39. metadata["camera"] = camera_obj;
  40. }
  41. QJsonObject runtime_obj;
  42. runtime_obj["paused"] = runtime.paused;
  43. runtime_obj["time_scale"] = runtime.time_scale;
  44. runtime_obj["victoryState"] = runtime.victory_state;
  45. runtime_obj["cursorMode"] = runtime.cursor_mode;
  46. runtime_obj["selectedPlayerId"] = runtime.selected_player_id;
  47. runtime_obj["followSelection"] = runtime.follow_selection;
  48. metadata["runtime"] = runtime_obj;
  49. return metadata;
  50. }
  51. void GameStateSerializer::restore_camera_from_metadata(
  52. const QJsonObject &metadata, Render::GL::Camera *camera, int viewport_width,
  53. int viewport_height) {
  54. if (!metadata.contains("camera") || (camera == nullptr)) {
  55. return;
  56. }
  57. const auto camera_obj = metadata.value("camera").toObject();
  58. const QVector3D position = App::JsonUtils::jsonArrayToVec3(
  59. camera_obj.value("position"), camera->get_position());
  60. const QVector3D target = App::JsonUtils::jsonArrayToVec3(
  61. camera_obj.value("target"), camera->get_target());
  62. camera->look_at(position, target, QVector3D(0.0F, 1.0F, 0.0F));
  63. const float near_plane =
  64. static_cast<float>(camera_obj.value("near").toDouble(camera->get_near()));
  65. const float far_plane =
  66. static_cast<float>(camera_obj.value("far").toDouble(camera->get_far()));
  67. const float fov =
  68. static_cast<float>(camera_obj.value("fov").toDouble(camera->get_fov()));
  69. float aspect = camera->get_aspect();
  70. if (viewport_height > 0) {
  71. aspect = float(viewport_width) / float(std::max(1, viewport_height));
  72. }
  73. camera->set_perspective(fov, aspect, near_plane, far_plane);
  74. }
  75. void GameStateSerializer::restore_runtime_from_metadata(
  76. const QJsonObject &metadata, RuntimeSnapshot &runtime) {
  77. if (!metadata.contains("runtime")) {
  78. return;
  79. }
  80. const auto runtime_obj = metadata.value("runtime").toObject();
  81. if (runtime_obj.contains("paused")) {
  82. runtime.paused = runtime_obj.value("paused").toBool(runtime.paused);
  83. }
  84. if (runtime_obj.contains("time_scale")) {
  85. runtime.time_scale = static_cast<float>(
  86. runtime_obj.value("time_scale").toDouble(runtime.time_scale));
  87. }
  88. runtime.victory_state =
  89. runtime_obj.value("victoryState").toString(runtime.victory_state);
  90. if (runtime_obj.contains("cursorMode")) {
  91. const auto cursor_value = runtime_obj.value("cursorMode");
  92. if (cursor_value.isDouble()) {
  93. runtime.cursor_mode = cursor_value.toInt(0);
  94. }
  95. }
  96. if (metadata.contains("local_owner_id")) {
  97. runtime.local_owner_id =
  98. metadata.value("local_owner_id").toInt(runtime.local_owner_id);
  99. }
  100. runtime.selected_player_id =
  101. runtime_obj.value("selectedPlayerId").toInt(runtime.selected_player_id);
  102. runtime.follow_selection =
  103. runtime_obj.value("followSelection").toBool(runtime.follow_selection);
  104. }
  105. void GameStateSerializer::restore_level_from_metadata(
  106. const QJsonObject &metadata, LevelSnapshot &level) {
  107. const QString map_path = metadata.value("map_path").toString();
  108. if (!map_path.isEmpty()) {
  109. level.map_path = map_path;
  110. }
  111. if (metadata.contains("map_name")) {
  112. level.map_name = metadata.value("map_name").toString(level.map_name);
  113. }
  114. if (metadata.contains("player_unit_id")) {
  115. level.player_unit_id = static_cast<Engine::Core::EntityID>(
  116. metadata.value("player_unit_id").toVariant().toULongLong());
  117. }
  118. int max_troops = metadata.value("max_troops_per_player")
  119. .toInt(level.max_troops_per_player);
  120. if (max_troops <= 0) {
  121. max_troops = Game::GameConfig::instance().get_max_troops_per_player();
  122. }
  123. level.max_troops_per_player = max_troops;
  124. Game::GameConfig::instance().set_max_troops_per_player(max_troops);
  125. }
  126. } // namespace Game::Systems