LCOV - code coverage report
Current view: top level - core/map - Map.hpp (source / functions) Coverage Total Hit
Test: coverage-src.info Lines: 74.5 % 51 38
Test Date: 2025-05-27 23:26:07 Functions: 70.4 % 54 38

            Line data    Source code
       1              : #ifndef __MAP_HPP__
       2              : #define __MAP_HPP__
       3              : 
       4              : #include "core/map/PMSConstants.hpp"
       5              : #include "core/map/PMSEnums.hpp"
       6              : #include "core/map/PMSStructs.hpp"
       7              : 
       8              : #include "core/math/Glm.hpp"
       9              : #include "core/data/IFileReader.hpp"
      10              : #include "core/data/FileReader.hpp"
      11              : #include "core/data/IFileWriter.hpp"
      12              : #include "core/data/FileWriter.hpp"
      13              : 
      14              : #include "core/utility/Observable.hpp"
      15              : 
      16              : #include <bitset>
      17              : #include <optional>
      18              : #include <utility>
      19              : #include <vector>
      20              : #include <sstream>
      21              : #include <cstring>
      22              : #include <span>
      23              : #include <array>
      24              : #include <memory>
      25              : #include <filesystem>
      26              : 
      27              : namespace Soldank
      28              : {
      29              : struct MapData
      30              : {
      31              :     std::array<float, 4> boundaries_xy;
      32              :     float polygons_min_x;
      33              :     float polygons_max_x;
      34              :     float polygons_min_y;
      35              :     float polygons_max_y;
      36              :     float width;
      37              :     float height;
      38              :     float center_x;
      39              :     float center_y;
      40              : 
      41              :     int version;
      42              : 
      43              :     std::optional<std::string> name;
      44              :     std::string description;
      45              :     std::string texture_name;
      46              : 
      47              :     PMSColor background_top_color;
      48              :     PMSColor background_bottom_color;
      49              : 
      50              :     int jet_count;
      51              :     unsigned char grenades_count;
      52              :     unsigned char medikits_count;
      53              :     PMSWeatherType weather_type;
      54              :     PMSStepType step_type;
      55              :     int random_id;
      56              : 
      57              :     std::vector<PMSPolygon> polygons;
      58              : 
      59              :     int sectors_size;
      60              :     int sectors_count;
      61              : 
      62              :     std::vector<std::vector<PMSSector>> sectors_poly;
      63              :     std::vector<PMSScenery> scenery_instances;
      64              :     std::vector<PMSSceneryType> scenery_types;
      65              :     std::vector<PMSCollider> colliders;
      66              :     std::vector<PMSSpawnPoint> spawn_points;
      67              :     std::vector<PMSWayPoint> way_points;
      68              : };
      69              : 
      70              : struct MapChangeEvents
      71              : {
      72              :     Observable<const PMSPolygon&> added_new_polygon;
      73              :     Observable<const PMSPolygon&, const std::vector<PMSPolygon>&> removed_polygon;
      74              :     Observable<const std::vector<PMSPolygon>, const std::vector<PMSPolygon>&> added_new_polygons;
      75              :     Observable<const std::vector<PMSPolygon>, const std::vector<PMSPolygon>&> removed_polygons;
      76              :     Observable<const PMSSpawnPoint&, unsigned int> added_new_spawn_point;
      77              :     Observable<const PMSSpawnPoint&, unsigned int> removed_spawn_point;
      78              :     Observable<const std::vector<PMSSpawnPoint>&> removed_spawn_points;
      79              :     Observable<const std::vector<PMSSpawnPoint>&> added_spawn_points;
      80              :     Observable<const PMSColor&, const PMSColor&, std::span<const float, 4>>
      81              :       changed_background_color;
      82              :     Observable<const std::string&> changed_texture_name;
      83              :     Observable<const PMSScenery&, unsigned int> added_new_scenery;
      84              :     Observable<const PMSScenery&, unsigned int, const std::vector<PMSScenery>&> removed_scenery;
      85              :     Observable<const PMSSceneryType&> added_new_scenery_type;
      86              :     Observable<const PMSSceneryType&, unsigned short, const std::vector<PMSSceneryType>&>
      87              :       removed_scenery_type;
      88              :     Observable<const std::vector<PMSScenery>&> added_sceneries;
      89              :     Observable<const std::vector<PMSScenery>&> removed_sceneries;
      90              :     Observable<const std::vector<std::pair<unsigned short, PMSSceneryType>>&> removed_scenery_types;
      91              :     Observable<const std::vector<PMSScenery>&> modified_sceneries;
      92              :     Observable<const std::vector<PMSPolygon>&> modified_polygons;
      93              :     Observable<const std::vector<PMSSpawnPoint>&> modified_spawn_points;
      94              : };
      95              : 
      96              : class Map
      97              : {
      98              : public:
      99            2 :     Map() = default;
     100            1 :     Map(MapData map_data)
     101            1 :         : map_data_(std::move(map_data)){};
     102              : 
     103              :     void CreateEmptyMap();
     104              :     void LoadMap(const std::filesystem::path& map_path,
     105              :                  const IFileReader& file_reader = FileReader());
     106              :     void SaveMap(const std::filesystem::path& map_path,
     107              :                  std::shared_ptr<IFileWriter> file_writer = std::make_shared<FileWriter>());
     108              : 
     109              :     static bool PointInPoly(glm::vec2 p, PMSPolygon poly);
     110              :     bool PointInPolyEdges(float x, float y, int i) const;
     111              :     static bool PointInScenery(glm::vec2 p, const PMSScenery& scenery);
     112              :     glm::vec2 ClosestPerpendicular(int j, glm::vec2 pos, float* d, int* n) const;
     113              :     bool CollisionTest(glm::vec2 pos, glm::vec2& perp_vec, bool is_flag = false) const;
     114              :     bool RayCast(glm::vec2 a,
     115              :                  glm::vec2 b,
     116              :                  float& distance,
     117              :                  float max_dist,
     118              :                  bool player = false,
     119              :                  bool flag = false,
     120              :                  bool bullet = true,
     121              :                  bool check_collider = false,
     122              :                  std::uint8_t team_id = 0) const;
     123              :     static bool LineInPoly(const glm::vec2& a,
     124              :                            const glm::vec2& b,
     125              :                            const PMSPolygon& polygon,
     126              :                            glm::vec2& v);
     127              : 
     128              :     MapChangeEvents& GetMapChangeEvents() { return map_change_events_; }
     129              : 
     130              :     PMSPolygon AddNewPolygon(const PMSPolygon& polygon);
     131              :     void AddPolygons(const std::vector<PMSPolygon>& polygons);
     132              :     PMSPolygon RemovePolygonById(unsigned int id);
     133              :     void RemovePolygonsById(const std::vector<unsigned int>& polygon_ids);
     134              :     void SetPolygonVerticesColorById(
     135              :       const std::vector<std::pair<std::pair<unsigned int, unsigned int>, PMSColor>>&
     136              :         polygon_vertices_with_new_color);
     137              :     void MovePolygonVerticesById(
     138              :       const std::vector<std::pair<std::pair<unsigned int, unsigned int>, glm::vec2>>&
     139              :         polygon_vertices_with_new_position);
     140              :     void SetPolygonsById(const std::vector<std::pair<unsigned int, PMSPolygon>>& polygons);
     141              : 
     142              :     unsigned int AddNewSpawnPoint(const PMSSpawnPoint& spawn_point);
     143              :     PMSSpawnPoint RemoveSpawnPointById(unsigned int id);
     144              :     void AddSpawnPoints(const std::vector<std::pair<unsigned int, PMSSpawnPoint>>& spawn_points);
     145              :     void RemoveSpawnPointsById(const std::vector<unsigned int>& spawn_point_ids);
     146              :     void MoveSpawnPointsById(
     147              :       const std::vector<std::pair<unsigned int, glm::ivec2>>& spawn_point_ids_with_new_position);
     148              :     void SetSpawnPointsById(
     149              :       const std::vector<std::pair<unsigned int, PMSSpawnPoint>>& spawn_points);
     150              : 
     151              :     unsigned int AddNewScenery(const PMSScenery& scenery, const std::string& file_name);
     152              :     PMSScenery RemoveSceneryById(unsigned int id);
     153              :     void AddSceneries(
     154              :       const std::vector<std::pair<unsigned int, std::pair<PMSScenery, std::string>>>& sceneries);
     155              :     void RemoveSceneriesById(const std::vector<unsigned int>& scenery_ids);
     156              :     void SetSceneriesColorById(
     157              :       const std::vector<std::pair<unsigned int, PMSColor>>& scenery_ids_with_new_color);
     158              :     void MoveSceneriesById(
     159              :       const std::vector<std::pair<unsigned int, glm::vec2>>& scenery_ids_with_new_position);
     160              :     void SetSceneriesById(const std::vector<std::pair<unsigned int, PMSScenery>>& sceneries);
     161              : 
     162              :     static std::array<glm::vec2, 4> GetSceneryVertexPositions(const PMSScenery& scenery);
     163              : 
     164            1 :     int GetVersion() const { return map_data_.version; }
     165              : 
     166              :     std::optional<std::string> GetName() const { return map_data_.name; }
     167              :     void SetName(const std::string& new_name) { map_data_.name = new_name; }
     168              : 
     169              :     void SetDescription(const std::string& new_description)
     170              :     {
     171              :         map_data_.description = new_description;
     172              :     }
     173              : 
     174            2 :     std::string GetDescription() const { return map_data_.description; }
     175              : 
     176              :     void SetBackgroundTopColor(const PMSColor& color)
     177              :     {
     178              :         map_data_.background_top_color = color;
     179              :         map_change_events_.changed_background_color.Notify(
     180              :           map_data_.background_top_color, map_data_.background_bottom_color, GetBoundaries());
     181              :     }
     182            1 :     PMSColor GetBackgroundTopColor() const { return map_data_.background_top_color; }
     183              : 
     184              :     void SetBackgroundBottomColor(const PMSColor& color)
     185              :     {
     186              :         map_data_.background_bottom_color = color;
     187              :         map_change_events_.changed_background_color.Notify(
     188              :           map_data_.background_top_color, map_data_.background_bottom_color, GetBoundaries());
     189              :     }
     190            1 :     PMSColor GetBackgroundBottomColor() const { return map_data_.background_bottom_color; }
     191              : 
     192            1 :     std::span<const float, 4> GetBoundaries() const { return map_data_.boundaries_xy; }
     193              : 
     194           12 :     const std::vector<PMSPolygon>& GetPolygons() const { return map_data_.polygons; }
     195              : 
     196            4 :     unsigned int GetPolygonsCount() const { return map_data_.polygons.size(); }
     197              : 
     198            4 :     const std::vector<PMSScenery>& GetSceneryInstances() const
     199              :     {
     200            4 :         return map_data_.scenery_instances;
     201              :     }
     202              : 
     203            4 :     const std::vector<PMSSceneryType>& GetSceneryTypes() const { return map_data_.scenery_types; }
     204              : 
     205            4 :     const std::vector<PMSSpawnPoint>& GetSpawnPoints() const { return map_data_.spawn_points; }
     206              : 
     207            4 :     const std::vector<PMSCollider>& GetColliders() const { return map_data_.colliders; }
     208              : 
     209            4 :     const std::vector<PMSWayPoint>& GetWayPoints() const { return map_data_.way_points; }
     210              : 
     211              :     void SetTextureName(const std::string& texture_name)
     212              :     {
     213              :         map_data_.texture_name = texture_name;
     214              :         map_change_events_.changed_texture_name.Notify(map_data_.texture_name);
     215              :     }
     216            1 :     const std::string& GetTextureName() const { return map_data_.texture_name; }
     217              : 
     218              :     void SetJetCount(int jet_count) { map_data_.jet_count = jet_count; }
     219            1 :     int GetJetCount() const { return map_data_.jet_count; }
     220              : 
     221              :     void SetGrenadesCount(unsigned char grenades_count)
     222              :     {
     223              :         map_data_.grenades_count = grenades_count;
     224              :     }
     225            1 :     unsigned char GetGrenadesCount() const { return map_data_.grenades_count; }
     226              : 
     227              :     void SetMedikitsCount(unsigned char medikits_count)
     228              :     {
     229              :         map_data_.medikits_count = medikits_count;
     230              :     }
     231            1 :     unsigned char GetMedikitsCount() const { return map_data_.medikits_count; }
     232              : 
     233              :     void SetWeatherType(PMSWeatherType weather_type) { map_data_.weather_type = weather_type; }
     234            1 :     PMSWeatherType GetWeatherType() const { return map_data_.weather_type; }
     235              :     std::string GetWeatherTypeText() const
     236              :     {
     237              :         switch (map_data_.weather_type) {
     238              :             case PMSWeatherType::None:
     239              :                 return "None";
     240              :             case PMSWeatherType::Rain:
     241              :                 return "Rain";
     242              :             case PMSWeatherType::Sandstorm:
     243              :                 return "Sandstorm";
     244              :             case PMSWeatherType::Snow:
     245              :                 return "Snow";
     246              :         }
     247              :     }
     248              : 
     249              :     void SetStepType(PMSStepType step_type) { map_data_.step_type = step_type; }
     250            1 :     PMSStepType GetStepType() const { return map_data_.step_type; }
     251              :     std::string GetStepTypeText() const
     252              :     {
     253              :         switch (map_data_.step_type) {
     254              :             case PMSStepType::HardGround:
     255              :                 return "Hard";
     256              :             case PMSStepType::SoftGround:
     257              :                 return "Soft";
     258              :             case PMSStepType::None:
     259              :                 return "None";
     260              :         }
     261              :     }
     262              : 
     263            1 :     int GetSectorsSize() const { return map_data_.sectors_size; }
     264              : 
     265            1 :     int GetSectorsCount() const { return map_data_.sectors_count; }
     266              : 
     267         2610 :     const PMSSector& GetSector(unsigned int x, unsigned int y) const
     268              :     {
     269         2610 :         return map_data_.sectors_poly[x][y];
     270              :     }
     271              : 
     272              :     std::optional<PMSSpawnPoint> FindFirstSpawnPoint(PMSSpawnPointType spawn_point_type) const;
     273              : 
     274              :     void GenerateSectors();
     275              :     glm::vec2 GetCenter() const { return { map_data_.center_x, map_data_.center_y }; }
     276              : 
     277              :     enum MapBoundary
     278              :     {
     279              :         TopBoundary = 0,
     280              :         BottomBoundary,
     281              :         LeftBoundary,
     282              :         RightBoundary
     283              :     };
     284              : 
     285              : private:
     286              :     MapData map_data_;
     287              :     MapChangeEvents map_change_events_;
     288              : 
     289              :     template<typename DataType>
     290           54 :     static void ReadFromBuffer(std::stringstream& buffer, DataType& variable_to_save_data)
     291              :     {
     292           54 :         buffer.read((char*)&variable_to_save_data, sizeof(DataType));
     293           54 :     }
     294              : 
     295            3 :     static void ReadStringFromBuffer(std::stringstream& buffer,
     296              :                                      std::string& string_to_save_data,
     297              :                                      unsigned int max_string_size)
     298              :     {
     299            3 :         unsigned char string_size = 0;
     300            3 :         ReadFromBuffer(buffer, string_size);
     301              :         // We need an array with dynamic size here
     302              :         // NOLINTNEXTLINE(modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
     303            3 :         auto bytes = std::make_unique<char[]>(string_size);
     304            3 :         buffer.read(bytes.get(), string_size);
     305            3 :         string_to_save_data.assign(bytes.get(), string_size);
     306              :         // We need an array with dynamic size here
     307              :         // NOLINTNEXTLINE(modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
     308            3 :         auto filler = std::make_unique<char[]>(max_string_size - string_size);
     309            3 :         buffer.read(filler.get(), max_string_size - string_size);
     310            3 :     }
     311              : 
     312              :     template<typename DataType>
     313            0 :     static void AppendToFileWriter(std::shared_ptr<IFileWriter>& file_writer, const DataType& data)
     314              :     {
     315              :         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
     316            0 :         file_writer->AppendData(reinterpret_cast<const char*>(&data), sizeof(data));
     317            0 :     }
     318              : 
     319            0 :     static void AppendStringToFileWriter(std::shared_ptr<IFileWriter>& file_writer,
     320              :                                          const std::string& data,
     321              :                                          unsigned int max_string_size)
     322              :     {
     323            0 :         unsigned char string_size = data.length();
     324              :         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
     325            0 :         file_writer->AppendData(reinterpret_cast<char*>(&string_size), sizeof(string_size));
     326            0 :         unsigned long long data_size = data.length() * sizeof(char);
     327            0 :         file_writer->AppendData(data.c_str(), (std::streamsize)data_size);
     328            0 :         std::array<char, 64> filler{};
     329            0 :         filler.fill(0);
     330            0 :         data_size = (max_string_size - data.length()) * sizeof(char);
     331            0 :         file_writer->AppendData(filler.data(), (std::streamsize)data_size);
     332            0 :     }
     333              : 
     334              :     void ReadPolygonsFromBuffer(std::stringstream& buffer);
     335              :     void ReadSectorsFromBuffer(std::stringstream& buffer);
     336              :     void ReadSceneryInstancesFromBuffer(std::stringstream& buffer);
     337              :     void ReadSceneryTypesFromBuffer(std::stringstream& buffer);
     338              :     void ReadCollidersFromBuffer(std::stringstream& buffer);
     339              :     void ReadSpawnPointsFromBuffer(std::stringstream& buffer);
     340              :     void ReadWayPointsFromBuffer(std::stringstream& buffer);
     341              : 
     342              :     void AppendPolygonsToFileWriter(std::shared_ptr<IFileWriter>& file_writer);
     343              :     void AppendSectorsToFileWriter(std::shared_ptr<IFileWriter>& file_writer);
     344              :     void AppendSceneryInstancesToFileWriter(std::shared_ptr<IFileWriter>& file_writer);
     345              :     void AppendSceneryTypesToFileWriter(std::shared_ptr<IFileWriter>& file_writer);
     346              :     void AppendCollidersToFileWriter(std::shared_ptr<IFileWriter>& file_writer);
     347              :     void AppendSpawnPointsToFileWriter(std::shared_ptr<IFileWriter>& file_writer);
     348              :     void AppendWayPointsToFileWriter(std::shared_ptr<IFileWriter>& file_writer);
     349              : 
     350              :     void UpdateBoundaries();
     351              :     bool IsPolygonInSector(unsigned short polygon_index,
     352              :                            float sector_x,
     353              :                            float sector_y,
     354              :                            float sector_size);
     355              : 
     356              :     static void SetPolygonVerticesAndPerpendiculars(PMSPolygon& polygon);
     357              : 
     358              :     void FixPolygonIds();
     359              :     void UpdateMinMaxPolygonPositions(const PMSPolygon& polygon, bool should_notify = true);
     360              :     void UpdateMinMaxPolygonPositions();
     361              : 
     362              :     bool are_sectors_generated_{};
     363              : };
     364              : } // namespace Soldank
     365              : 
     366              : #endif
        

Generated by: LCOV version 2.0-1