event_manager.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. #pragma once
  2. #include "../units/spawn_type.h"
  3. #include "entity.h"
  4. #include <algorithm>
  5. #include <functional>
  6. #include <memory>
  7. #include <mutex>
  8. #include <typeindex>
  9. #include <unordered_map>
  10. #include <utility>
  11. #include <vector>
  12. namespace Engine::Core {
  13. class Event {
  14. public:
  15. virtual ~Event() = default;
  16. [[nodiscard]] virtual auto get_type_name() const -> const char * {
  17. return "Event";
  18. }
  19. };
  20. template <typename T> using EventHandler = std::function<void(const T &)>;
  21. using SubscriptionHandle = std::size_t;
  22. struct EventStats {
  23. size_t publish_count = 0;
  24. size_t subscriber_count = 0;
  25. };
  26. class EventManager {
  27. public:
  28. static auto instance() -> EventManager & {
  29. static EventManager inst;
  30. return inst;
  31. }
  32. template <typename T>
  33. auto subscribe(EventHandler<T> handler) -> SubscriptionHandle {
  34. static_assert(std::is_base_of_v<Event, T>, "T must inherit from Event");
  35. std::lock_guard<std::mutex> const lock(m_mutex);
  36. SubscriptionHandle const handle = m_nextHandle++;
  37. auto wrapper = [handler, handle](const void *event) {
  38. handler(*static_cast<const T *>(event));
  39. };
  40. HandlerEntry const entry{handle, wrapper};
  41. m_handlers[std::type_index(typeid(T))].push_back(entry);
  42. m_stats[std::type_index(typeid(T))].subscriber_count++;
  43. return handle;
  44. }
  45. template <typename T> void unsubscribe(SubscriptionHandle handle) {
  46. static_assert(std::is_base_of_v<Event, T>, "T must inherit from Event");
  47. std::lock_guard<std::mutex> const lock(m_mutex);
  48. auto it = m_handlers.find(std::type_index(typeid(T)));
  49. if (it != m_handlers.end()) {
  50. auto &handlers = it->second;
  51. auto sizeBefore = handlers.size();
  52. handlers.erase(std::remove_if(handlers.begin(), handlers.end(),
  53. [handle](const HandlerEntry &e) {
  54. return e.handle == handle;
  55. }),
  56. handlers.end());
  57. if (handlers.size() < sizeBefore) {
  58. m_stats[std::type_index(typeid(T))].subscriber_count--;
  59. }
  60. }
  61. }
  62. template <typename T> void publish(const T &event) {
  63. static_assert(std::is_base_of_v<Event, T>, "T must inherit from Event");
  64. std::vector<HandlerEntry> handlersCopy;
  65. {
  66. std::lock_guard<std::mutex> const lock(m_mutex);
  67. auto it = m_handlers.find(std::type_index(typeid(T)));
  68. if (it != m_handlers.end()) {
  69. handlersCopy = it->second;
  70. m_stats[std::type_index(typeid(T))].publish_count++;
  71. }
  72. }
  73. for (const auto &entry : handlersCopy) {
  74. entry.handler(&event);
  75. }
  76. }
  77. auto get_stats(const std::type_index &event_type) const -> EventStats {
  78. std::lock_guard<std::mutex> const lock(m_mutex);
  79. auto it = m_stats.find(event_type);
  80. if (it != m_stats.end()) {
  81. return it->second;
  82. }
  83. return EventStats{};
  84. }
  85. auto get_subscriber_count(const std::type_index &event_type) const -> size_t {
  86. std::lock_guard<std::mutex> const lock(m_mutex);
  87. auto it = m_handlers.find(event_type);
  88. if (it != m_handlers.end()) {
  89. return it->second.size();
  90. }
  91. return 0;
  92. }
  93. void clear_all_subscriptions() {
  94. std::lock_guard<std::mutex> const lock(m_mutex);
  95. m_handlers.clear();
  96. m_stats.clear();
  97. }
  98. private:
  99. struct HandlerEntry {
  100. SubscriptionHandle handle;
  101. std::function<void(const void *)> handler;
  102. };
  103. mutable std::mutex m_mutex;
  104. std::unordered_map<std::type_index, std::vector<HandlerEntry>> m_handlers;
  105. std::unordered_map<std::type_index, EventStats> m_stats;
  106. SubscriptionHandle m_nextHandle = 1;
  107. };
  108. template <typename T> class ScopedEventSubscription {
  109. public:
  110. ScopedEventSubscription() : m_handle(0) {}
  111. ScopedEventSubscription(EventHandler<T> handler)
  112. : m_handle(EventManager::instance().subscribe<T>(handler)) {}
  113. ~ScopedEventSubscription() { unsubscribe(); }
  114. ScopedEventSubscription(const ScopedEventSubscription &) = delete;
  115. auto operator=(const ScopedEventSubscription &) -> ScopedEventSubscription & =
  116. delete;
  117. ScopedEventSubscription(ScopedEventSubscription &&other) noexcept
  118. : m_handle(other.m_handle) {
  119. other.m_handle = 0;
  120. }
  121. auto operator=(ScopedEventSubscription &&other) noexcept
  122. -> ScopedEventSubscription & {
  123. if (this != &other) {
  124. unsubscribe();
  125. m_handle = other.m_handle;
  126. other.m_handle = 0;
  127. }
  128. return *this;
  129. }
  130. void unsubscribe() {
  131. if (m_handle != 0) {
  132. EventManager::instance().unsubscribe<T>(m_handle);
  133. m_handle = 0;
  134. }
  135. }
  136. private:
  137. SubscriptionHandle m_handle;
  138. };
  139. class UnitSelectedEvent : public Event {
  140. public:
  141. UnitSelectedEvent(EntityID unit_id) : unit_id(unit_id) {}
  142. EntityID unit_id;
  143. [[nodiscard]] auto get_type_name() const -> const char * override {
  144. return "UNIT_SELECTED";
  145. }
  146. };
  147. class UnitMovedEvent : public Event {
  148. public:
  149. UnitMovedEvent(EntityID unit_id, float x, float y)
  150. : unit_id(unit_id), x(x), y(y) {}
  151. EntityID unit_id;
  152. float x, y;
  153. };
  154. class UnitDiedEvent : public Event {
  155. public:
  156. UnitDiedEvent(EntityID unit_id, int owner_id,
  157. Game::Units::SpawnType spawn_type, EntityID killer_id = 0,
  158. int killer_owner_id = 0)
  159. : unit_id(unit_id), owner_id(owner_id), spawn_type(spawn_type),
  160. killer_id(killer_id), killer_owner_id(killer_owner_id) {}
  161. EntityID unit_id;
  162. int owner_id;
  163. Game::Units::SpawnType spawn_type;
  164. EntityID killer_id;
  165. int killer_owner_id;
  166. };
  167. class UnitSpawnedEvent : public Event {
  168. public:
  169. UnitSpawnedEvent(EntityID unit_id, int owner_id,
  170. Game::Units::SpawnType spawn_type,
  171. bool is_initial_spawn = true)
  172. : unit_id(unit_id), owner_id(owner_id), spawn_type(spawn_type),
  173. is_initial_spawn(is_initial_spawn) {}
  174. EntityID unit_id;
  175. int owner_id;
  176. Game::Units::SpawnType spawn_type;
  177. bool is_initial_spawn;
  178. };
  179. class BuildingAttackedEvent : public Event {
  180. public:
  181. BuildingAttackedEvent(EntityID building_id, int owner_id,
  182. Game::Units::SpawnType building_type,
  183. EntityID attacker_id = 0, int attacker_owner_id = 0,
  184. int damage = 0)
  185. : building_id(building_id), owner_id(owner_id),
  186. building_type(building_type), attacker_id(attacker_id),
  187. attacker_owner_id(attacker_owner_id), damage(damage) {}
  188. EntityID building_id;
  189. int owner_id;
  190. Game::Units::SpawnType building_type;
  191. EntityID attacker_id;
  192. int attacker_owner_id;
  193. int damage;
  194. };
  195. class BarrackCapturedEvent : public Event {
  196. public:
  197. BarrackCapturedEvent(EntityID barrack_id, int previous_owner_id,
  198. int new_owner_id)
  199. : barrack_id(barrack_id), previous_owner_id(previous_owner_id),
  200. new_owner_id(new_owner_id) {}
  201. EntityID barrack_id;
  202. int previous_owner_id;
  203. int new_owner_id;
  204. };
  205. enum class AmbientState { PEACEFUL, TENSE, COMBAT, VICTORY, DEFEAT };
  206. class AmbientStateChangedEvent : public Event {
  207. public:
  208. AmbientStateChangedEvent(AmbientState new_state, AmbientState previous_state)
  209. : new_state(new_state), previous_state(previous_state) {}
  210. AmbientState new_state;
  211. AmbientState previous_state;
  212. [[nodiscard]] auto get_type_name() const -> const char * override {
  213. return "AMBIENT_STATE_CHANGED";
  214. }
  215. };
  216. class AudioTriggerEvent : public Event {
  217. public:
  218. AudioTriggerEvent(std::string sound_id, float volume = 1.0F,
  219. bool loop = false, int priority = 0)
  220. : sound_id(std::move(sound_id)), volume(volume), loop(loop),
  221. priority(priority) {}
  222. std::string sound_id;
  223. float volume;
  224. bool loop;
  225. int priority;
  226. };
  227. class MusicTriggerEvent : public Event {
  228. public:
  229. MusicTriggerEvent(std::string music_id, float volume = 1.0F,
  230. bool crossfade = true)
  231. : music_id(std::move(music_id)), volume(volume), crossfade(crossfade) {}
  232. std::string music_id;
  233. float volume;
  234. bool crossfade;
  235. };
  236. class CombatHitEvent : public Event {
  237. public:
  238. CombatHitEvent(EntityID attacker_id, EntityID target_id, int damage,
  239. Game::Units::SpawnType attacker_type, bool is_killing_blow)
  240. : attacker_id(attacker_id), target_id(target_id), damage(damage),
  241. attacker_type(attacker_type), is_killing_blow(is_killing_blow) {}
  242. EntityID attacker_id;
  243. EntityID target_id;
  244. int damage;
  245. Game::Units::SpawnType attacker_type;
  246. bool is_killing_blow;
  247. [[nodiscard]] auto get_type_name() const -> const char * override {
  248. return "COMBAT_HIT";
  249. }
  250. };
  251. } // namespace Engine::Core