From df3265c82e7ea712a892e5e7974e79044c6981ef Mon Sep 17 00:00:00 2001 From: David Markowitz Date: Fri, 5 May 2023 23:31:30 -0700 Subject: [PATCH] Add more null checks and split out code Makes crash logs more apparent for what stage they crashed in for the engine updating. --- dGame/EntityManager.cpp | 69 +++++++++++-------- dGame/EntityManager.h | 4 ++ .../ai/MINIGAME/SG_GF/SERVER/SGCannon.cpp | 45 ++++++------ 3 files changed, 67 insertions(+), 51 deletions(-) diff --git a/dGame/EntityManager.cpp b/dGame/EntityManager.cpp index 1a77d365..0fc859bd 100644 --- a/dGame/EntityManager.cpp +++ b/dGame/EntityManager.cpp @@ -161,9 +161,7 @@ void EntityManager::DestroyEntity(const LWOOBJID& objectID) { } void EntityManager::DestroyEntity(Entity* entity) { - if (entity == nullptr) { - return; - } + if (!entity) return; entity->TriggerEvent(eTriggerEventType::DESTROY, entity); @@ -182,15 +180,11 @@ void EntityManager::DestroyEntity(Entity* entity) { ScheduleForDeletion(id); } -void EntityManager::UpdateEntities(const float deltaTime) { - for (const auto& e : m_Entities) { - e.second->Update(deltaTime); - } - +void EntityManager::SerializeEntities() { for (auto entry = m_EntitiesToSerialize.begin(); entry != m_EntitiesToSerialize.end(); entry++) { auto* entity = GetEntity(*entry); - if (entity == nullptr) continue; + if (!entity) continue; m_SerializationCounter++; @@ -212,11 +206,16 @@ void EntityManager::UpdateEntities(const float deltaTime) { } } m_EntitiesToSerialize.clear(); +} +void EntityManager::KillEntities() { for (auto entry = m_EntitiesToKill.begin(); entry != m_EntitiesToKill.end(); entry++) { auto* entity = GetEntity(*entry); - if (!entity) continue; + if (!entity) { + Game::logger->Log("EntityManager", "Attempting to kill null entity %llu", *entry); + continue; + } if (entity->GetScheduledKiller()) { entity->Smash(entity->GetScheduledKiller()->GetObjectID(), eKillType::SILENT); @@ -225,32 +224,41 @@ void EntityManager::UpdateEntities(const float deltaTime) { } } m_EntitiesToKill.clear(); +} +void EntityManager::DeleteEntities() { for (auto entry = m_EntitiesToDelete.begin(); entry != m_EntitiesToDelete.end(); entry++) { - - // Get all this info first before we delete the player. auto entityToDelete = GetEntity(*entry); - auto networkIdToErase = entityToDelete->GetNetworkId(); - const auto& ghostingToDelete = std::find(m_EntitiesToGhost.begin(), m_EntitiesToGhost.end(), entityToDelete); - if (entityToDelete) { - // If we are a player run through the player destructor. - if (entityToDelete->IsPlayer()) { - delete dynamic_cast(entityToDelete); - } else { - delete entityToDelete; - } + // Get all this info first before we delete the player. + auto networkIdToErase = entityToDelete->GetNetworkId(); + const auto& ghostingToDelete = std::find(m_EntitiesToGhost.begin(), m_EntitiesToGhost.end(), entityToDelete); + + delete entityToDelete; + entityToDelete = nullptr; + if (networkIdToErase != 0) m_LostNetworkIds.push(networkIdToErase); + + if (ghostingToDelete != m_EntitiesToGhost.end()) m_EntitiesToGhost.erase(ghostingToDelete); + } else { + Game::logger->Log("EntityManager", "Attempted to delete non-existent entity %llu", *entry); } - - if (ghostingToDelete != m_EntitiesToGhost.end()) m_EntitiesToGhost.erase(ghostingToDelete); - m_Entities.erase(*entry); } m_EntitiesToDelete.clear(); } +void EntityManager::UpdateEntities(const float deltaTime) { + for (const auto& e : m_Entities) { + e.second->Update(deltaTime); + } + + SerializeEntities(); + KillEntities(); + DeleteEntities(); +} + Entity* EntityManager::GetEntity(const LWOOBJID& objectId) const { const auto& index = m_Entities.find(objectId); @@ -316,6 +324,11 @@ const std::unordered_map& EntityManager::GetSpawnPointEnt } void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr, const bool skipChecks) { + if (!entity) { + Game::logger->Log("EntityManager", "Attempted to construct null entity"); + return; + } + if (entity->GetNetworkId() == 0) { uint16_t networkId; @@ -395,9 +408,7 @@ void EntityManager::ConstructAllEntities(const SystemAddress& sysAddr) { } void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr) { - if (entity->GetNetworkId() == 0) { - return; - } + if (!entity || entity->GetNetworkId() == 0) return; RakNet::BitStream stream; @@ -414,9 +425,7 @@ void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr) } void EntityManager::SerializeEntity(Entity* entity) { - if (entity->GetNetworkId() == 0) { - return; - } + if (!entity || entity->GetNetworkId() == 0) return; if (std::find(m_EntitiesToSerialize.begin(), m_EntitiesToSerialize.end(), entity->GetObjectID()) == m_EntitiesToSerialize.end()) { m_EntitiesToSerialize.push_back(entity->GetObjectID()); diff --git a/dGame/EntityManager.h b/dGame/EntityManager.h index 0314cc09..b524344c 100644 --- a/dGame/EntityManager.h +++ b/dGame/EntityManager.h @@ -85,6 +85,10 @@ public: const uint32_t GetHardcoreUscoreEnemiesMultiplier() { return m_HardcoreUscoreEnemiesMultiplier; }; private: + void SerializeEntities(); + void KillEntities(); + void DeleteEntities(); + static EntityManager* m_Address; //For singleton method static std::vector m_GhostingExcludedZones; static std::vector m_GhostingExcludedLOTs; diff --git a/dScripts/ai/MINIGAME/SG_GF/SERVER/SGCannon.cpp b/dScripts/ai/MINIGAME/SG_GF/SERVER/SGCannon.cpp index bdd7a506..50cd229a 100644 --- a/dScripts/ai/MINIGAME/SG_GF/SERVER/SGCannon.cpp +++ b/dScripts/ai/MINIGAME/SG_GF/SERVER/SGCannon.cpp @@ -275,6 +275,11 @@ void SGCannon::OnActivityTimerDone(Entity* self, const std::string& name) { toSpawn.spawnPaths.at(pathIndex) ); + if (!path) { + Game::logger->Log("SGCannon", "Path %s at index %i is null", toSpawn.spawnPaths.at(pathIndex).c_str(), pathIndex); + return; + } + auto info = EntityInfo{}; info.lot = toSpawn.lot; info.spawnerID = self->GetObjectID(); @@ -294,32 +299,30 @@ void SGCannon::OnActivityTimerDone(Entity* self, const std::string& name) { auto* enemy = EntityManager::Instance()->CreateEntity(info, nullptr, self); EntityManager::Instance()->ConstructEntity(enemy); - if (true) { - auto* movementAI = new MovementAIComponent(enemy, {}); + auto* movementAI = new MovementAIComponent(enemy, {}); - enemy->AddComponent(eReplicaComponentType::MOVEMENT_AI, movementAI); + enemy->AddComponent(eReplicaComponentType::MOVEMENT_AI, movementAI); - movementAI->SetSpeed(toSpawn.initialSpeed); - movementAI->SetCurrentSpeed(toSpawn.initialSpeed); - movementAI->SetHaltDistance(0.0f); + movementAI->SetSpeed(toSpawn.initialSpeed); + movementAI->SetCurrentSpeed(toSpawn.initialSpeed); + movementAI->SetHaltDistance(0.0f); - std::vector pathWaypoints; + std::vector pathWaypoints; - for (const auto& waypoint : path->pathWaypoints) { - pathWaypoints.push_back(waypoint.position); - } - - if (GeneralUtils::GenerateRandomNumber(0, 1) < 0.5f) { - std::reverse(pathWaypoints.begin(), pathWaypoints.end()); - } - - movementAI->SetPath(pathWaypoints); - - enemy->AddDieCallback([this, self, enemy, name]() { - RegisterHit(self, enemy, name); - }); + for (const auto& waypoint : path->pathWaypoints) { + pathWaypoints.push_back(waypoint.position); } + if (GeneralUtils::GenerateRandomNumber(0, 1) < 0.5f) { + std::reverse(pathWaypoints.begin(), pathWaypoints.end()); + } + + movementAI->SetPath(pathWaypoints); + + enemy->AddDieCallback([this, self, enemy, name]() { + RegisterHit(self, enemy, name); + }); + // Save the enemy and tell it to start pathing if (enemy != nullptr) { const_cast&>(self->GetVar>(SpawnedObjects)).push_back(enemy->GetObjectID()); @@ -577,7 +580,7 @@ void SGCannon::StopGame(Entity* self, bool cancel) { self->SetNetworkVar(u"UI_Rewards", GeneralUtils::to_u16string(self->GetVar(TotalScoreVariable)) + u"_0_0_0_0_0_0" - ); + ); GameMessages::SendRequestActivitySummaryLeaderboardData( player->GetObjectID(),