CreatureLib/src/Battling/EventHooks/EventHook.hpp

71 lines
2.3 KiB
C++

#ifndef CREATURELIB_EVENTHOOK_HPP
#define CREATURELIB_EVENTHOOK_HPP
#include <Arbutils/Exception.hpp>
#include <functional>
#include <thread>
#include "../../Library/Exceptions/CreatureException.hpp"
#include "Events/EventData.hpp"
template <class T>
concept EventDataType = std::is_base_of<CreatureLib::Battling::EventData, T>::value;
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<void(const CreatureLib::Battling::EventData* non_null)> EventHookFunc;
private:
std::vector<EventHookFunc> _listeners;
size_t _offset;
size_t _capacity;
u8* nullable _memory = nullptr;
static constexpr size_t initialSize = 2048;
static constexpr size_t stepSize = 1024;
public:
EventHook() : _offset(0), _capacity(2048) {
auto ptr = malloc(_capacity);
if (ptr == nullptr) {
THROW("Out of memory.");
}
_memory = static_cast<u8*>(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 <EventDataType T, class... parameters> void Trigger(parameters... args) {
if (_listeners.size() == 0)
return;
if (_offset + sizeof(T) >= _capacity) {
_capacity += stepSize;
auto* newPtr = realloc(_memory, _capacity);
if (newPtr == nullptr) {
THROW("Out of memory.");
}
_memory = static_cast<u8*>(newPtr);
}
u8* ptr = _memory + _offset;
T* event = new (ptr) T(args...);
_offset += sizeof(T);
for (const auto& listener : _listeners) {
try_creature(listener(event), "Exception in event listener");
}
}
void RegisterListener(const EventHookFunc& func) { _listeners.push_back(func); }
private:
};
}
#endif // CREATURELIB_EVENTHOOK_HPP