1 /* Copyright (C) 2017 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 #ifndef INCLUDED_MESSAGETYPES
19 #define INCLUDED_MESSAGETYPES
20 
21 #include "simulation2/system/Components.h"
22 #include "simulation2/system/Entity.h"
23 #include "simulation2/system/Message.h"
24 
25 #include "simulation2/helpers/Player.h"
26 #include "simulation2/helpers/Position.h"
27 
28 #include "simulation2/components/ICmpPathfinder.h"
29 
30 #include "maths/Vector3D.h"
31 
32 #include "ps/CStr.h"
33 
34 #define DEFAULT_MESSAGE_IMPL(name) \
35 	virtual int GetType() const { return MT_##name; } \
36 	virtual const char* GetScriptHandlerName() const { return "On" #name; } \
37 	virtual const char* GetScriptGlobalHandlerName() const { return "OnGlobal" #name; } \
38 	virtual JS::Value ToJSVal(const ScriptInterface& scriptInterface) const; \
39 	static CMessage* FromJSVal(const ScriptInterface&, JS::HandleValue val);
40 
41 class SceneCollector;
42 class CFrustum;
43 
44 class CMessageTurnStart : public CMessage
45 {
46 public:
DEFAULT_MESSAGE_IMPL(TurnStart)47 	DEFAULT_MESSAGE_IMPL(TurnStart)
48 
49 	CMessageTurnStart()
50 	{
51 	}
52 };
53 
54 // The update process is split into a number of phases, in an attempt
55 // to cope with dependencies between components. Each phase is implemented
56 // as a separate message. Simulation2.cpp sends them in sequence.
57 
58 /**
59  * Generic per-turn update message, for things that don't care much about ordering.
60  */
61 class CMessageUpdate : public CMessage
62 {
63 public:
DEFAULT_MESSAGE_IMPL(Update)64 	DEFAULT_MESSAGE_IMPL(Update)
65 
66 	CMessageUpdate(fixed turnLength) :
67 		turnLength(turnLength)
68 	{
69 	}
70 
71 	fixed turnLength;
72 };
73 
74 /**
75  * Update phase for formation controller movement (must happen before individual
76  * units move to follow their formation).
77  */
78 class CMessageUpdate_MotionFormation : public CMessage
79 {
80 public:
DEFAULT_MESSAGE_IMPL(Update_MotionFormation)81 	DEFAULT_MESSAGE_IMPL(Update_MotionFormation)
82 
83 	CMessageUpdate_MotionFormation(fixed turnLength) :
84 		turnLength(turnLength)
85 	{
86 	}
87 
88 	fixed turnLength;
89 };
90 
91 /**
92  * Update phase for non-formation-controller unit movement.
93  */
94 class CMessageUpdate_MotionUnit : public CMessage
95 {
96 public:
DEFAULT_MESSAGE_IMPL(Update_MotionUnit)97 	DEFAULT_MESSAGE_IMPL(Update_MotionUnit)
98 
99 	CMessageUpdate_MotionUnit(fixed turnLength) :
100 		turnLength(turnLength)
101 	{
102 	}
103 
104 	fixed turnLength;
105 };
106 
107 /**
108  * Final update phase, after all other updates.
109  */
110 class CMessageUpdate_Final : public CMessage
111 {
112 public:
DEFAULT_MESSAGE_IMPL(Update_Final)113 	DEFAULT_MESSAGE_IMPL(Update_Final)
114 
115 	CMessageUpdate_Final(fixed turnLength) :
116 		turnLength(turnLength)
117 	{
118 	}
119 
120 	fixed turnLength;
121 };
122 
123 /**
124  * Prepare for rendering a new frame (set up model positions etc).
125  */
126 class CMessageInterpolate : public CMessage
127 {
128 public:
DEFAULT_MESSAGE_IMPL(Interpolate)129 	DEFAULT_MESSAGE_IMPL(Interpolate)
130 
131 	CMessageInterpolate(float deltaSimTime, float offset, float deltaRealTime) :
132 		deltaSimTime(deltaSimTime), offset(offset), deltaRealTime(deltaRealTime)
133 	{
134 	}
135 
136 	/// Elapsed simulation time since previous interpolate, in seconds. This is similar to the elapsed real time, except
137 	/// it is scaled by the current simulation rate (and might indeed be zero).
138 	float deltaSimTime;
139 	/// Range [0, 1] (inclusive); fractional time of current frame between previous/next simulation turns.
140 	float offset;
141 	/// Elapsed real time since previous interpolate, in seconds.
142 	float deltaRealTime;
143 };
144 
145 /**
146  * Add renderable objects to the scene collector.
147  * Called after CMessageInterpolate.
148  */
149 class CMessageRenderSubmit : public CMessage
150 {
151 public:
DEFAULT_MESSAGE_IMPL(RenderSubmit)152 	DEFAULT_MESSAGE_IMPL(RenderSubmit)
153 
154 	CMessageRenderSubmit(SceneCollector& collector, const CFrustum& frustum, bool culling) :
155 		collector(collector), frustum(frustum), culling(culling)
156 	{
157 	}
158 
159 	SceneCollector& collector;
160 	const CFrustum& frustum;
161 	bool culling;
162 };
163 
164 /**
165  * Handle progressive loading of resources.
166  * A component that listens to this message must do the following:
167  *  - Increase *msg.total by the non-zero number of loading tasks this component can perform.
168  *  - If *msg.progressed == true, return and do nothing.
169  *  - If you've loaded everything, increase *msg.progress by the value you added to .total
170  *  - Otherwise do some loading, set *msg.progressed = true, and increase *msg.progress by a
171  *    value indicating how much progress you've made in total (0 <= p <= what you added to .total)
172  * In some situations these messages will never be sent - components must ensure they
173  * load all their data themselves before using it in that case.
174  */
175 class CMessageProgressiveLoad : public CMessage
176 {
177 public:
DEFAULT_MESSAGE_IMPL(ProgressiveLoad)178 	DEFAULT_MESSAGE_IMPL(ProgressiveLoad)
179 
180 	CMessageProgressiveLoad(bool* progressed, int* total, int* progress) :
181 		progressed(progressed), total(total), progress(progress)
182 	{
183 	}
184 
185 	bool* progressed;
186 	int* total;
187 	int* progress;
188 };
189 
190 /**
191  * Broadcast after the entire simulation state has been deserialized.
192  * Components should do all their self-contained work in their Deserialize
193  * function when possible. But any reinitialisation that depends on other
194  * components or other entities, that might not be constructed until later
195  * in the deserialization process, may be done in response to this message
196  * instead.
197  */
198 class CMessageDeserialized : public CMessage
199 {
200 public:
DEFAULT_MESSAGE_IMPL(Deserialized)201 	DEFAULT_MESSAGE_IMPL(Deserialized)
202 
203 	CMessageDeserialized()
204 	{
205 	}
206 };
207 
208 
209 /**
210  * This is sent immediately after a new entity's components have all been created
211  * and initialised.
212  */
213 class CMessageCreate : public CMessage
214 {
215 public:
DEFAULT_MESSAGE_IMPL(Create)216 	DEFAULT_MESSAGE_IMPL(Create)
217 
218 	CMessageCreate(entity_id_t entity) :
219 		entity(entity)
220 	{
221 	}
222 
223 	entity_id_t entity;
224 };
225 
226 /**
227  * This is sent immediately before a destroyed entity is flushed and really destroyed.
228  * (That is, after CComponentManager::DestroyComponentsSoon and inside FlushDestroyedComponents).
229  * The entity will still exist at the time this message is sent.
230  * It's possible for this message to be sent multiple times for one entity, but all its components
231  * will have been deleted after the first time.
232  */
233 class CMessageDestroy : public CMessage
234 {
235 public:
DEFAULT_MESSAGE_IMPL(Destroy)236 	DEFAULT_MESSAGE_IMPL(Destroy)
237 
238 	CMessageDestroy(entity_id_t entity) :
239 		entity(entity)
240 	{
241 	}
242 
243 	entity_id_t entity;
244 };
245 
246 class CMessageOwnershipChanged : public CMessage
247 {
248 public:
DEFAULT_MESSAGE_IMPL(OwnershipChanged)249 	DEFAULT_MESSAGE_IMPL(OwnershipChanged)
250 
251 	CMessageOwnershipChanged(entity_id_t entity, player_id_t from, player_id_t to) :
252 		entity(entity), from(from), to(to)
253 	{
254 	}
255 
256 	entity_id_t entity;
257 	player_id_t from;
258 	player_id_t to;
259 };
260 
261 /**
262  * Sent by CCmpPosition whenever anything has changed that will affect the
263  * return value of GetPosition2D() or GetRotation().Y
264  *
265  * If @c inWorld is false, then the other fields are invalid and meaningless.
266  * Otherwise they represent the current position.
267  */
268 class CMessagePositionChanged : public CMessage
269 {
270 public:
DEFAULT_MESSAGE_IMPL(PositionChanged)271 	DEFAULT_MESSAGE_IMPL(PositionChanged)
272 
273 	CMessagePositionChanged(entity_id_t entity, bool inWorld, entity_pos_t x, entity_pos_t z, entity_angle_t a) :
274 		entity(entity), inWorld(inWorld), x(x), z(z), a(a)
275 	{
276 	}
277 
278 	entity_id_t entity;
279 	bool inWorld;
280 	entity_pos_t x, z;
281 	entity_angle_t a;
282 };
283 
284 /**
285  * Sent by CCmpPosition whenever anything has changed that will affect the
286  * return value of GetInterpolatedTransform()
287  */
288 class CMessageInterpolatedPositionChanged : public CMessage
289 {
290 public:
DEFAULT_MESSAGE_IMPL(InterpolatedPositionChanged)291 	DEFAULT_MESSAGE_IMPL(InterpolatedPositionChanged)
292 
293 	CMessageInterpolatedPositionChanged(entity_id_t entity, bool inWorld, const CVector3D& pos0, const CVector3D& pos1) :
294 		entity(entity), inWorld(inWorld), pos0(pos0), pos1(pos1)
295 	{
296 	}
297 
298 	entity_id_t entity;
299 	bool inWorld;
300 	CVector3D pos0;
301 	CVector3D pos1;
302 };
303 
304 /*Sent whenever the territory type (neutral,own,enemy) differs from the former type*/
305 class CMessageTerritoryPositionChanged : public CMessage
306 {
307 public:
DEFAULT_MESSAGE_IMPL(TerritoryPositionChanged)308 	DEFAULT_MESSAGE_IMPL(TerritoryPositionChanged)
309 
310 	CMessageTerritoryPositionChanged(entity_id_t entity, player_id_t newTerritory) :
311 		entity(entity), newTerritory(newTerritory)
312 	{
313 	}
314 
315 	entity_id_t entity;
316 	player_id_t newTerritory;
317 };
318 
319 /**
320  * Sent by CCmpUnitMotion during Update, whenever the motion status has changed
321  * since the previous update.
322  */
323 class CMessageMotionChanged : public CMessage
324 {
325 public:
DEFAULT_MESSAGE_IMPL(MotionChanged)326 	DEFAULT_MESSAGE_IMPL(MotionChanged)
327 
328 	CMessageMotionChanged(bool starting, bool error) :
329 		starting(starting), error(error)
330 	{
331 	}
332 
333 	bool starting; // whether this is a start or end of movement
334 	bool error; // whether we failed to start moving (couldn't find any path)
335 };
336 
337 /**
338  * Sent when water height has been changed.
339  */
340 class CMessageWaterChanged : public CMessage
341 {
342 public:
DEFAULT_MESSAGE_IMPL(WaterChanged)343 	DEFAULT_MESSAGE_IMPL(WaterChanged)
344 
345 	CMessageWaterChanged()
346 	{
347 	}
348 };
349 
350 /**
351  * Sent when terrain (texture or elevation) has been changed.
352  */
353 class CMessageTerrainChanged : public CMessage
354 {
355 public:
DEFAULT_MESSAGE_IMPL(TerrainChanged)356 	DEFAULT_MESSAGE_IMPL(TerrainChanged)
357 
358 	CMessageTerrainChanged(int32_t i0, int32_t j0, int32_t i1, int32_t j1) :
359 		i0(i0), j0(j0), i1(i1), j1(j1)
360 	{
361 	}
362 
363 	int32_t i0, j0, i1, j1; // inclusive lower bound, exclusive upper bound, in tiles
364 };
365 
366 /**
367  * Sent, at most once per turn, when the visibility of an entity changed
368  */
369 class CMessageVisibilityChanged : public CMessage
370 {
371 public:
DEFAULT_MESSAGE_IMPL(VisibilityChanged)372 	DEFAULT_MESSAGE_IMPL(VisibilityChanged)
373 
374 	CMessageVisibilityChanged(player_id_t player, entity_id_t ent, int oldVisibility, int newVisibility) :
375 		player(player), ent(ent), oldVisibility(oldVisibility), newVisibility(newVisibility)
376 	{
377 	}
378 
379 	player_id_t player;
380 	entity_id_t ent;
381 	int oldVisibility;
382 	int newVisibility;
383 };
384 
385 /**
386  * Sent when ObstructionManager's view of the shape of the world has changed
387  * (changing the TILE_OUTOFBOUNDS tiles returned by Rasterise).
388  */
389 class CMessageObstructionMapShapeChanged : public CMessage
390 {
391 public:
DEFAULT_MESSAGE_IMPL(ObstructionMapShapeChanged)392 	DEFAULT_MESSAGE_IMPL(ObstructionMapShapeChanged)
393 
394 	CMessageObstructionMapShapeChanged()
395 	{
396 	}
397 };
398 
399 /**
400  * Sent when territory assignments have changed.
401  */
402 class CMessageTerritoriesChanged : public CMessage
403 {
404 public:
DEFAULT_MESSAGE_IMPL(TerritoriesChanged)405 	DEFAULT_MESSAGE_IMPL(TerritoriesChanged)
406 
407 	CMessageTerritoriesChanged()
408 	{
409 	}
410 };
411 
412 /**
413  * Sent by CCmpRangeManager at most once per turn, when an active range query
414  * has had matching units enter/leave the range since the last RangeUpdate.
415  */
416 class CMessageRangeUpdate : public CMessage
417 {
418 public:
419 	DEFAULT_MESSAGE_IMPL(RangeUpdate)
420 
421 
422 
423 	u32 tag;
424 	std::vector<entity_id_t> added;
425 	std::vector<entity_id_t> removed;
426 
427 	// CCmpRangeManager wants to store a vector of messages and wants to
428 	// swap vectors instead of copying (to save on memory allocations),
429 	// so add some constructors for it:
430 
431 	// don't init tag in empty ctor
CMessageRangeUpdate()432 	CMessageRangeUpdate()
433 	{
434 	}
CMessageRangeUpdate(u32 tag)435 	CMessageRangeUpdate(u32 tag) : tag(tag)
436 	{
437 	}
CMessageRangeUpdate(u32 tag,const std::vector<entity_id_t> & added,const std::vector<entity_id_t> & removed)438 	CMessageRangeUpdate(u32 tag, const std::vector<entity_id_t>& added, const std::vector<entity_id_t>& removed)
439 		: tag(tag), added(added), removed(removed)
440 	{
441 	}
CMessageRangeUpdate(const CMessageRangeUpdate & other)442 	CMessageRangeUpdate(const CMessageRangeUpdate& other)
443 		: CMessage(), tag(other.tag), added(other.added), removed(other.removed)
444 	{
445 	}
446 	CMessageRangeUpdate& operator=(const CMessageRangeUpdate& other)
447 	{
448 		tag = other.tag;
449 		added = other.added;
450 		removed = other.removed;
451 		return *this;
452 	}
453 };
454 
455 /**
456  * Sent by CCmpPathfinder after async path requests.
457  */
458 class CMessagePathResult : public CMessage
459 {
460 public:
DEFAULT_MESSAGE_IMPL(PathResult)461 	DEFAULT_MESSAGE_IMPL(PathResult)
462 
463 	CMessagePathResult(u32 ticket, const WaypointPath& path) :
464 		ticket(ticket), path(path)
465 	{
466 	}
467 
468 	u32 ticket;
469 	WaypointPath path;
470 };
471 
472 /**
473  * Sent by aura manager when a value of a certain entity's component is changed
474  */
475 class CMessageValueModification : public CMessage
476 {
477 public:
DEFAULT_MESSAGE_IMPL(ValueModification)478 	DEFAULT_MESSAGE_IMPL(ValueModification)
479 
480 	CMessageValueModification(const std::vector<entity_id_t>& entities, std::wstring component, const std::vector<std::wstring>& valueNames) :
481 		entities(entities),
482 		component(component),
483 		valueNames(valueNames)
484 	{
485 	}
486 
487 	std::vector<entity_id_t> entities;
488 	std::wstring component;
489 	std::vector<std::wstring> valueNames;
490 };
491 
492 /**
493  * Sent by atlas if the playercolor has been changed.
494  */
495 class CMessagePlayerColorChanged : public CMessage
496 {
497 public:
DEFAULT_MESSAGE_IMPL(PlayerColorChanged)498 	DEFAULT_MESSAGE_IMPL(PlayerColorChanged)
499 
500 	CMessagePlayerColorChanged(player_id_t player) :
501 		player(player)
502 	{
503 	}
504 
505 	player_id_t player;
506 };
507 
508 /**
509  * Sent by aura and tech managers when a value of a certain template's component is changed
510  */
511 class CMessageTemplateModification : public CMessage
512 {
513 public:
DEFAULT_MESSAGE_IMPL(TemplateModification)514 	DEFAULT_MESSAGE_IMPL(TemplateModification)
515 
516 	CMessageTemplateModification(player_id_t player, std::wstring component, const std::vector<std::wstring>& valueNames) :
517 		player(player),
518 		component(component),
519 		valueNames(valueNames)
520 	{
521 	}
522 
523 	player_id_t player;
524 	std::wstring component;
525 	std::vector<std::wstring> valueNames;
526 };
527 
528 /**
529  * Sent by CCmpVision when an entity's vision range changes.
530  */
531 class CMessageVisionRangeChanged : public CMessage
532 {
533 public:
DEFAULT_MESSAGE_IMPL(VisionRangeChanged)534 	DEFAULT_MESSAGE_IMPL(VisionRangeChanged)
535 
536 	CMessageVisionRangeChanged(entity_id_t entity, entity_pos_t oldRange, entity_pos_t newRange) :
537 		entity(entity), oldRange(oldRange), newRange(newRange)
538 	{
539 	}
540 
541 	entity_id_t entity;
542 	entity_pos_t oldRange;
543 	entity_pos_t newRange;
544 };
545 
546 /**
547  * Sent by CCmpVision when an entity's vision sharing changes.
548  */
549 class CMessageVisionSharingChanged : public CMessage
550 {
551 public:
DEFAULT_MESSAGE_IMPL(VisionSharingChanged)552 	DEFAULT_MESSAGE_IMPL(VisionSharingChanged)
553 
554 	CMessageVisionSharingChanged(entity_id_t entity, player_id_t player, bool add) :
555 		entity(entity), player(player), add(add)
556 	{
557 	}
558 
559 	entity_id_t entity;
560 	player_id_t player;
561 	bool add;
562 };
563 
564 /**
565  * Sent when an entity pings the minimap
566  */
567 class CMessageMinimapPing : public CMessage
568 {
569 public:
DEFAULT_MESSAGE_IMPL(MinimapPing)570 	DEFAULT_MESSAGE_IMPL(MinimapPing)
571 
572 	CMessageMinimapPing()
573 	{
574 	}
575 };
576 
577 /**
578 * Cinematics events
579 */
580 
581 class CMessageCinemaPathEnded : public CMessage
582 {
583 public:
DEFAULT_MESSAGE_IMPL(CinemaPathEnded)584 	DEFAULT_MESSAGE_IMPL(CinemaPathEnded)
585 
586 	CMessageCinemaPathEnded(CStrW name) :
587 	name(name)
588 	{
589 	}
590 
591 	CStrW name;
592 };
593 
594 class CMessageCinemaQueueEnded : public CMessage
595 {
596 public:
597 	DEFAULT_MESSAGE_IMPL(CinemaQueueEnded)
598 };
599 
600 #endif // INCLUDED_MESSAGETYPES
601