diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index e312fcd..5942240 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -11,12 +11,15 @@ target_sources(StellarForgeCommon ${CMAKE_CURRENT_SOURCE_DIR}/IError.hpp ${CMAKE_CURRENT_SOURCE_DIR}/UUID.hpp ${CMAKE_CURRENT_SOURCE_DIR}/UUIDException.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/event/EventData.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/event/EventSystem.hpp ${CMAKE_CURRENT_SOURCE_DIR}/managers/ObjectManager.hpp ${CMAKE_CURRENT_SOURCE_DIR}/managers/SceneManager.hpp ${CMAKE_CURRENT_SOURCE_DIR}/managers/ManagerException.hpp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/UUID.cpp ${CMAKE_CURRENT_SOURCE_DIR}/UUIDException.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/event/EventSystem.cpp ${CMAKE_CURRENT_SOURCE_DIR}/managers/ObjectManager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/managers/SceneManager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/managers/ManagerException.cpp diff --git a/src/common/event/EventData.hpp b/src/common/event/EventData.hpp new file mode 100644 index 0000000..07872b6 --- /dev/null +++ b/src/common/event/EventData.hpp @@ -0,0 +1,35 @@ +/* +** EPITECH PROJECT, 2024 +** Stellar-Forge +** File description: +** EventData +*/ + +#ifndef EVENTDATA_HPP +#define EVENTDATA_HPP + +#include + +/** + * @brief Structure to hold event data + * @param name std::string, name of the event + * @param timestamp time_t, timestamp of the event + * @param data void *, data of the event (can be anything) + * @note This structure is used to pass data to the event consumers + */ +struct EventData +{ + std::string name; + time_t timestamp; + void* data; +}; + +/** + * @brief Event consumer function type + * + * @param EventData_t * structure containing the event data + * @note This function type is used to define the event consumers + */ +using EventConsumer = std::function; + +#endif // EVENTDATA_HPP diff --git a/src/common/event/EventSystem.cpp b/src/common/event/EventSystem.cpp new file mode 100644 index 0000000..30f647c --- /dev/null +++ b/src/common/event/EventSystem.cpp @@ -0,0 +1,100 @@ +/* +** EPITECH PROJECT, 2024 +** Stellar-Forge +** File description: +** EventSystem +*/ + +#include "EventSystem.hpp" + +EventSystem::EventSystem(): _listeners({}) +{ + _event_system = this; +} + +EventSystem::~EventSystem() +{ + for (auto& [_, listenerVector] : this->_listeners) + { + listenerVector.clear(); + } + this->_listeners.clear(); +} + +UUID EventSystem::registerListener(const std::string& name, const EventConsumer& listener) +{ + auto uuid = UUID(); + uuid.generateUuid(); + + if (this->_listeners.find(name) == this->_listeners.end()) + { + this->_listeners[name] = std::vector>(); + } + this->_listeners[name].emplace_back(uuid, listener); + return uuid; +} + +bool EventSystem::unregisterListener(const UUID& uuid) +{ + for (auto& [key, listenersVector] : this->_listeners) + { + for (int i = 0; i < listenersVector.size(); i++) + { + if (listenersVector[i].first == uuid) + { + listenersVector.erase(listenersVector.begin() + i); + if (listenersVector.empty()) + { + this->_listeners.erase(key); + } + return true; + } + } + } + return false; +} + +bool EventSystem::triggerEvents(const std::string& eventName, void* data) +{ + auto const eventData = EventData{eventName, std::time(nullptr), data}; + bool handled = false; + + if (this->_listeners.find(eventName) != this->_listeners.end()) + { + handled = this->_triggerEventFromEventName(eventName, eventData) || handled; + } + for (auto& [key, _] : this->_listeners) + { + std::size_t const found = key.find('*'); + if (found != std::string::npos) + { + std::string const name = key.substr(0, found); + if (eventName.find(name) == 0) + { + handled = this->_triggerEventFromEventName(key, eventData) || handled; + } + } + } + return handled; +} + +bool EventSystem::_triggerEventFromEventName(const std::string& eventName, const EventData& eventData) +{ + bool handled = false; + + for (auto& [_, callback] : this->_listeners[eventName]) + { + callback(eventData); + handled = true; + } + return handled; +} + +EventSystem* EventSystem::getInstance() +{ + if (_event_system == nullptr) + { + return nullptr; + } + return _event_system; +} diff --git a/src/common/event/EventSystem.hpp b/src/common/event/EventSystem.hpp new file mode 100644 index 0000000..6c6ead0 --- /dev/null +++ b/src/common/event/EventSystem.hpp @@ -0,0 +1,124 @@ +/* +** EPITECH PROJECT, 2024 +** Stellar-Forge +** File description: +** EventSystem +*/ + +#ifndef EVENTSYSTEM_HPP +#define EVENTSYSTEM_HPP + +#include "../UUID.hpp" +#include "EventData.hpp" + +/** + * @brief Event System class + * @details This class is used to manage events and event listeners + * @version 0.1.0 + * @since 0.1.0 + * @author Marius PAIN + */ +class EventSystem +{ +public: + /** + * @brief Default constructor + * @details This constructor initializes the event system + * @version 0.1.0 + * @since 0.1.0 + * @author Marius PAIN + */ + EventSystem(); + + /** + * @brief Default destructor + * @details This destructor clears the event system + * @version 0.1.0 + * @since 0.1.0 + * @author Marius PAIN + */ + ~EventSystem(); + + /** + * @brief Register a listener for an event + * @details This function registers a listener for an event + * @param name std::string, the name of the event + * @param listener EventConsumer, the listener to register + * @return UUID, the UUID of the listener + * @version 0.1.0 + * @since 0.1.0 + * @author Marius PAIN + */ + UUID registerListener(const std::string& name, const EventConsumer& listener); + + /** + * @brief Unregister a listener + * @details This function unregisters a listener + * @param uuid UUID, the UUID of the listener to unregister + * @return bool, true if the listener was unregistered, + * false if the listener was not found + * @version 0.1.0 + * @since 0.1.0 + * @author Marius PAIN + */ + bool unregisterListener(const UUID& uuid); + + /** + * @brief Trigger an event + * @details This function triggers an event + * @param eventName std::string, the name of the event to trigger + * @param data void*, the data to pass to the listeners + * @return bool, true if at least one listener was found, + * false if no listener was found + * @version 0.1.0 + * @since 0.1.0 + * @author Marius PAIN + */ + bool triggerEvents(const std::string& eventName, void* data = nullptr); + + /** + * @brief Get the instance of the event system + * @details This function returns an instance of the event system + * @return EventSystem*, the instance of the event system + * @version 0.1.0 + * @since 0.1.0 + * @author Marius PAIN + */ + static EventSystem* getInstance(); + +private: + /** + * @brief Trigger an event from the event name + * @details This function triggers an event from the event name + * @param eventName std::string, the name of the event to trigger + * @param eventData EventData, the data to pass to the listeners + * @return bool, true if at least one listener was found, + * false if no listener was found + * @version 0.1.0 + * @since 0.1.0 + * @author Marius PAIN + */ + bool _triggerEventFromEventName(const std::string& eventName, const EventData& eventData); + + /** + * @brief Listeners + * @details This unordered map contains the listeners + * the key is the name of the event and the value is a vector of pairs + * that contains the UUID of the listener and the listener itself + * @version 0.1.0 + * @since 0.1.0 + * @author Marius PAIN + */ + std::unordered_map>> _listeners; + + /** + * @brief Event manager + * @details This static pointer contains the event manager + * @version 0.1.0 + * @since 0.1.0 + * @author Marius PAIN + */ + static EventSystem* _event_system; +}; + +#endif // EVENTSYSTEM_HPP