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)
|