change timers to not use ptrs (#1399)

add comments as to why logic may seem confusing.
This commit is contained in:
David Markowitz 2024-01-06 01:45:23 -08:00 committed by GitHub
parent 325598cd99
commit 14c20fbd62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 67 additions and 78 deletions

View File

@ -1222,39 +1222,56 @@ void Entity::UpdateXMLDoc(tinyxml2::XMLDocument* doc) {
void Entity::Update(const float deltaTime) { void Entity::Update(const float deltaTime) {
uint32_t timerPosition; uint32_t timerPosition;
timerPosition = 0; for (timerPosition = 0; timerPosition < m_Timers.size();) {
while (timerPosition < m_Timers.size()) { auto& timer = m_Timers[timerPosition];
m_Timers[timerPosition]->Update(deltaTime); timer.Update(deltaTime);
if (m_Timers[timerPosition]->GetTime() <= 0) { // If the timer is expired, erase it and dont increment the position because the next timer will be at the same position.
const auto timerName = m_Timers[timerPosition]->GetName(); // Before: [0, 1, 2, 3, ..., n]
// timerPosition ^
delete m_Timers[timerPosition]; // After: [0, 1, 3, ..., n]
// timerPosition ^
if (timer.GetTime() <= 0) {
// Remove the timer from the list of timers first so that scripts and events can remove timers without causing iterator invalidation
auto timerName = timer.GetName();
m_Timers.erase(m_Timers.begin() + timerPosition); m_Timers.erase(m_Timers.begin() + timerPosition);
for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) { for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) {
script->OnTimerDone(this, timerName); script->OnTimerDone(this, timerName);
} }
TriggerEvent(eTriggerEventType::TIMER_DONE, this); TriggerEvent(eTriggerEventType::TIMER_DONE, this);
} else {
// If the timer isnt expired, go to the next timer.
timerPosition++;
}
}
for (timerPosition = 0; timerPosition < m_CallbackTimers.size(); ) {
// If the timer is expired, erase it and dont increment the position because the next timer will be at the same position.
// Before: [0, 1, 2, 3, ..., n]
// timerPosition ^
// After: [0, 1, 3, ..., n]
// timerPosition ^
auto& callbackTimer = m_CallbackTimers[timerPosition];
callbackTimer.Update(deltaTime);
if (callbackTimer.GetTime() <= 0) {
// Remove the timer from the list of timers first so that callbacks can remove timers without causing iterator invalidation
auto callback = callbackTimer.GetCallback();
m_CallbackTimers.erase(m_CallbackTimers.begin() + timerPosition);
callback();
} else { } else {
timerPosition++; timerPosition++;
} }
} }
for (int i = 0; i < m_CallbackTimers.size(); i++) { // Add pending timers to the list of timers so they start next tick.
m_CallbackTimers[i]->Update(deltaTime); if (!m_PendingTimers.empty()) {
if (m_CallbackTimers[i]->GetTime() <= 0) { m_Timers.insert(m_Timers.end(), m_PendingTimers.begin(), m_PendingTimers.end());
m_CallbackTimers[i]->GetCallback()(); m_PendingTimers.clear();
delete m_CallbackTimers[i];
m_CallbackTimers.erase(m_CallbackTimers.begin() + i);
}
} }
// Add pending timers to the list of timers so they start next tick. if (!m_PendingCallbackTimers.empty()) {
if (m_PendingTimers.size() > 0) { m_CallbackTimers.insert(m_CallbackTimers.end(), m_PendingCallbackTimers.begin(), m_PendingCallbackTimers.end());
for (auto namedTimer : m_PendingTimers) { m_PendingCallbackTimers.clear();
m_Timers.push_back(namedTimer);
}
m_PendingTimers.clear();
} }
if (IsSleeping()) { if (IsSleeping()) {
@ -1692,31 +1709,20 @@ void Entity::RemoveParent() {
} }
void Entity::AddTimer(std::string name, float time) { void Entity::AddTimer(std::string name, float time) {
EntityTimer* timer = new EntityTimer(name, time); m_PendingTimers.emplace_back(name, time);
m_PendingTimers.push_back(timer);
} }
void Entity::AddCallbackTimer(float time, std::function<void()> callback) { void Entity::AddCallbackTimer(float time, std::function<void()> callback) {
EntityCallbackTimer* timer = new EntityCallbackTimer(time, callback); m_PendingCallbackTimers.emplace_back(time, callback);
m_CallbackTimers.push_back(timer);
} }
bool Entity::HasTimer(const std::string& name) { bool Entity::HasTimer(const std::string& name) {
for (auto* timer : m_Timers) { return std::find(m_Timers.begin(), m_Timers.end(), name) != m_Timers.end();
if (timer->GetName() == name) {
return true;
}
}
return false;
} }
void Entity::CancelCallbackTimers() { void Entity::CancelCallbackTimers() {
for (auto* callback : m_CallbackTimers) {
delete callback;
}
m_CallbackTimers.clear(); m_CallbackTimers.clear();
m_PendingCallbackTimers.clear();
} }
void Entity::ScheduleKillAfterUpdate(Entity* murderer) { void Entity::ScheduleKillAfterUpdate(Entity* murderer) {
@ -1728,8 +1734,8 @@ void Entity::ScheduleKillAfterUpdate(Entity* murderer) {
void Entity::CancelTimer(const std::string& name) { void Entity::CancelTimer(const std::string& name) {
for (int i = 0; i < m_Timers.size(); i++) { for (int i = 0; i < m_Timers.size(); i++) {
if (m_Timers[i]->GetName() == name) { auto& timer = m_Timers[i];
delete m_Timers[i]; if (timer == name) {
m_Timers.erase(m_Timers.begin() + i); m_Timers.erase(m_Timers.begin() + i);
return; return;
} }
@ -1737,21 +1743,10 @@ void Entity::CancelTimer(const std::string& name) {
} }
void Entity::CancelAllTimers() { void Entity::CancelAllTimers() {
/*for (auto timer : m_Timers) {
if (timer) delete timer;
}*/
for (auto* timer : m_Timers) {
delete timer;
}
m_Timers.clear(); m_Timers.clear();
m_PendingTimers.clear();
for (auto* callBackTimer : m_CallbackTimers) {
delete callBackTimer;
}
m_CallbackTimers.clear(); m_CallbackTimers.clear();
m_PendingCallbackTimers.clear();
} }
bool Entity::IsPlayer() const { bool Entity::IsPlayer() const {

View File

@ -160,6 +160,8 @@ public:
void AddChild(Entity* child); void AddChild(Entity* child);
void RemoveChild(Entity* child); void RemoveChild(Entity* child);
void RemoveParent(); void RemoveParent();
// Adds a timer to start next frame with the given name and time.
void AddTimer(std::string name, float time); void AddTimer(std::string name, float time);
void AddCallbackTimer(float time, std::function<void()> callback); void AddCallbackTimer(float time, std::function<void()> callback);
bool HasTimer(const std::string& name); bool HasTimer(const std::string& name);
@ -324,9 +326,10 @@ protected:
std::vector<std::function<void(Entity* target)>> m_PhantomCollisionCallbacks; std::vector<std::function<void(Entity* target)>> m_PhantomCollisionCallbacks;
std::unordered_map<eReplicaComponentType, Component*> m_Components; std::unordered_map<eReplicaComponentType, Component*> m_Components;
std::vector<EntityTimer*> m_Timers; std::vector<EntityTimer> m_Timers;
std::vector<EntityTimer*> m_PendingTimers; std::vector<EntityTimer> m_PendingTimers;
std::vector<EntityCallbackTimer*> m_CallbackTimers; std::vector<EntityCallbackTimer> m_CallbackTimers;
std::vector<EntityCallbackTimer> m_PendingCallbackTimers;
bool m_ShouldDestroyAfterUpdate = false; bool m_ShouldDestroyAfterUpdate = false;

View File

@ -1,22 +1,10 @@
#include "EntityCallbackTimer.h" #include "EntityCallbackTimer.h"
EntityCallbackTimer::EntityCallbackTimer(float time, std::function<void()> callback) { EntityCallbackTimer::EntityCallbackTimer(const float time, const std::function<void()> callback) {
m_Time = time; m_Time = time;
m_Callback = callback; m_Callback = callback;
} }
EntityCallbackTimer::~EntityCallbackTimer() {
}
std::function<void()> EntityCallbackTimer::GetCallback() {
return m_Callback;
}
float EntityCallbackTimer::GetTime() {
return m_Time;
}
void EntityCallbackTimer::Update(float deltaTime) { void EntityCallbackTimer::Update(float deltaTime) {
m_Time -= deltaTime; m_Time -= deltaTime;
} }

View File

@ -5,11 +5,11 @@
class EntityCallbackTimer { class EntityCallbackTimer {
public: public:
EntityCallbackTimer(float time, std::function<void()> callback); EntityCallbackTimer(const float time, const std::function<void()> callback);
~EntityCallbackTimer();
std::function<void()> GetCallback(); std::function<void()> GetCallback() const { return m_Callback; };
float GetTime();
float GetTime() const { return m_Time; };
void Update(float deltaTime); void Update(float deltaTime);

View File

@ -1,14 +1,10 @@
#include "EntityTimer.h" #include "EntityTimer.h"
EntityTimer::EntityTimer(std::string name, float time) { EntityTimer::EntityTimer(const std::string& name, const float time) {
m_Name = name; m_Name = name;
m_Time = time; m_Time = time;
} }
EntityTimer::~EntityTimer() {
}
std::string EntityTimer::GetName() { std::string EntityTimer::GetName() {
return m_Name; return m_Name;
} }

View File

@ -4,8 +4,15 @@
class EntityTimer { class EntityTimer {
public: public:
EntityTimer(std::string name, float time); EntityTimer(const std::string& name, const float time);
~EntityTimer();
bool operator==(const EntityTimer& other) const {
return m_Name == other.m_Name;
}
bool operator==(const std::string& other) const {
return m_Name == other;
}
std::string GetName(); std::string GetName();
float GetTime(); float GetTime();