From c29c7bd968be4de9f0d3d3788b3ee94d9734b886 Mon Sep 17 00:00:00 2001 From: Stoabrogga <38475780+Stoabrogga@users.noreply.github.com> Date: Wed, 10 Jul 2019 02:28:56 +0200 Subject: [PATCH] feat(Core/Pool): improve pool manager (#2027) Use "std::unordered_map" instead of "std::vector" in order to reduce memory usage (not much, perhaps 5-10%) identify missing pool entries in pool_template via error messages in the server log Concerning the pool entries I applied the following fixes as they would now cause errors: Remove pool entry 5217 from pool_gameobject (only 1 game object "Saronite", not needed here) Remove pool entry 1047 from pool_creature (only 1 creature "Hematos", not needed here) Add a few missing Saronite nodes to pool_template --- .../rev_1561816769087112416.sql | 16 ++ src/server/game/Pools/PoolMgr.cpp | 146 +++++++++++------- src/server/game/Pools/PoolMgr.h | 11 +- 3 files changed, 107 insertions(+), 66 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1561816769087112416.sql diff --git a/data/sql/updates/pending_db_world/rev_1561816769087112416.sql b/data/sql/updates/pending_db_world/rev_1561816769087112416.sql new file mode 100644 index 000000000..60c3e821e --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1561816769087112416.sql @@ -0,0 +1,16 @@ +INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1561816769087112416'); + +-- Only one game object "Saronite", pool entry is not needed +DELETE FROM `pool_gameobject` WHERE `pool_entry` = 5217; + +-- Only one creature "Hematos" (8976), pool entry is not needed +DELETE FROM `pool_creature` WHERE `pool_entry` = 1047; + +-- Add missing Saronite nodes to pool template +DELETE FROM `pool_template` WHERE `entry` IN (5450,5506,5608,5517); +INSERT INTO `pool_template` (`entry`,`max_limit`,`description`) +VALUES +(5450,1,'Icecrown 189980, node 3'), +(5506,1,'Icecrown 189980, node 59'), +(5608,1,'Icecrown 189980, node 161'), +(5517,1,'Icecrown 189981, node 70'); diff --git a/src/server/game/Pools/PoolMgr.cpp b/src/server/game/Pools/PoolMgr.cpp index d2fac39d9..ee15379ff 100644 --- a/src/server/game/Pools/PoolMgr.cpp +++ b/src/server/game/Pools/PoolMgr.cpp @@ -533,25 +533,12 @@ void PoolGroup::ReSpawn1Object(PoolObject* /*obj*/) //////////////////////////////////////////////////////////// // Methods of class PoolMgr -PoolMgr::PoolMgr() : max_pool_id(0) +PoolMgr::PoolMgr() { } void PoolMgr::Initialize() { - QueryResult result = WorldDatabase.Query("SELECT MAX(entry) FROM pool_template"); - if (result) - { - Field* fields = result->Fetch(); - max_pool_id = fields[0].GetUInt32(); - } - - mPoolTemplate.resize(max_pool_id + 1); - mPoolCreatureGroups.resize(max_pool_id + 1); - mPoolGameobjectGroups.resize(max_pool_id + 1); - mPoolPoolGroups.resize(max_pool_id + 1); - mPoolQuestGroups.resize(max_pool_id + 1); - mQuestSearchMap.clear(); mGameobjectSearchMap.clear(); mCreatureSearchMap.clear(); @@ -621,9 +608,10 @@ void PoolMgr::LoadFromDB() sLog->outErrorDb("`pool_creature` has a non existing creature spawn (GUID: %u) defined for pool id (%u), skipped.", guid, pool_id); continue; } - if (pool_id > max_pool_id) + auto it = mPoolTemplate.find(pool_id); + if (it == mPoolTemplate.end()) { - sLog->outErrorDb("`pool_creature` pool id (%u) is out of range compared to max pool id in `pool_template`, skipped.", pool_id); + sLog->outErrorDb("`pool_creature` pool id (%u) is not in `pool_template`, skipped.", pool_id); continue; } if (chance < 0 || chance > 100) @@ -689,9 +677,10 @@ void PoolMgr::LoadFromDB() continue; } - if (pool_id > max_pool_id) + auto it = mPoolTemplate.find(pool_id); + if (it == mPoolTemplate.end()) { - sLog->outErrorDb("`pool_gameobject` pool id (%u) is out of range compared to max pool id in `pool_template`, skipped.", pool_id); + sLog->outErrorDb("`pool_gameobject` pool id (%u) is not in `pool_template`, skipped.", pool_id); continue; } @@ -743,15 +732,21 @@ void PoolMgr::LoadFromDB() uint32 mother_pool_id = fields[1].GetUInt32(); float chance = fields[2].GetFloat(); - if (mother_pool_id > max_pool_id) { - sLog->outErrorDb("`pool_pool` mother_pool id (%u) is out of range compared to max pool id in `pool_template`, skipped.", mother_pool_id); - continue; + auto it = mPoolTemplate.find(mother_pool_id); + if (it == mPoolTemplate.end()) + { + sLog->outErrorDb("`pool_pool` mother_pool id (%u) is not in `pool_template`, skipped.", mother_pool_id); + continue; + } } - if (child_pool_id > max_pool_id) { - sLog->outErrorDb("`pool_pool` included pool_id (%u) is out of range compared to max pool id in `pool_template`, skipped.", child_pool_id); - continue; + auto it = mPoolTemplate.find(child_pool_id); + if (it == mPoolTemplate.end()) + { + sLog->outErrorDb("`pool_pool` included pool_id (%u) is not in `pool_template`, skipped.", child_pool_id); + continue; + } } if (mother_pool_id == child_pool_id) { @@ -776,10 +771,11 @@ void PoolMgr::LoadFromDB() while (result->NextRow()); // Now check for circular reference - for (uint32 i=0; i < max_pool_id; ++i) + // All pool_ids are in pool_template + for (auto const it : mPoolTemplate) { std::set checkedPools; - for (SearchMap::iterator poolItr = mPoolSearchMap.find(i); poolItr != mPoolSearchMap.end(); poolItr = mPoolSearchMap.find(poolItr->second)) + for (SearchMap::iterator poolItr = mPoolSearchMap.find(it.first); poolItr != mPoolSearchMap.end(); poolItr = mPoolSearchMap.find(poolItr->second)) { checkedPools.insert(poolItr->first); if (checkedPools.find(poolItr->second) != checkedPools.end()) @@ -844,9 +840,10 @@ void PoolMgr::LoadFromDB() continue; } - if (pool_id > max_pool_id) + auto it = mPoolTemplate.find(pool_id); + if (it == mPoolTemplate.end()) { - sLog->outErrorDb("`pool_quest` pool id (%u) is out of range compared to max pool id in `pool_template`, skipped.", pool_id); + sLog->outErrorDb("`pool_quest` pool id (%u) is not in `pool_template`, skipped.", pool_id); continue; } @@ -956,9 +953,9 @@ void PoolMgr::SaveQuestsToDB(bool daily, bool weekly, bool other) std::set deletedPools; for (PoolGroupQuestMap::iterator itr = mPoolQuestGroups.begin(); itr != mPoolQuestGroups.end(); ++itr) { - if (itr->isEmpty()) + if (itr->second.isEmpty()) continue; - if (Quest const* quest = sObjectMgr->GetQuestTemplate(itr->GetFirstEqualChancedObjectId())) + if (Quest const* quest = sObjectMgr->GetQuestTemplate(itr->second.GetFirstEqualChancedObjectId())) { if (!daily && quest->IsDaily()) continue; @@ -968,9 +965,9 @@ void PoolMgr::SaveQuestsToDB(bool daily, bool weekly, bool other) continue; } PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_QUEST_POOL_SAVE); - stmt->setUInt32(0, itr->GetPoolId()); + stmt->setUInt32(0, itr->second.GetPoolId()); trans->Append(stmt); - deletedPools.insert(itr->GetPoolId()); + deletedPools.insert(itr->second.GetPoolId()); } for (SearchMap::iterator itr = mQuestSearchMap.begin(); itr != mQuestSearchMap.end(); ++itr) @@ -990,12 +987,12 @@ void PoolMgr::ChangeDailyQuests() { for (PoolGroupQuestMap::iterator itr = mPoolQuestGroups.begin(); itr != mPoolQuestGroups.end(); ++itr) { - if (Quest const* quest = sObjectMgr->GetQuestTemplate(itr->GetFirstEqualChancedObjectId())) + if (Quest const* quest = sObjectMgr->GetQuestTemplate(itr->second.GetFirstEqualChancedObjectId())) { if (quest->IsWeekly()) continue; - UpdatePool(itr->GetPoolId(), 1); // anything non-zero means don't load from db + UpdatePool(itr->second.GetPoolId(), 1); // anything non-zero means don't load from db } } @@ -1006,12 +1003,12 @@ void PoolMgr::ChangeWeeklyQuests() { for (PoolGroupQuestMap::iterator itr = mPoolQuestGroups.begin(); itr != mPoolQuestGroups.end(); ++itr) { - if (Quest const* quest = sObjectMgr->GetQuestTemplate(itr->GetFirstEqualChancedObjectId())) + if (Quest const* quest = sObjectMgr->GetQuestTemplate(itr->second.GetFirstEqualChancedObjectId())) { if (quest->IsDaily()) continue; - UpdatePool(itr->GetPoolId(), 1); + UpdatePool(itr->second.GetPoolId(), 1); } } @@ -1023,8 +1020,9 @@ void PoolMgr::ChangeWeeklyQuests() template<> void PoolMgr::SpawnPool(uint32 pool_id, uint32 db_guid) { - if (!mPoolCreatureGroups[pool_id].isEmpty()) - mPoolCreatureGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, db_guid); + auto it = mPoolCreatureGroups.find(pool_id); + if (it != mPoolCreatureGroups.end() && !it->second.isEmpty()) + it->second.SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, db_guid); } // Call to spawn a pool, if cache if true the method will spawn only if cached entry is different @@ -1032,8 +1030,9 @@ void PoolMgr::SpawnPool(uint32 pool_id, uint32 db_guid) template<> void PoolMgr::SpawnPool(uint32 pool_id, uint32 db_guid) { - if (!mPoolGameobjectGroups[pool_id].isEmpty()) - mPoolGameobjectGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, db_guid); + auto it = mPoolGameobjectGroups.find(pool_id); + if (it != mPoolGameobjectGroups.end() && !it->second.isEmpty()) + it->second.SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, db_guid); } // Call to spawn a pool, if cache if true the method will spawn only if cached entry is different @@ -1041,16 +1040,18 @@ void PoolMgr::SpawnPool(uint32 pool_id, uint32 db_guid) template<> void PoolMgr::SpawnPool(uint32 pool_id, uint32 sub_pool_id) { - if (!mPoolPoolGroups[pool_id].isEmpty()) - mPoolPoolGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, sub_pool_id); + auto it = mPoolPoolGroups.find(pool_id); + if (it != mPoolPoolGroups.end() && !it->second.isEmpty()) + it->second.SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, sub_pool_id); } // Call to spawn a pool template<> void PoolMgr::SpawnPool(uint32 pool_id, uint32 quest_id) { - if (!mPoolQuestGroups[pool_id].isEmpty()) - mPoolQuestGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, quest_id); + auto it = mPoolQuestGroups.find(pool_id); + if (it != mPoolQuestGroups.end() && !it->second.isEmpty()) + it->second.SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, quest_id); } void PoolMgr::SpawnPool(uint32 pool_id) @@ -1064,27 +1065,52 @@ void PoolMgr::SpawnPool(uint32 pool_id) // Call to despawn a pool, all gameobjects/creatures in this pool are removed void PoolMgr::DespawnPool(uint32 pool_id) { - if (!mPoolCreatureGroups[pool_id].isEmpty()) - mPoolCreatureGroups[pool_id].DespawnObject(mSpawnedData); - - if (!mPoolGameobjectGroups[pool_id].isEmpty()) - mPoolGameobjectGroups[pool_id].DespawnObject(mSpawnedData); - - if (!mPoolPoolGroups[pool_id].isEmpty()) - mPoolPoolGroups[pool_id].DespawnObject(mSpawnedData); - - if (!mPoolQuestGroups[pool_id].isEmpty()) - mPoolQuestGroups[pool_id].DespawnObject(mSpawnedData); + { + auto it = mPoolCreatureGroups.find(pool_id); + if (it != mPoolCreatureGroups.end() && !it->second.isEmpty()) + it->second.DespawnObject(mSpawnedData); + } + { + auto it = mPoolGameobjectGroups.find(pool_id); + if (it != mPoolGameobjectGroups.end() && !it->second.isEmpty()) + it->second.DespawnObject(mSpawnedData); + } + { + auto it = mPoolPoolGroups.find(pool_id); + if (it != mPoolPoolGroups.end() && !it->second.isEmpty()) + it->second.DespawnObject(mSpawnedData); + } + { + auto it = mPoolQuestGroups.find(pool_id); + if (it != mPoolQuestGroups.end() && !it->second.isEmpty()) + it->second.DespawnObject(mSpawnedData); + } } // Method that check chance integrity of the creatures and gameobjects in this pool bool PoolMgr::CheckPool(uint32 pool_id) const { - return pool_id <= max_pool_id && - mPoolGameobjectGroups[pool_id].CheckPool() && - mPoolCreatureGroups[pool_id].CheckPool() && - mPoolPoolGroups[pool_id].CheckPool() && - mPoolQuestGroups[pool_id].CheckPool(); + { + auto it = mPoolGameobjectGroups.find(pool_id); + if (it != mPoolGameobjectGroups.end() && !it->second.CheckPool()) + return false; + } + { + auto it = mPoolCreatureGroups.find(pool_id); + if (it != mPoolCreatureGroups.end() && !it->second.CheckPool()) + return false; + } + { + auto it = mPoolPoolGroups.find(pool_id); + if (it != mPoolPoolGroups.end() && !it->second.CheckPool()) + return false; + } + { + auto it = mPoolQuestGroups.find(pool_id); + if (it != mPoolQuestGroups.end() && !it->second.CheckPool()) + return false; + } + return true; } // Call to update the pool when a gameobject/creature part of pool [pool_id] is ready to respawn diff --git a/src/server/game/Pools/PoolMgr.h b/src/server/game/Pools/PoolMgr.h index bdb71978b..546a08d22 100644 --- a/src/server/game/Pools/PoolMgr.h +++ b/src/server/game/Pools/PoolMgr.h @@ -129,12 +129,11 @@ class PoolMgr template void SpawnPool(uint32 pool_id, uint32 db_guid_or_pool_id); - uint32 max_pool_id; - typedef std::vector PoolTemplateDataMap; - typedef std::vector > PoolGroupCreatureMap; - typedef std::vector > PoolGroupGameObjectMap; - typedef std::vector > PoolGroupPoolMap; - typedef std::vector > PoolGroupQuestMap; + typedef std::unordered_map PoolTemplateDataMap; + typedef std::unordered_map> PoolGroupCreatureMap; + typedef std::unordered_map> PoolGroupGameObjectMap; + typedef std::unordered_map> PoolGroupPoolMap; + typedef std::unordered_map> PoolGroupQuestMap; typedef std::pair SearchPair; typedef std::map SearchMap;