diff --git a/CMakeLists.txt b/CMakeLists.txt index bfb86ac..7c794db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,7 @@ target_link_libraries(CreatureLib PUBLIC ${_LIBRARYLINKS}) if (TESTS) # Create Test executable file(GLOB_RECURSE TEST_FILES "tests/*.cpp" "tests/*.hpp") - add_executable(CreatureLibTests ${TEST_FILES} extern/catch.hpp) + add_executable(CreatureLibTests ${TEST_FILES} extern/catch.hpp tests/BattleTests/EventHookTests.cpp) target_link_libraries(CreatureLibTests PUBLIC CreatureLib Arbutils) # Add a definition for the test library diff --git a/src/Battling/EventHooks/EventHook.hpp b/src/Battling/EventHooks/EventHook.hpp index f018ee1..888d3df 100644 --- a/src/Battling/EventHooks/EventHook.hpp +++ b/src/Battling/EventHooks/EventHook.hpp @@ -1,25 +1,29 @@ #ifndef CREATURELIB_EVENTHOOK_HPP #define CREATURELIB_EVENTHOOK_HPP +#include #include #include "EventData.hpp" -#define EVENT_HOOK_FUNC(name) void (*name)(const EventData*) 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 { - std::vector _listeners; + public: + typedef std::function EventHookFunc; + + private: + std::vector _listeners; size_t _position; size_t _capacity; - uint64_t* _memory; + uint8_t* _memory; // Consider tweaking this size to be in line with the normal amount of events we use. static const size_t defaultSize = 1024; public: - EventHook() : _position(0), _capacity(defaultSize), _memory(static_cast(malloc(defaultSize))) {} + EventHook() : _position(0), _capacity(defaultSize), _memory(static_cast(malloc(defaultSize))) {} ~EventHook() { free(_memory); } size_t GetPosition() const noexcept { return _position; } @@ -30,9 +34,9 @@ namespace CreatureLib::Battling { return; if (_position + sizeof(T) > _capacity) { _capacity += defaultSize; - _memory = static_cast(realloc(_memory, _capacity)); + _memory = static_cast(realloc(_memory, _capacity)); } - auto ptr = _memory + _position; + uint8_t* ptr = _memory + _position; T* event = new (ptr) T(args...); _position += sizeof(T); for (auto listener : _listeners) { @@ -40,7 +44,7 @@ namespace CreatureLib::Battling { } } - void RegisterListener(EVENT_HOOK_FUNC(func)) { _listeners.push_back(func); } + void RegisterListener(const EventHookFunc& func) { _listeners.push_back(func); } }; } #endif // CREATURELIB_EVENTHOOK_HPP diff --git a/src/Battling/Models/Battle.hpp b/src/Battling/Models/Battle.hpp index 38fe354..858b419 100644 --- a/src/Battling/Models/Battle.hpp +++ b/src/Battling/Models/Battle.hpp @@ -98,7 +98,7 @@ namespace CreatureLib::Battling { const EventHook& GetEventHook() const noexcept { return _eventHook; } void DisplayText(const ArbUt::StringView& text); - void RegisterEventListener(EVENT_HOOK_FUNC(listener)) { this->_eventHook.RegisterListener(listener); } + void RegisterEventListener(EventHook::EventHookFunc listener) { this->_eventHook.RegisterListener(listener); } template void TriggerEventListener(parameters... args) { this->_eventHook.Trigger(args...); } diff --git a/tests/BattleTests/EventHookTests.cpp b/tests/BattleTests/EventHookTests.cpp new file mode 100644 index 0000000..37549ad --- /dev/null +++ b/tests/BattleTests/EventHookTests.cpp @@ -0,0 +1,30 @@ +#ifdef TESTS_BUILD +#include "../../extern/catch.hpp" +#include "../../src/Battling/EventHooks/EventHook.hpp" +#include "../../src/Battling/Models/CreateCreature.hpp" +#include "../TestLibrary/TestLibrary.hpp" + +using namespace CreatureLib::Battling; + +TEST_CASE("Build and use event hook", "[Battling]") { + auto eventHook = EventHook(); + std::vector events; + eventHook.RegisterListener([&](const EventData* evt) mutable -> void { events.push_back(evt); }); + for (size_t i = 0; i < 10; i++) { + eventHook.Trigger(nullptr, DamageSource::AttackDamage, 0, 0); + } + REQUIRE(events.size() == 10); + REQUIRE(events[0]->GetKind() == EventDataKind::Damage); +} + +TEST_CASE("Build and use event hook a lot", "[Battling]") { + auto eventHook = EventHook(); + std::vector events; + eventHook.RegisterListener([&](const EventData* evt) mutable -> void { events.push_back(evt); }); + for (size_t i = 0; i < 10000; i++) { + eventHook.Trigger(nullptr, DamageSource::AttackDamage, 0, 0); + } + REQUIRE(events.size() == 10000); +} + +#endif \ No newline at end of file