#ifndef CREATURELIB_EVENTHOOK_HPP #define CREATURELIB_EVENTHOOK_HPP #include #include #include "../../Library/Exceptions/CreatureException.hpp" #include "EventData.hpp" namespace CreatureLib::Battling { /// The Event Hook class allows users to write consumers for the battle events, for example to write User Interfaces /// for it. class EventHook { public: typedef std::function EventHookFunc; private: std::vector _listeners; size_t _offset; size_t _capacity; uint8_t* _memory = nullptr; // Consider tweaking this size to be in line with the normal amount of events we use. static const size_t defaultSize = 1024; public: EventHook() : _offset(0), _capacity(defaultSize) { auto ptr = malloc(_capacity); if (ptr == nullptr) { THROW_CREATURE("Out of memory."); } _memory = static_cast(ptr); } EventHook(const EventHook&) = delete; EventHook& operator=(const EventHook&) = delete; ~EventHook() { free(_memory); } size_t GetPosition() const noexcept { return _offset; } size_t GetCapacity() const noexcept { return _capacity; } template void Trigger(parameters... args) { if (_listeners.size() == 0) return; if (_offset + sizeof(T) >= _capacity) { _capacity += defaultSize; auto newPtr = realloc(_memory, _capacity); if (newPtr == nullptr) { THROW_CREATURE("Out of memory."); } _memory = static_cast(newPtr); } uint8_t* ptr = _memory + _offset; T* event = new (ptr) T(args...); _offset += sizeof(T); for (auto listener : _listeners) { try_creature(listener(event), "Exception in event listener"); } } void RegisterListener(const EventHookFunc& func) { _listeners.push_back(func); } }; } #endif // CREATURELIB_EVENTHOOK_HPP