1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2 
3 #ifndef EVENT_HANDLER_H
4 #define EVENT_HANDLER_H
5 
6 #include <string>
7 #include <vector>
8 #include <map>
9 
10 #include "System/EventClient.h"
11 #include "Sim/Units/Unit.h"
12 #include "Sim/Features/Feature.h"
13 #include "Sim/Projectiles/Projectile.h"
14 
15 class CWeapon;
16 struct Command;
17 struct BuildInfo;
18 
19 
20 class CEventHandler
21 {
22 	public:
23 		CEventHandler();
24 		~CEventHandler();
25 
26 		void AddClient(CEventClient* ec);
27 		void RemoveClient(CEventClient* ec);
28 
29 		bool InsertEvent(CEventClient* ec, const std::string& ciName);
30 		bool RemoveEvent(CEventClient* ec, const std::string& ciName);
31 
32 		void GetEventList(std::vector<std::string>& list) const;
33 
34 		bool IsKnown(const std::string& ciName) const;
35 		bool IsManaged(const std::string& ciName) const;
36 		bool IsUnsynced(const std::string& ciName) const;
37 		bool IsController(const std::string& ciName) const;
38 
39 	public: // EventBatchHandler
40 		void UpdateUnits();
41 		void UpdateDrawUnits();
42 		void DeleteSyncedUnits();
43 		void UpdateFeatures();
44 		void UpdateDrawFeatures();
45 		void DeleteSyncedFeatures();
46 		void UpdateProjectiles();
47 		void UpdateDrawProjectiles();
48 		void DeleteSyncedProjectiles();
49 		void UpdateObjects();
50 		void DeleteSyncedObjects();
51 	public:
52 		/**
53 		 * @name Synced_events
54 		 * @{
55 		 */
56 		void Load(IArchive* archive);
57 
58 		void GamePreload();
59 		void GameStart();
60 		void GameOver(const std::vector<unsigned char>& winningAllyTeams);
61 		void GamePaused(int playerID, bool paused);
62 		void GameFrame(int gameFrame);
63 		void GameID(const unsigned char* gameID, unsigned int numBytes);
64 
65 		void TeamDied(int teamID);
66 		void TeamChanged(int teamID);
67 		void PlayerChanged(int playerID);
68 		void PlayerAdded(int playerID);
69 		void PlayerRemoved(int playerID, int reason);
70 
71 		void UnitCreated(const CUnit* unit, const CUnit* builder);
72 		void UnitFinished(const CUnit* unit);
73 		void UnitFromFactory(const CUnit* unit, const CUnit* factory,
74 		                     bool userOrders);
75 		void UnitDestroyed(const CUnit* unit, const CUnit* attacker);
76 		void UnitTaken(const CUnit* unit, int oldTeam, int newTeam);
77 		void UnitGiven(const CUnit* unit, int oldTeam, int newTeam);
78 
79 		//FIXME no events
80 		void RenderUnitCreated(const CUnit* unit, int cloaked);
81 		void RenderUnitDestroyed(const CUnit* unit);
82 		void RenderUnitCloakChanged(const CUnit* unit, int cloaked);
83 		void RenderUnitLOSChanged(const CUnit* unit, int allyTeam, int newStatus);
84 		void RenderUnitMoved(const CUnit* unit, const float3& newpos);
85 		void RenderFeatureCreated(const CFeature* feature);
86 		void RenderFeatureDestroyed(const CFeature* feature);
87 		void RenderFeatureMoved(const CFeature* feature, const float3& oldpos, const float3& newpos);
88 		void RenderProjectileCreated(const CProjectile* proj);
89 		void RenderProjectileDestroyed(const CProjectile* proj);
90 		void UnsyncedProjectileCreated(const CProjectile* proj);
91 		void UnsyncedProjectileDestroyed(const CProjectile* proj);
92 
93 		void UnitIdle(const CUnit* unit);
94 		void UnitCommand(const CUnit* unit, const Command& command);
95 		void UnitCmdDone(const CUnit* unit, const Command& command);
96 		void UnitDamaged(
97 			const CUnit* unit,
98 			const CUnit* attacker,
99 			float damage,
100 			int weaponDefID,
101 			int projectileID,
102 			bool paralyzer);
103 		void UnitExperience(const CUnit* unit, float oldExperience);
104 		void UnitHarvestStorageFull(const CUnit* unit);
105 
106 		void UnitSeismicPing(const CUnit* unit, int allyTeam,
107 		                     const float3& pos, float strength);
108 		void UnitEnteredRadar(const CUnit* unit, int allyTeam);
109 		void UnitEnteredLos(const CUnit* unit, int allyTeam);
110 		void UnitLeftRadar(const CUnit* unit, int allyTeam);
111 		void UnitLeftLos(const CUnit* unit, int allyTeam);
112 
113 		void UnitEnteredWater(const CUnit* unit);
114 		void UnitEnteredAir(const CUnit* unit);
115 		void UnitLeftWater(const CUnit* unit);
116 		void UnitLeftAir(const CUnit* unit);
117 
118 		void UnitLoaded(const CUnit* unit, const CUnit* transport);
119 		void UnitUnloaded(const CUnit* unit, const CUnit* transport);
120 
121 		void UnitCloaked(const CUnit* unit);
122 		void UnitDecloaked(const CUnit* unit);
123 
124 		void UnitUnitCollision(const CUnit* collider, const CUnit* collidee);
125 		void UnitFeatureCollision(const CUnit* collider, const CFeature* collidee);
126 		void UnitMoved(const CUnit* unit);
127 		void UnitMoveFailed(const CUnit* unit);
128 
129 		void FeatureCreated(const CFeature* feature);
130 		void FeatureDestroyed(const CFeature* feature);
131 		void FeatureDamaged(
132 			const CFeature* feature,
133 			const CUnit* attacker,
134 			float damage,
135 			int weaponDefID,
136 			int projectileID);
137 		void FeatureMoved(const CFeature* feature, const float3& oldpos);
138 
139 		void ProjectileCreated(const CProjectile* proj, int allyTeam);
140 		void ProjectileDestroyed(const CProjectile* proj, int allyTeam);
141 
142 		bool Explosion(int weaponDefID, int projectileID, const float3& pos, const CUnit* owner);
143 
144 		void StockpileChanged(const CUnit* unit,
145 		                      const CWeapon* weapon, int oldCount);
146 
147 		bool CommandFallback(const CUnit* unit, const Command& cmd);
148 		bool AllowCommand(const CUnit* unit, const Command& cmd, bool fromSynced);
149 
150 		bool AllowUnitCreation(const UnitDef* unitDef, const CUnit* builder, const BuildInfo* buildInfo);
151 		bool AllowUnitTransfer(const CUnit* unit, int newTeam, bool capture);
152 		bool AllowUnitBuildStep(const CUnit* builder, const CUnit* unit, float part);
153 		bool AllowFeatureCreation(const FeatureDef* featureDef, int allyTeamID, const float3& pos);
154 		bool AllowFeatureBuildStep(const CUnit* builder, const CFeature* feature, float part);
155 		bool AllowResourceLevel(int teamID, const string& type, float level);
156 		bool AllowResourceTransfer(int oldTeam, int newTeam, const string& type, float amount);
157 		bool AllowDirectUnitControl(int playerID, const CUnit* unit);
158 		bool AllowBuilderHoldFire(const CUnit* unit, int action);
159 		bool AllowStartPosition(int playerID, unsigned char readyState, const float3& clampedPos, const float3& rawPickPos);
160 
161 		bool TerraformComplete(const CUnit* unit, const CUnit* build);
162 		bool MoveCtrlNotify(const CUnit* unit, int data);
163 
164 		int AllowWeaponTargetCheck(unsigned int attackerID, unsigned int attackerWeaponNum, unsigned int attackerWeaponDefID);
165 		bool AllowWeaponTarget(
166 			unsigned int attackerID,
167 			unsigned int targetID,
168 			unsigned int attackerWeaponNum,
169 			unsigned int attackerWeaponDefID,
170 			float* targetPriority
171 		);
172 		bool AllowWeaponInterceptTarget(const CUnit* interceptorUnit, const CWeapon* interceptorWeapon, const CProjectile* interceptorTarget);
173 
174 		bool UnitPreDamaged(
175 			const CUnit* unit,
176 			const CUnit* attacker,
177 			float damage,
178 			int weaponDefID,
179 			int projectileID,
180 			bool paralyzer,
181 			float* newDamage,
182 			float* impulseMult);
183 
184 		bool FeaturePreDamaged(
185 			const CFeature* feature,
186 			const CUnit* attacker,
187 			float damage,
188 			int weaponDefID,
189 			int projectileID,
190 			float* newDamage,
191 			float* impulseMult);
192 
193 		bool ShieldPreDamaged(const CProjectile*, const CWeapon*, const CUnit*, bool);
194 
195 		bool SyncedActionFallback(const string& line, int playerID);
196 		/// @}
197 
198 	public:
199 		/**
200 		 * @name Unsynced_events
201 		 * @{
202 		 */
203 		void Save(zipFile archive);
204 
205 		void UnsyncedHeightMapUpdate(const SRectangle& rect);
206 		void Update();
207 
208 		bool KeyPress(int key, bool isRepeat);
209 		bool KeyRelease(int key);
210 		bool TextInput(const std::string& utf8);
211 		bool MouseMove(int x, int y, int dx, int dy, int button);
212 		bool MousePress(int x, int y, int button);
213 		void MouseRelease(int x, int y, int button);
214 		bool MouseWheel(bool up, float value);
215 		bool JoystickEvent(const std::string& event, int val1, int val2);
216 		bool IsAbove(int x, int y);
217 
218 		std::string GetTooltip(int x, int y);
219 
220 		bool DefaultCommand(const CUnit* unit, const CFeature* feature, int& cmd);
221 
222 		bool CommandNotify(const Command& cmd);
223 
224 		bool AddConsoleLine(const std::string& msg, const std::string& section, int level);
225 
226 		void LastMessagePosition(const float3& pos);
227 
228 		bool GroupChanged(int groupID);
229 
230 		bool GameSetup(const std::string& state, bool& ready,
231 		               const map<int, std::string>& playerStates);
232 
233 		std::string WorldTooltip(const CUnit* unit,
234 		                         const CFeature* feature,
235 		                         const float3* groundPos);
236 
237 		bool MapDrawCmd(int playerID, int type,
238 		                const float3* pos0,
239 		                const float3* pos1,
240 		                const std::string* label);
241 
242 		void SunChanged(const float3& sunDir);
243 
244 		void ViewResize();
245 
246 		void DrawGenesis();
247 		void DrawWorld();
248 		void DrawWorldPreUnit();
249 		void DrawWorldShadow();
250 		void DrawWorldReflection();
251 		void DrawWorldRefraction();
252 		void DrawScreenEffects();
253 		void DrawScreen();
254 		void DrawInMiniMap();
255 		void DrawInMiniMapBackground();
256 
257 		bool DrawUnit(const CUnit* unit);
258 		bool DrawFeature(const CFeature* feature);
259 		bool DrawShield(const CUnit* unit, const CWeapon* weapon);
260 		bool DrawProjectile(const CProjectile* projectile);
261 
262 		/// @brief this UNSYNCED event is generated every GameServer::gameProgressFrameInterval
263 		/// it skips network queuing and caching and can be used to calculate the current catchup
264 		/// percentage when reconnecting to a running game
265 		void GameProgress(int gameFrame);
266 
267 		void CollectGarbage();
268 		void DbgTimingInfo(DbgTimingInfoType type, const spring_time start, const spring_time end);
269 		/// @}
270 
271 		//FIXME no real event
272 		void LoadedModelRequested();
273 
274 	private:
275 		typedef vector<CEventClient*> EventClientList;
276 
277 		enum EventPropertyBits {
278 			MANAGED_BIT  = (1 << 0), // managed by eventHandler
279 			UNSYNCED_BIT = (1 << 1), // delivers unsynced information
280 			CONTROL_BIT  = (1 << 2)  // controls synced information
281 		};
282 
283 		class EventInfo {
284 			public:
EventInfo()285 				EventInfo() : list(NULL), propBits(0) {}
EventInfo(const std::string & _name,EventClientList * _list,int _bits)286 				EventInfo(const std::string& _name, EventClientList* _list, int _bits)
287 				: name(_name), list(_list), propBits(_bits) {}
~EventInfo()288 				~EventInfo() {}
289 
GetName()290 				inline const std::string& GetName() const { return name; }
GetList()291 				inline EventClientList* GetList() const { return list; }
GetPropBits()292 				inline int GetPropBits() const { return propBits; }
HasPropBit(int bit)293 				inline bool HasPropBit(int bit) const { return propBits & bit; }
294 
295 			private:
296 				std::string name;
297 				EventClientList* list;
298 				int propBits;
299 		};
300 
301 		typedef map<std::string, EventInfo> EventMap;
302 
303 	private:
304 		void SetupEvent(const std::string& ciName,
305 		                EventClientList* list, int props);
306 		void ListInsert(EventClientList& ciList, CEventClient* ec);
307 		void ListRemove(EventClientList& ciList, CEventClient* ec);
308 
309 	private:
310 		CEventClient* mouseOwner;
311 
312 	private:
313 		EventMap eventMap;
314 
315 		EventClientList handles;
316 
317 	#define SETUP_EVENT(name, props) EventClientList list ## name;
318 	#define SETUP_UNMANAGED_EVENT(name, props)
319 		#include "Events.def"
320 	#undef SETUP_EVENT
321 	#undef SETUP_UNMANAGED_EVENT
322 };
323 
324 
325 extern CEventHandler eventHandler;
326 
327 
328 /******************************************************************************/
329 /******************************************************************************/
330 //
331 // Inlined call-in loops
332 //
333 
334 #define ITERATE_EVENTCLIENTLIST(name, ...) \
335 	for (int i = 0; i < list##name.size(); ) { \
336 		CEventClient* ec = list##name[i]; \
337 		ec->name(__VA_ARGS__); \
338 		if (i < list##name.size() && ec == list##name[i]) \
339 			++i; /* the call-in may remove itself from the list */ \
340 	}
341 
342 #define ITERATE_ALLYTEAM_EVENTCLIENTLIST(name, allyTeam, ...) \
343 	for (int i = 0; i < list##name.size(); ) { \
344 		CEventClient* ec = list##name[i]; \
345 		if (ec->CanReadAllyTeam(allyTeam)) { \
346 			ec->name(__VA_ARGS__); \
347 		} \
348 		if (i < list##name.size() && ec == list##name[i]) \
349 			++i; /* the call-in may remove itself from the list */ \
350 	}
351 
352 #define ITERATE_UNIT_ALLYTEAM_EVENTCLIENTLIST(name, unit, ...) \
353 	const auto unitAllyTeam = unit->allyteam; \
354 	for (int i = 0; i < list##name.size(); ) { \
355 		CEventClient* ec = list##name[i]; \
356 		if (ec->CanReadAllyTeam(unitAllyTeam)) { \
357 			ec->name(unit, __VA_ARGS__); \
358 		} \
359 		if (i < list##name.size() && ec == list##name[i]) \
360 			++i; /* the call-in may remove itself from the list */ \
361 	}
362 
UnitCreated(const CUnit * unit,const CUnit * builder)363 inline void CEventHandler::UnitCreated(const CUnit* unit, const CUnit* builder)
364 {
365 	ITERATE_UNIT_ALLYTEAM_EVENTCLIENTLIST(UnitCreated, unit, builder)
366 }
367 
368 
UnitDestroyed(const CUnit * unit,const CUnit * attacker)369 inline void CEventHandler::UnitDestroyed(const CUnit* unit,
370                                              const CUnit* attacker)
371 {
372 	ITERATE_UNIT_ALLYTEAM_EVENTCLIENTLIST(UnitDestroyed, unit, attacker)
373 }
374 
375 #define UNIT_CALLIN_NO_PARAM(name)                                 \
376 	inline void CEventHandler:: name (const CUnit* unit)           \
377 	{                                                              \
378 		const auto unitAllyTeam = unit->allyteam; \
379 		for (int i = 0; i < list##name.size(); ) { \
380 			CEventClient* ec = list##name[i]; \
381 			if (ec->CanReadAllyTeam(unitAllyTeam)) { \
382 				ec->name(unit); \
383 			} \
384 			if (i < list##name.size() && ec == list##name[i]) \
385 				++i; /* the call-in may remove itself from the list */ \
386 		} \
387 	}
388 
389 UNIT_CALLIN_NO_PARAM(UnitFinished)
UNIT_CALLIN_NO_PARAM(UnitIdle)390 UNIT_CALLIN_NO_PARAM(UnitIdle)
391 UNIT_CALLIN_NO_PARAM(UnitMoveFailed)
392 UNIT_CALLIN_NO_PARAM(UnitEnteredWater)
393 UNIT_CALLIN_NO_PARAM(UnitEnteredAir)
394 UNIT_CALLIN_NO_PARAM(UnitLeftWater)
395 UNIT_CALLIN_NO_PARAM(UnitLeftAir)
396 UNIT_CALLIN_NO_PARAM(UnitMoved)
397 
398 #define UNIT_CALLIN_INT_PARAMS(name)                                       \
399 	inline void CEventHandler:: Unit ## name (const CUnit* unit, int p1, int p2)   \
400 	{                                                                     \
401 		ITERATE_UNIT_ALLYTEAM_EVENTCLIENTLIST(Unit ## name, unit, p1, p2) \
402 	}
403 
404 UNIT_CALLIN_INT_PARAMS(Taken)
405 UNIT_CALLIN_INT_PARAMS(Given)
406 
407 
408 #define UNIT_CALLIN_LOS_PARAM(name)                                        \
409 	inline void CEventHandler:: Unit ## name (const CUnit* unit, int at)   \
410 	{                                                                      \
411 		ITERATE_ALLYTEAM_EVENTCLIENTLIST(Unit ## name, at, unit, at) \
412 	}
413 
414 UNIT_CALLIN_LOS_PARAM(EnteredRadar)
415 UNIT_CALLIN_LOS_PARAM(EnteredLos)
416 UNIT_CALLIN_LOS_PARAM(LeftRadar)
417 UNIT_CALLIN_LOS_PARAM(LeftLos)
418 
419 
420 
421 inline void CEventHandler::UnitFromFactory(const CUnit* unit,
422                                                const CUnit* factory,
423                                                bool userOrders)
424 {
425 	ITERATE_UNIT_ALLYTEAM_EVENTCLIENTLIST(UnitFromFactory, unit, factory, userOrders)
426 }
427 
428 
429 UNIT_CALLIN_NO_PARAM(UnitCloaked)
UNIT_CALLIN_NO_PARAM(UnitDecloaked)430 UNIT_CALLIN_NO_PARAM(UnitDecloaked)
431 
432 
433 inline void CEventHandler::UnitUnitCollision(const CUnit* collider, const CUnit* collidee)
434 {
435 	ITERATE_EVENTCLIENTLIST(UnitUnitCollision, collider, collidee)
436 }
437 
UnitFeatureCollision(const CUnit * collider,const CFeature * collidee)438 inline void CEventHandler::UnitFeatureCollision(const CUnit* collider, const CFeature* collidee)
439 {
440 	ITERATE_EVENTCLIENTLIST(UnitFeatureCollision, collider, collidee)
441 }
442 
443 
444 
UnitCommand(const CUnit * unit,const Command & command)445 inline void CEventHandler::UnitCommand(const CUnit* unit,
446                                            const Command& command)
447 {
448 	ITERATE_UNIT_ALLYTEAM_EVENTCLIENTLIST(UnitCommand, unit, command)
449 }
450 
451 
452 
UnitCmdDone(const CUnit * unit,const Command & command)453 inline void CEventHandler::UnitCmdDone(const CUnit* unit,
454                                            const Command& command)
455 {
456 	ITERATE_UNIT_ALLYTEAM_EVENTCLIENTLIST(UnitCmdDone, unit, command)
457 }
458 
459 
UnitDamaged(const CUnit * unit,const CUnit * attacker,float damage,int weaponDefID,int projectileID,bool paralyzer)460 inline void CEventHandler::UnitDamaged(
461 	const CUnit* unit,
462 	const CUnit* attacker,
463 	float damage,
464 	int weaponDefID,
465 	int projectileID,
466 	bool paralyzer)
467 {
468 	ITERATE_UNIT_ALLYTEAM_EVENTCLIENTLIST(UnitDamaged, unit, attacker, damage, weaponDefID, projectileID, paralyzer)
469 }
470 
471 
UnitExperience(const CUnit * unit,float oldExperience)472 inline void CEventHandler::UnitExperience(const CUnit* unit,
473                                               float oldExperience)
474 {
475 	ITERATE_UNIT_ALLYTEAM_EVENTCLIENTLIST(UnitExperience, unit, oldExperience)
476 }
477 
478 
UnitSeismicPing(const CUnit * unit,int allyTeam,const float3 & pos,float strength)479 inline void  CEventHandler::UnitSeismicPing(const CUnit* unit,
480                                                 int allyTeam,
481                                                 const float3& pos,
482                                                 float strength)
483 {
484 	ITERATE_UNIT_ALLYTEAM_EVENTCLIENTLIST(UnitSeismicPing, unit, allyTeam, pos, strength)
485 }
486 
487 
UnitLoaded(const CUnit * unit,const CUnit * transport)488 inline void CEventHandler::UnitLoaded(const CUnit* unit,
489                                           const CUnit* transport)
490 {
491 	const int count = listUnitLoaded.size();
492 	for (int i = 0; i < count; i++) {
493 		CEventClient* ec = listUnitLoaded[i];
494 		const int ecAllyTeam = ec->GetReadAllyTeam();
495 		if (ec->GetFullRead() ||
496 		    (ecAllyTeam == unit->allyteam) ||
497 		    (ecAllyTeam == transport->allyteam)) {
498 			ec->UnitLoaded(unit, transport);
499 		}
500 	}
501 }
502 
503 
UnitUnloaded(const CUnit * unit,const CUnit * transport)504 inline void CEventHandler::UnitUnloaded(const CUnit* unit,
505                                             const CUnit* transport)
506 {
507 	const int count = listUnitUnloaded.size();
508 	for (int i = 0; i < count; i++) {
509 		CEventClient* ec = listUnitUnloaded[i];
510 		const int ecAllyTeam = ec->GetReadAllyTeam();
511 		if (ec->GetFullRead() ||
512 		    (ecAllyTeam == unit->allyteam) ||
513 		    (ecAllyTeam == transport->allyteam)) {
514 			ec->UnitUnloaded(unit, transport);
515 		}
516 	}
517 }
518 
FeatureCreated(const CFeature * feature)519 inline void CEventHandler::FeatureCreated(const CFeature* feature)
520 {
521 	const int featureAllyTeam = feature->allyteam;
522 	const int count = listFeatureCreated.size();
523 	for (int i = 0; i < count; i++) {
524 		CEventClient* ec = listFeatureCreated[i];
525 		if ((featureAllyTeam < 0) || ec->CanReadAllyTeam(featureAllyTeam)) {
526 			ec->FeatureCreated(feature);
527 		}
528 	}
529 }
530 
FeatureDestroyed(const CFeature * feature)531 inline void CEventHandler::FeatureDestroyed(const CFeature* feature)
532 {
533 	const int featureAllyTeam = feature->allyteam;
534 	const int count = listFeatureDestroyed.size();
535 	for (int i = 0; i < count; i++) {
536 		CEventClient* ec = listFeatureDestroyed[i];
537 		if ((featureAllyTeam < 0) || ec->CanReadAllyTeam(featureAllyTeam)) {
538 			ec->FeatureDestroyed(feature);
539 		}
540 	}
541 }
542 
FeatureDamaged(const CFeature * feature,const CUnit * attacker,float damage,int weaponDefID,int projectileID)543 inline void CEventHandler::FeatureDamaged(
544 	const CFeature* feature,
545 	const CUnit* attacker,
546 	float damage,
547 	int weaponDefID,
548 	int projectileID)
549 {
550 	const int featureAllyTeam = feature->allyteam;
551 	const int count = listFeatureDamaged.size();
552 
553 	for (int i = 0; i < count; i++) {
554 		CEventClient* ec = listFeatureDamaged[i];
555 		if (featureAllyTeam < 0 || ec->CanReadAllyTeam(featureAllyTeam)) {
556 			ec->FeatureDamaged(feature, attacker, damage, weaponDefID, projectileID);
557 		}
558 	}
559 }
560 
FeatureMoved(const CFeature * feature,const float3 & oldpos)561 inline void CEventHandler::FeatureMoved(const CFeature* feature, const float3& oldpos)
562 {
563 	const int featureAllyTeam = feature->allyteam;
564 	const int count = listFeatureMoved.size();
565 	for (int i = 0; i < count; i++) {
566 		CEventClient* ec = listFeatureMoved[i];
567 		if ((featureAllyTeam < 0) || ec->CanReadAllyTeam(featureAllyTeam)) {
568 			ec->FeatureMoved(feature, oldpos);
569 		}
570 	}
571 }
572 
573 
ProjectileCreated(const CProjectile * proj,int allyTeam)574 inline void CEventHandler::ProjectileCreated(const CProjectile* proj, int allyTeam)
575 {
576 	const int count = listProjectileCreated.size();
577 	for (int i = 0; i < count; i++) {
578 		CEventClient* ec = listProjectileCreated[i];
579 		if ((allyTeam < 0) || // projectile had no owner at creation
580 		    ec->CanReadAllyTeam(allyTeam)) {
581 			ec->ProjectileCreated(proj);
582 		}
583 	}
584 }
585 
586 
ProjectileDestroyed(const CProjectile * proj,int allyTeam)587 inline void CEventHandler::ProjectileDestroyed(const CProjectile* proj, int allyTeam)
588 {
589 	const int count = listProjectileDestroyed.size();
590 	for (int i = 0; i < count; i++) {
591 		CEventClient* ec = listProjectileDestroyed[i];
592 		if ((allyTeam < 0) || // projectile had no owner at creation
593 		    ec->CanReadAllyTeam(allyTeam)) {
594 			ec->ProjectileDestroyed(proj);
595 		}
596 	}
597 }
598 
599 
UnsyncedHeightMapUpdate(const SRectangle & rect)600 inline void CEventHandler::UnsyncedHeightMapUpdate(const SRectangle& rect)
601 {
602 	ITERATE_EVENTCLIENTLIST(UnsyncedHeightMapUpdate, rect)
603 }
604 
605 
606 
607 
Explosion(int weaponDefID,int projectileID,const float3 & pos,const CUnit * owner)608 inline bool CEventHandler::Explosion(int weaponDefID, int projectileID, const float3& pos, const CUnit* owner)
609 {
610 	const int count = listExplosion.size();
611 	bool noGfx = false;
612 	for (int i = 0; i < count; i++) {
613 		CEventClient* ec = listExplosion[i];
614 		if (ec->GetFullRead()) {
615 			noGfx = noGfx || ec->Explosion(weaponDefID, projectileID, pos, owner);
616 		}
617 	}
618 	return noGfx;
619 }
620 
621 
StockpileChanged(const CUnit * unit,const CWeapon * weapon,int oldCount)622 inline void CEventHandler::StockpileChanged(const CUnit* unit,
623                                                 const CWeapon* weapon,
624                                                 int oldCount)
625 {
626 	ITERATE_UNIT_ALLYTEAM_EVENTCLIENTLIST(StockpileChanged, unit, weapon, oldCount)
627 }
628 
629 
DefaultCommand(const CUnit * unit,const CFeature * feature,int & cmd)630 inline bool CEventHandler::DefaultCommand(const CUnit* unit,
631                                               const CFeature* feature,
632                                               int& cmd)
633 {
634 	// reverse order, user has the override
635 	const int count = listDefaultCommand.size();
636 	for (int i = (count - 1); i >= 0; i--) {
637 		CEventClient* ec = listDefaultCommand[i];
638 		if (ec->DefaultCommand(unit, feature, cmd)) {
639 			return true;
640 		}
641 	}
642 	return false;
643 }
644 
645 
646 
RenderUnitCreated(const CUnit * unit,int cloaked)647 inline void CEventHandler::RenderUnitCreated(const CUnit* unit, int cloaked)
648 {
649 	ITERATE_EVENTCLIENTLIST(RenderUnitCreated, unit, cloaked)
650 }
651 
RenderUnitDestroyed(const CUnit * unit)652 inline void CEventHandler::RenderUnitDestroyed(const CUnit* unit)
653 {
654 	ITERATE_EVENTCLIENTLIST(RenderUnitDestroyed, unit)
655 }
656 
RenderUnitCloakChanged(const CUnit * unit,int cloaked)657 inline void CEventHandler::RenderUnitCloakChanged(const CUnit* unit, int cloaked)
658 {
659 	ITERATE_EVENTCLIENTLIST(RenderUnitCloakChanged, unit, cloaked)
660 }
661 
RenderUnitLOSChanged(const CUnit * unit,int allyTeam,int newStatus)662 inline void CEventHandler::RenderUnitLOSChanged(const CUnit* unit, int allyTeam, int newStatus)
663 {
664 	ITERATE_EVENTCLIENTLIST(RenderUnitLOSChanged, unit, allyTeam, newStatus)
665 }
666 
RenderUnitMoved(const CUnit * unit,const float3 & newpos)667 inline void CEventHandler::RenderUnitMoved(const CUnit* unit, const float3& newpos)
668 {
669 	ITERATE_EVENTCLIENTLIST(RenderUnitMoved, unit, newpos)
670 }
671 
RenderFeatureCreated(const CFeature * feature)672 inline void CEventHandler::RenderFeatureCreated(const CFeature* feature)
673 {
674 	ITERATE_EVENTCLIENTLIST(RenderFeatureCreated, feature)
675 }
676 
RenderFeatureDestroyed(const CFeature * feature)677 inline void CEventHandler::RenderFeatureDestroyed(const CFeature* feature)
678 {
679 	ITERATE_EVENTCLIENTLIST(RenderFeatureDestroyed, feature)
680 }
681 
RenderFeatureMoved(const CFeature * feature,const float3 & oldpos,const float3 & newpos)682 inline void CEventHandler::RenderFeatureMoved(const CFeature* feature, const float3& oldpos, const float3& newpos)
683 {
684 	ITERATE_EVENTCLIENTLIST(RenderFeatureMoved, feature, oldpos, newpos)
685 }
686 
RenderProjectileCreated(const CProjectile * proj)687 inline void CEventHandler::RenderProjectileCreated(const CProjectile* proj)
688 {
689 	ITERATE_EVENTCLIENTLIST(RenderProjectileCreated, proj)
690 }
691 
RenderProjectileDestroyed(const CProjectile * proj)692 inline void CEventHandler::RenderProjectileDestroyed(const CProjectile* proj)
693 {
694 	ITERATE_EVENTCLIENTLIST(RenderProjectileDestroyed, proj)
695 }
696 
697 
698 #undef ITERATE_EVENTCLIENTLIST
699 #undef ITERATE_ALLYTEAM_EVENTCLIENTLIST
700 #undef ITERATE_UNIT_ALLYTEAM_EVENTCLIENTLIST
701 #undef UNIT_CALLIN_NO_PARAM
702 #undef UNIT_CALLIN_INT_PARAMS
703 #undef UNIT_CALLIN_LOS_PARAM
704 
705 #endif /* EVENT_HANDLER_H */
706 
707