From 5ea06f9bda7321f798cfdcff311bc70bfe838af9 Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 23 Oct 2023 06:55:38 -0700 Subject: [PATCH] EntityManager: Fix iterator invalidation (#1234) Tested that servers still start up, and that zones like bons no longer hard crash when all players have left the world. --- dGame/EntityManager.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/dGame/EntityManager.cpp b/dGame/EntityManager.cpp index 15634e14..86737dd4 100644 --- a/dGame/EntityManager.cpp +++ b/dGame/EntityManager.cpp @@ -176,8 +176,9 @@ void EntityManager::DestroyEntity(Entity* entity) { } void EntityManager::SerializeEntities() { - for (auto entry = m_EntitiesToSerialize.begin(); entry != m_EntitiesToSerialize.end(); entry++) { - auto* entity = GetEntity(*entry); + for (int32_t i = 0; i < m_EntitiesToSerialize.size(); i++) { + const LWOOBJID toSerialize = m_EntitiesToSerialize.at(i); + auto* entity = GetEntity(toSerialize); if (!entity) continue; @@ -192,7 +193,7 @@ void EntityManager::SerializeEntities() { if (entity->GetIsGhostingCandidate()) { for (auto* player : Player::GetAllPlayers()) { - if (player->IsObserved(*entry)) { + if (player->IsObserved(toSerialize)) { Game::server->Send(&stream, player->GetSystemAddress(), false); } } @@ -204,11 +205,12 @@ void EntityManager::SerializeEntities() { } void EntityManager::KillEntities() { - for (auto entry = m_EntitiesToKill.begin(); entry != m_EntitiesToKill.end(); entry++) { - auto* entity = GetEntity(*entry); + for (int32_t i = 0; i < m_EntitiesToKill.size(); i++) { + const LWOOBJID toKill = m_EntitiesToKill.at(i); + auto* entity = GetEntity(toKill); if (!entity) { - LOG("Attempting to kill null entity %llu", *entry); + LOG("Attempting to kill null entity %llu", toKill); continue; } @@ -222,8 +224,9 @@ void EntityManager::KillEntities() { } void EntityManager::DeleteEntities() { - for (auto entry = m_EntitiesToDelete.begin(); entry != m_EntitiesToDelete.end(); entry++) { - auto entityToDelete = GetEntity(*entry); + for (int32_t i = 0; i < m_EntitiesToDelete.size(); i++) { + const LWOOBJID toDelete = m_EntitiesToDelete.at(i); + auto entityToDelete = GetEntity(toDelete); if (entityToDelete) { // Get all this info first before we delete the player. auto networkIdToErase = entityToDelete->GetNetworkId(); @@ -237,9 +240,9 @@ void EntityManager::DeleteEntities() { if (ghostingToDelete != m_EntitiesToGhost.end()) m_EntitiesToGhost.erase(ghostingToDelete); } else { - LOG("Attempted to delete non-existent entity %llu", *entry); + LOG("Attempted to delete non-existent entity %llu", toDelete); } - m_Entities.erase(*entry); + m_Entities.erase(toDelete); } m_EntitiesToDelete.clear(); }