diff options
author | Treeston <treeston.mmoc@gmail.com> | 2020-12-30 21:08:22 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-30 21:08:22 +0100 |
commit | f8afcec9f3efc58ce8a38a6c63e2ebfc24d2e01d (patch) | |
tree | 725a62d14988ec5c99d93769510ff92ef5d36c8c /src | |
parent | 0ad1854d1c6a3b6ff93e71272c919f1f5f11d5ed (diff) |
Core/Maps: move pooling hand-off outside of Map::CheckRespawn (PR#25785)
fixes #25777
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Maps/Map.cpp | 109 | ||||
-rw-r--r-- | src/server/game/Pools/PoolMgr.cpp | 15 | ||||
-rw-r--r-- | src/server/game/Pools/PoolMgr.h | 1 |
3 files changed, 69 insertions, 56 deletions
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 1908f2efe2a..912a68e5d31 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -3036,47 +3036,42 @@ bool Map::CheckRespawn(RespawnInfo* info) return false; } - uint32 poolId = info->spawnId ? sPoolMgr->IsPartOfAPool(info->type, info->spawnId) : 0; // Next, check if there's already an instance of this object that would block the respawn - // Only do this for unpooled spawns - if (!poolId) + bool alreadyExists = false; + switch (info->type) { - bool doDelete = false; - switch (info->type) + case SPAWN_TYPE_CREATURE: { - case SPAWN_TYPE_CREATURE: - { - // escort check for creatures only (if the world config boolean is set) - bool const isEscort = (sWorld->getBoolConfig(CONFIG_RESPAWN_DYNAMIC_ESCORTNPC) && data->spawnGroupData->flags & SPAWNGROUP_FLAG_ESCORTQUESTNPC); + // escort check for creatures only (if the world config boolean is set) + bool const isEscort = (sWorld->getBoolConfig(CONFIG_RESPAWN_DYNAMIC_ESCORTNPC) && data->spawnGroupData->flags & SPAWNGROUP_FLAG_ESCORTQUESTNPC); - auto range = _creatureBySpawnIdStore.equal_range(info->spawnId); - for (auto it = range.first; it != range.second; ++it) - { - Creature* creature = it->second; - if (!creature->IsAlive()) - continue; - // escort NPCs are allowed to respawn as long as all other instances are already escorting - if (isEscort && creature->IsEscorted()) - continue; - doDelete = true; - break; - } + auto range = _creatureBySpawnIdStore.equal_range(info->spawnId); + for (auto it = range.first; it != range.second; ++it) + { + Creature* creature = it->second; + if (!creature->IsAlive()) + continue; + // escort NPCs are allowed to respawn as long as all other instances are already escorting + if (isEscort && creature->IsEscorted()) + continue; + alreadyExists = true; break; } - case SPAWN_TYPE_GAMEOBJECT: - // gameobject check is simpler - they cannot be dead or escorting - if (_gameobjectBySpawnIdStore.find(info->spawnId) != _gameobjectBySpawnIdStore.end()) - doDelete = true; - break; - default: - ABORT_MSG("Invalid spawn type %u with spawnId %u on map %u", uint32(info->type), info->spawnId, GetId()); - return true; - } - if (doDelete) - { - info->respawnTime = 0; - return false; + break; } + case SPAWN_TYPE_GAMEOBJECT: + // gameobject check is simpler - they cannot be dead or escorting + if (_gameobjectBySpawnIdStore.find(info->spawnId) != _gameobjectBySpawnIdStore.end()) + alreadyExists = true; + break; + default: + ABORT_MSG("Invalid spawn type %u with spawnId %u on map %u", uint32(info->type), info->spawnId, GetId()); + return true; + } + if (alreadyExists) + { + info->respawnTime = 0; + return false; } // next, check linked respawn time @@ -3094,21 +3089,6 @@ bool Map::CheckRespawn(RespawnInfo* info) info->respawnTime = respawnTime; return false; } - - // now, check if we're part of a pool - if (poolId) - { - // ok, part of a pool - hand off to pool logic to handle this, we're just going to remove the respawn and call it a day - if (info->type == SPAWN_TYPE_GAMEOBJECT) - sPoolMgr->UpdatePool<GameObject>(poolId, info->spawnId); - else if (info->type == SPAWN_TYPE_CREATURE) - sPoolMgr->UpdatePool<Creature>(poolId, info->spawnId); - else - ABORT_MSG("Invalid spawn type %u (spawnid %u) on map %u", uint32(info->type), info->spawnId, GetId()); - info->respawnTime = 0; - return false; - } - // everything ok, let's spawn return true; } @@ -3275,22 +3255,39 @@ void Map::ProcessRespawns() RespawnInfo* next = _respawnTimes.top(); if (now < next->respawnTime) // done for this tick break; - if (CheckRespawn(next)) // see if we're allowed to respawn - { - // ok, respawn + + if (uint32 poolId = sPoolMgr->IsPartOfAPool(next->type, next->spawnId)) // is this part of a pool? + { // if yes, respawn will be handled by (external) pooling logic, just delete the respawn time + // step 1: remove entry from maps to avoid it being reachable by outside logic _respawnTimes.pop(); GetRespawnMapForType(next->type).erase(next->spawnId); + + // step 2: tell pooling logic to do its thing + sPoolMgr->UpdatePool(poolId, next->type, next->spawnId); + + // step 3: get rid of the actual entry + delete next; + } + else if (CheckRespawn(next)) // see if we're allowed to respawn + { // ok, respawn + // step 1: remove entry from maps to avoid it being reachable by outside logic + _respawnTimes.pop(); + GetRespawnMapForType(next->type).erase(next->spawnId); + + // step 2: do the respawn, which involves external logic DoRespawn(next->type, next->spawnId, next->gridId); + + // step 3: get rid of the actual entry delete next; } - else if (!next->respawnTime) // just remove respawn entry without rescheduling - { + else if (!next->respawnTime) + { // just remove this respawn entry without rescheduling _respawnTimes.pop(); GetRespawnMapForType(next->type).erase(next->spawnId); delete next; } - else // value changed, update heap position - { + else + { // new respawn time, update heap position ASSERT(now < next->respawnTime); // infinite loop guard _respawnTimes.decrease(next->handle); SaveRespawnInfoDB(*next); diff --git a/src/server/game/Pools/PoolMgr.cpp b/src/server/game/Pools/PoolMgr.cpp index 3f427526dcf..e685c1f1b15 100644 --- a/src/server/game/Pools/PoolMgr.cpp +++ b/src/server/game/Pools/PoolMgr.cpp @@ -845,3 +845,18 @@ void PoolMgr::UpdatePool(uint32 pool_id, uint32 db_guid_or_pool_id) template void PoolMgr::UpdatePool<Pool>(uint32 pool_id, uint32 db_guid_or_pool_id); template void PoolMgr::UpdatePool<GameObject>(uint32 pool_id, uint32 db_guid_or_pool_id); template void PoolMgr::UpdatePool<Creature>(uint32 pool_id, uint32 db_guid_or_pool_id); + +void PoolMgr::UpdatePool(uint32 pool_id, SpawnObjectType type, uint32 spawnId) +{ + switch (type) + { + case SPAWN_TYPE_CREATURE: + UpdatePool<Creature>(pool_id, spawnId); + break; + case SPAWN_TYPE_GAMEOBJECT: + UpdatePool<GameObject>(pool_id, spawnId); + break; + default: + ABORT_MSG("Invalid spawn type %u passed to PoolMgr::IsPartOfPool (with spawnId %u)", uint32(type), spawnId); + } +} diff --git a/src/server/game/Pools/PoolMgr.h b/src/server/game/Pools/PoolMgr.h index 7ee026998b3..d60fad2e3d0 100644 --- a/src/server/game/Pools/PoolMgr.h +++ b/src/server/game/Pools/PoolMgr.h @@ -120,6 +120,7 @@ class TC_GAME_API PoolMgr template<typename T> void UpdatePool(uint32 pool_id, uint32 db_guid_or_pool_id); + void UpdatePool(uint32 pool_id, SpawnObjectType type, ObjectGuid::LowType spawnId); private: template<typename T> |