fix: Remove pending timer logic (#1416)

* remove pending timers

they serve no purpose anymore since iterator invalidation is a non-issue.  I added this initially to make it so if you added a timer this frame, there would be at least 1 frame before you would start it, but this in practice doesnt serve a purpose

* timers still work
This commit is contained in:
David Markowitz 2024-01-14 01:46:56 -08:00 committed by GitHub
parent 6592bbea46
commit 0a30430c4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 18 additions and 22 deletions

View File

@ -1243,12 +1243,18 @@ void Entity::Update(const float deltaTime) {
// 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]
// After: [0, 1, n, ..., n - 1] 2 is expired and removed now
// 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);
// We don't need to copy the element if there is only 1 element nor do we need to copy if we are on the last element.
// This is a clever removal trick that avoids having to copy the entire vector and instead replaces this now expired
// element with the last element in the vector and then removes the last element.
if (m_Timers.size() > 1 && timerPosition < m_Timers.size() - 1) {
m_Timers[timerPosition] = m_Timers[m_Timers.size() - 1];
}
m_Timers.erase(m_Timers.end() - 1);
for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) {
script->OnTimerDone(this, timerName);
}
@ -1264,31 +1270,26 @@ void Entity::Update(const float deltaTime) {
// 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]
// After: [0, 1, n, ..., n - 1] 2 is expired and removed now
// 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);
// We don't need to copy the element if there is only 1 element nor do we need to copy if we are on the last element.
// This is a clever removal trick that avoids having to copy the entire vector and instead replaces this now expired
// element with the last element in the vector and then removes the last element.
if (m_CallbackTimers.size() > 1 && timerPosition < m_CallbackTimers.size() - 1) {
m_CallbackTimers[timerPosition] = m_CallbackTimers[m_CallbackTimers.size() - 1];
}
m_CallbackTimers.erase(m_CallbackTimers.end() - 1);
callback();
} else {
timerPosition++;
}
}
// Add pending timers to the list of timers so they start next tick.
if (!m_PendingTimers.empty()) {
m_Timers.insert(m_Timers.end(), m_PendingTimers.begin(), m_PendingTimers.end());
m_PendingTimers.clear();
}
if (!m_PendingCallbackTimers.empty()) {
m_CallbackTimers.insert(m_CallbackTimers.end(), m_PendingCallbackTimers.begin(), m_PendingCallbackTimers.end());
m_PendingCallbackTimers.clear();
}
if (IsSleeping()) {
Sleep();
@ -1724,11 +1725,11 @@ void Entity::RemoveParent() {
}
void Entity::AddTimer(std::string name, float time) {
m_PendingTimers.emplace_back(name, time);
m_Timers.emplace_back(name, time);
}
void Entity::AddCallbackTimer(float time, std::function<void()> callback) {
m_PendingCallbackTimers.emplace_back(time, callback);
m_CallbackTimers.emplace_back(time, callback);
}
bool Entity::HasTimer(const std::string& name) {
@ -1737,7 +1738,6 @@ bool Entity::HasTimer(const std::string& name) {
void Entity::CancelCallbackTimers() {
m_CallbackTimers.clear();
m_PendingCallbackTimers.clear();
}
void Entity::ScheduleKillAfterUpdate(Entity* murderer) {
@ -1759,9 +1759,7 @@ void Entity::CancelTimer(const std::string& name) {
void Entity::CancelAllTimers() {
m_Timers.clear();
m_PendingTimers.clear();
m_CallbackTimers.clear();
m_PendingCallbackTimers.clear();
}
bool Entity::IsPlayer() const {

View File

@ -330,9 +330,7 @@ protected:
std::unordered_map<eReplicaComponentType, Component*> m_Components;
std::vector<EntityTimer> m_Timers;
std::vector<EntityTimer> m_PendingTimers;
std::vector<EntityCallbackTimer> m_CallbackTimers;
std::vector<EntityCallbackTimer> m_PendingCallbackTimers;
bool m_ShouldDestroyAfterUpdate = false;