Reworked event hook to a system with pre-allocated memory, owned by the battle. This deals with cleaning up event data memory.
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2020-07-31 16:19:39 +02:00
parent 3e8f9340f3
commit 0eaae43444
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
5 changed files with 33 additions and 13 deletions

View File

@ -76,7 +76,4 @@ export bool CreatureLib_Battle_HasVolatileScript(Battle* p, const char* key) {
export uint8_t CreatureLib_Battle_RegisterEventListener(Battle* p, void (*func)(const EventData*)) { export uint8_t CreatureLib_Battle_RegisterEventListener(Battle* p, void (*func)(const EventData*)) {
Try(p->RegisterEventListener(func);) Try(p->RegisterEventListener(func);)
}
export uint8_t CreatureLib_Battle_TriggerEventListener(Battle* p, EventData* data) {
Try(p->TriggerEventListener(data);)
} }

View File

@ -11,16 +11,36 @@ namespace CreatureLib::Battling {
/// for it. /// for it.
class EventHook { class EventHook {
std::vector<EVENT_HOOK_FUNC()> _listeners; std::vector<EVENT_HOOK_FUNC()> _listeners;
size_t _position;
size_t _capacity;
uint64_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: public:
void RegisterListener(EVENT_HOOK_FUNC(func)) { _listeners.push_back(func); } EventHook() : _position(0), _capacity(defaultSize), _memory(static_cast<uint64_t*>(malloc(defaultSize))) {}
~EventHook() { free(_memory); }
void TriggerEvent(EventData* eventData) const { size_t GetPosition() const noexcept { return _position; }
AssertNotNull(eventData) size_t GetCapacity() const noexcept { return _capacity; }
template <class T, class... parameters> void Trigger(parameters... args) {
if (_listeners.size() == 0)
return;
if (_position + sizeof(T) > _capacity) {
_capacity += defaultSize;
_memory = static_cast<uint64_t*>(realloc(_memory, _capacity));
}
auto ptr = _memory + _position;
T* event = new (ptr) T(args...);
_position += sizeof(T);
for (auto listener : _listeners) { for (auto listener : _listeners) {
listener(eventData); listener(event);
} }
} }
void RegisterListener(EVENT_HOOK_FUNC(func)) { _listeners.push_back(func); }
}; };
} }
#endif // CREATURELIB_EVENTHOOK_HPP #endif // CREATURELIB_EVENTHOOK_HPP

View File

@ -163,4 +163,4 @@ void Battle::AddVolatileScript(const ArbUt::StringView& key) {
} }
void Battle::AddVolatileScript(Script* script) { return _volatile.Add(script); } void Battle::AddVolatileScript(Script* script) { return _volatile.Add(script); }
void Battle::RemoveVolatileScript(Script* script) { _volatile.Remove(script->GetName()); } void Battle::RemoveVolatileScript(Script* script) { _volatile.Remove(script->GetName()); }
void Battle::DisplayText(const ArbUt::StringView& text) const { TriggerEventListener(new DisplayTextEvent(text)); } void Battle::DisplayText(const ArbUt::StringView& text) { TriggerEventListener<DisplayTextEvent>(text); }

View File

@ -95,10 +95,13 @@ namespace CreatureLib::Battling {
void RemoveVolatileScript(Script* script); void RemoveVolatileScript(Script* script);
bool HasVolatileScript(const ArbUt::BasicStringView& name) const { return _volatile.Has(name); } bool HasVolatileScript(const ArbUt::BasicStringView& name) const { return _volatile.Has(name); }
bool HasVolatileScript(uint32_t keyHash) const { return _volatile.Has(keyHash); } bool HasVolatileScript(uint32_t keyHash) const { return _volatile.Has(keyHash); }
const EventHook& GetEventHook() const noexcept { return _eventHook; }
void DisplayText(const ArbUt::StringView& text) const; void DisplayText(const ArbUt::StringView& text);
void RegisterEventListener(EVENT_HOOK_FUNC(listener)) { this->_eventHook.RegisterListener(listener); } void RegisterEventListener(EVENT_HOOK_FUNC(listener)) { this->_eventHook.RegisterListener(listener); }
void TriggerEventListener(EventData* data) const { this->_eventHook.TriggerEvent(data); } template <class T, class... parameters> void TriggerEventListener(parameters... args) {
this->_eventHook.Trigger<T>(args...);
}
}; };
} }

View File

@ -124,7 +124,7 @@ bool Battling::Creature::IsFainted() const noexcept { return this->_currentHealt
void Battling::Creature::OnFaint() { void Battling::Creature::OnFaint() {
// HOOK: On Faint // HOOK: On Faint
if (_battle != nullptr) { if (_battle != nullptr) {
_battle->TriggerEventListener(new FaintEvent(this)); _battle->TriggerEventListener<FaintEvent>(this);
} }
_library->GetExperienceLibrary()->HandleExperienceGain(this, _seenOpponents); _library->GetExperienceLibrary()->HandleExperienceGain(this, _seenOpponents);
auto sideIndex = _side->GetCreatureIndex(this); auto sideIndex = _side->GetCreatureIndex(this);
@ -144,7 +144,7 @@ void Battling::Creature::Damage(uint32_t damage, Battling::DamageSource source)
auto newHealth = _currentHealth - damage; auto newHealth = _currentHealth - damage;
auto battle = this->GetBattle(); auto battle = this->GetBattle();
if (battle != nullptr) { if (battle != nullptr) {
battle->TriggerEventListener(new DamageEvent(this, source, _currentHealth, newHealth)); battle->TriggerEventListener<DamageEvent>(this, source, _currentHealth, newHealth);
} }
_currentHealth = newHealth; _currentHealth = newHealth;
@ -164,7 +164,7 @@ void Battling::Creature::Heal(uint32_t amount, bool canRevive) {
auto newHealth = _currentHealth + amount; auto newHealth = _currentHealth + amount;
auto battle = this->GetBattle(); auto battle = this->GetBattle();
if (battle != nullptr) { if (battle != nullptr) {
battle->TriggerEventListener(new HealEvent(this, _currentHealth, newHealth)); battle->TriggerEventListener<HealEvent>(this, _currentHealth, newHealth);
} }
_currentHealth = newHealth; _currentHealth = newHealth;
} }