LCOV - code coverage report
Current view: top level - source/simulation2/components - CCmpMinimap.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 10 114 8.8 %
Date: 2023-01-19 00:18:29 Functions: 5 24 20.8 %

          Line data    Source code
       1             : /* Copyright (C) 2022 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       4             :  * 0 A.D. is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * 0 A.D. is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include "precompiled.h"
      19             : 
      20             : #include "simulation2/system/Component.h"
      21             : #include "ICmpMinimap.h"
      22             : 
      23             : #include "simulation2/components/ICmpPlayerManager.h"
      24             : #include "simulation2/components/ICmpPlayer.h"
      25             : #include "simulation2/components/ICmpOwnership.h"
      26             : #include "simulation2/MessageTypes.h"
      27             : 
      28             : #include "graphics/Color.h"
      29             : 
      30           0 : class CCmpMinimap final : public ICmpMinimap
      31             : {
      32             : public:
      33         116 :     static void ClassInit(CComponentManager& componentManager)
      34             :     {
      35         116 :         componentManager.SubscribeToMessageType(MT_Deserialized);
      36         116 :         componentManager.SubscribeToMessageType(MT_PositionChanged);
      37         116 :         componentManager.SubscribeToMessageType(MT_OwnershipChanged);
      38         116 :         componentManager.SubscribeToMessageType(MT_PlayerColorChanged);
      39         116 :         componentManager.SubscribeToMessageType(MT_MinimapPing);
      40         116 :     }
      41             : 
      42           0 :     DEFAULT_COMPONENT_ALLOCATOR(Minimap)
      43             : 
      44             :     // Template state:
      45             : 
      46             :     bool m_UsePlayerColor;
      47             : 
      48             :     u8 m_R, m_G, m_B; // static template state if m_UsePlayerColor false; dynamic state if true
      49             : 
      50             :     // Dynamic state:
      51             : 
      52             :     bool m_Active;
      53             :     entity_pos_t m_X, m_Z; // cache the latest position for more efficient rendering; only valid when m_Active true
      54             : 
      55             :     // Not serialized (based on renderer timing):
      56             :     // TODO: eventually ping state should be serialized and tied into simulation time, but currently lag causes too many problems
      57             :     double m_PingEndTime;
      58             :     bool m_IsPinging;
      59             : 
      60             :     bool m_HasIcon = false;
      61             :     std::string m_IconPath;
      62             :     float m_IconSize = 16.0f;
      63             : 
      64         116 :     static std::string GetSchema()
      65             :     {
      66             :         return
      67             :             "<element name='Type'>"
      68             :                 "<choice>"
      69             :                     "<value>food</value>"
      70             :                     "<value>wood</value>"
      71             :                     "<value>stone</value>"
      72             :                     "<value>metal</value>"
      73             :                     "<value>structure</value>"
      74             :                     "<value>unit</value>"
      75             :                     "<value>support</value>"
      76             :                     "<value>hero</value>"
      77             :                 "</choice>"
      78             :             "</element>"
      79             :             "<optional>"
      80             :                 "<element name='Color'>"
      81             :                     "<attribute name='r'>"
      82             :                         "<data type='integer'><param name='minInclusive'>0</param><param name='maxInclusive'>255</param></data>"
      83             :                     "</attribute>"
      84             :                     "<attribute name='g'>"
      85             :                         "<data type='integer'><param name='minInclusive'>0</param><param name='maxInclusive'>255</param></data>"
      86             :                     "</attribute>"
      87             :                     "<attribute name='b'>"
      88             :                         "<data type='integer'><param name='minInclusive'>0</param><param name='maxInclusive'>255</param></data>"
      89             :                     "</attribute>"
      90             :                 "</element>"
      91             :             "</optional>"
      92             :             "<optional>"
      93             :                 "<element name='Icon' a:help='Icon texture that should be displayed on a minimap. Filepath relative to art/textures/ui/session/icons/minimap/.'>"
      94             :                     "<attribute name='size'>"
      95             :                         "<data type='float'><param name='minExclusive'>0</param></data>"
      96             :                     "</attribute>"
      97             :                     "<text/>"
      98             :                 "</element>"
      99         116 :             "</optional>";
     100             :     }
     101             : 
     102           0 :     void Init(const CParamNode& paramNode) override
     103             :     {
     104           0 :         m_Active = true;
     105           0 :         m_IsPinging = false;
     106           0 :         m_PingEndTime = 0.0;
     107           0 :         m_HasIcon = false;
     108             : 
     109           0 :         const CParamNode& color = paramNode.GetChild("Color");
     110           0 :         if (color.IsOk())
     111             :         {
     112           0 :             m_UsePlayerColor = false;
     113           0 :             m_R = (u8)color.GetChild("@r").ToInt();
     114           0 :             m_G = (u8)color.GetChild("@g").ToInt();
     115           0 :             m_B = (u8)color.GetChild("@b").ToInt();
     116             :         }
     117             :         else
     118             :         {
     119           0 :             m_UsePlayerColor = true;
     120             :             // Choose a bogus color which will get replaced once we have an owner
     121           0 :             m_R = 255;
     122           0 :             m_G = 0;
     123           0 :             m_B = 255;
     124             :         }
     125             : 
     126           0 :         const CParamNode& iconNode = paramNode.GetChild("Icon");
     127           0 :         if (iconNode.IsOk())
     128             :         {
     129           0 :             const CParamNode& iconSizeNode = iconNode.GetChild("@size");
     130           0 :             if (iconSizeNode.IsOk())
     131             :             {
     132           0 :                 m_HasIcon = true;
     133           0 :                 m_IconPath = "art/textures/ui/session/icons/minimap/" + iconNode.ToString();
     134           0 :                 m_IconSize = iconSizeNode.ToFloat();
     135             :             }
     136             :         }
     137           0 :     }
     138             : 
     139           0 :     void Deinit() override
     140             :     {
     141           0 :     }
     142             : 
     143             :     template<typename S>
     144           0 :     void SerializeCommon(S& serialize)
     145             :     {
     146           0 :         serialize.Bool("active", m_Active);
     147             : 
     148           0 :         if (m_Active)
     149             :         {
     150           0 :             serialize.NumberFixed_Unbounded("x", m_X);
     151           0 :             serialize.NumberFixed_Unbounded("z", m_Z);
     152             :         }
     153           0 :     }
     154             : 
     155           0 :     void Serialize(ISerializer& serialize) override
     156             :     {
     157           0 :         SerializeCommon(serialize);
     158           0 :     }
     159             : 
     160           0 :     void Deserialize(const CParamNode& paramNode, IDeserializer& deserialize) override
     161             :     {
     162           0 :         Init(paramNode);
     163             : 
     164           0 :         SerializeCommon(deserialize);
     165           0 :     }
     166             : 
     167           0 :     void HandleMessage(const CMessage& msg, bool UNUSED(global)) override
     168             :     {
     169           0 :         switch (msg.GetType())
     170             :         {
     171           0 :         case MT_PositionChanged:
     172             :         {
     173           0 :             const CMessagePositionChanged& data = static_cast<const CMessagePositionChanged&> (msg);
     174             : 
     175           0 :             if (data.inWorld)
     176             :             {
     177           0 :                 m_Active = true;
     178           0 :                 m_X = data.x;
     179           0 :                 m_Z = data.z;
     180             :             }
     181             :             else
     182             :             {
     183           0 :                 m_Active = false;
     184             :             }
     185             : 
     186           0 :             break;
     187             :         }
     188           0 :         case MT_Deserialized:
     189             :         case MT_OwnershipChanged:
     190             :         case MT_PlayerColorChanged:
     191             :         {
     192           0 :             UpdateColor();
     193           0 :             break;
     194             :         }
     195           0 :         case MT_MinimapPing:
     196             :         {
     197           0 :             CmpPtr<ICmpOwnership> cmpOwnership(GetSimContext(), GetEntityId());
     198           0 :             if (!cmpOwnership || cmpOwnership->GetOwner() != (player_id_t)GetSimContext().GetCurrentDisplayedPlayer())
     199           0 :                 break;
     200             : 
     201             :             // This depends on the viewing player, so don't alter the synchronized simulation state
     202           0 :             m_IsPinging = true;
     203           0 :             m_PingEndTime = 0.0;
     204             : 
     205           0 :             break;
     206             :         }
     207             :         }
     208           0 :     }
     209             : 
     210           0 :     bool GetRenderData(u8& r, u8& g, u8& b, entity_pos_t& x, entity_pos_t& z) const override
     211             :     {
     212           0 :         if (!m_Active)
     213           0 :             return false;
     214             : 
     215           0 :         r = m_R;
     216           0 :         g = m_G;
     217           0 :         b = m_B;
     218           0 :         x = m_X;
     219           0 :         z = m_Z;
     220           0 :         return true;
     221             :     }
     222             : 
     223           0 :     bool CheckPing(double currentTime, double pingDuration) override
     224             :     {
     225           0 :         if (!m_Active || !m_IsPinging)
     226           0 :             return false;
     227             : 
     228             :         // We're currently pinging
     229           0 :         if (m_PingEndTime == 0.0)
     230           0 :             m_PingEndTime = currentTime + pingDuration;
     231           0 :         else if (currentTime > m_PingEndTime)
     232             :         {
     233           0 :             m_IsPinging = false;
     234           0 :             m_PingEndTime = 0;
     235             :         }
     236             : 
     237           0 :         return m_IsPinging;
     238             :     }
     239             : 
     240           0 :     void UpdateColor() override
     241             :     {
     242           0 :         if (!m_UsePlayerColor)
     243           0 :             return;
     244             : 
     245           0 :         CmpPtr<ICmpOwnership> cmpOwnership(GetEntityHandle());
     246           0 :         if (!cmpOwnership)
     247           0 :             return;
     248             : 
     249           0 :         player_id_t owner = cmpOwnership->GetOwner();
     250           0 :         if (owner == INVALID_PLAYER)
     251           0 :             return;
     252             : 
     253           0 :         CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSystemEntity());
     254           0 :         if (!cmpPlayerManager)
     255           0 :             return;
     256             : 
     257           0 :         CmpPtr<ICmpPlayer> cmpPlayer(GetSimContext(), cmpPlayerManager->GetPlayerByID(owner));
     258           0 :         if (!cmpPlayer)
     259           0 :             return;
     260             : 
     261           0 :         CColor color = cmpPlayer->GetDisplayedColor();
     262           0 :         m_R = (u8) (color.r * 255);
     263           0 :         m_G = (u8) (color.g * 255);
     264           0 :         m_B = (u8) (color.b * 255);
     265             :     }
     266             : 
     267           0 :     bool HasIcon() override
     268             :     {
     269           0 :         return m_HasIcon;
     270             :     }
     271             : 
     272           0 :     std::string GetIconPath() override
     273             :     {
     274           0 :         return m_IconPath;
     275             :     }
     276             : 
     277           0 :     float GetIconSize() override
     278             :     {
     279           0 :         return m_IconSize;
     280             :     }
     281             : };
     282             : 
     283         119 : REGISTER_COMPONENT_TYPE(Minimap)

Generated by: LCOV version 1.13