diff options
author | Shauren <shauren.trinity@gmail.com> | 2021-10-12 16:09:47 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2021-10-12 16:09:47 +0200 |
commit | b6b46924f682bd3d00e28c606c1a7f7054478f72 (patch) | |
tree | ddb9b1c88b5121b5bc17c8366a95dfcbc0eb1cb5 /src | |
parent | 6d9ce8e8baa100ecc7650d0ae56037c131bab2e0 (diff) |
Core/Scripts: Make ObjectMgr::LoadScriptNames safe to call multiple times
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 71 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.h | 19 | ||||
-rw-r--r-- | src/server/game/Scripting/ScriptMgr.cpp | 4 |
3 files changed, 71 insertions, 23 deletions
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index e1391f9b3e5..b033d6b7896 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -9492,13 +9492,60 @@ bool ObjectMgr::IsVendorItemValid(uint32 vendor_entry, VendorItem const& vItem, return true; } +void ObjectMgr::ScriptNameContainer::reserve(size_t capacity) +{ + IndexToName.reserve(capacity); +} + +void ObjectMgr::ScriptNameContainer::insert(std::string&& scriptName) +{ + auto insertResult = NameToIndex.insert({ std::move(scriptName), NameToIndex.size() }); + if (insertResult.second) + IndexToName.push_back(insertResult.first); +} + +size_t ObjectMgr::ScriptNameContainer::size() const +{ + return IndexToName.size(); +} + +std::string const& ObjectMgr::ScriptNameContainer::operator[](size_t index) const +{ + static std::string const empty; + return index < IndexToName.size() ? IndexToName[index]->first : empty; +} + +uint32 ObjectMgr::ScriptNameContainer::operator[](std::string const& name) const +{ + // assume "" is the first element + if (name.empty()) + return 0; + + if (uint32 const* id = Trinity::Containers::MapGetValuePtr(NameToIndex, name)) + return *id; + + return 0; +} + +std::unordered_set<std::string> ObjectMgr::ScriptNameContainer::GetAllScriptNames() const +{ + std::unordered_set<std::string> scriptNames; + std::transform(NameToIndex.begin(), NameToIndex.end(), std::inserter(scriptNames, scriptNames.end()), + [](std::pair<std::string const, uint32> const& pair) + { + return pair.first; + }); + + return scriptNames; +} + void ObjectMgr::LoadScriptNames() { uint32 oldMSTime = getMSTime(); // We insert an empty placeholder here so we can use the // script id 0 as dummy for "no script found". - _scriptNamesStore.emplace_back(""); + _scriptNamesStore.insert(""); QueryResult result = WorldDatabase.Query( "SELECT DISTINCT(ScriptName) FROM battleground_template WHERE ScriptName <> '' " @@ -9547,38 +9594,26 @@ void ObjectMgr::LoadScriptNames() do { - _scriptNamesStore.push_back((*result)[0].GetString()); + _scriptNamesStore.insert((*result)[0].GetString()); } while (result->NextRow()); - std::sort(_scriptNamesStore.begin(), _scriptNamesStore.end()); - TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " ScriptNames in %u ms", _scriptNamesStore.size(), GetMSTimeDiffToNow(oldMSTime)); } -ObjectMgr::ScriptNameContainer const& ObjectMgr::GetAllScriptNames() const +std::unordered_set<std::string> ObjectMgr::GetAllScriptNames() const { - return _scriptNamesStore; + return _scriptNamesStore.GetAllScriptNames(); } std::string const& ObjectMgr::GetScriptName(uint32 id) const { - static std::string const empty = ""; - return (id < _scriptNamesStore.size()) ? _scriptNamesStore[id] : empty; + return _scriptNamesStore[id]; } uint32 ObjectMgr::GetScriptId(std::string const& name) { - // use binary search to find the script name in the sorted vector - // assume "" is the first element - if (name.empty()) - return 0; - - ScriptNameContainer::const_iterator itr = std::lower_bound(_scriptNamesStore.begin(), _scriptNamesStore.end(), name); - if (itr == _scriptNamesStore.end() || *itr != name) - return 0; - - return uint32(itr - _scriptNamesStore.begin()); + return _scriptNamesStore[name]; } CreatureBaseStats const* ObjectMgr::GetCreatureBaseStats(uint8 level, uint8 unitClass) diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 5f0614bf1af..b555dd2fa52 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -1032,7 +1032,22 @@ class TC_GAME_API ObjectMgr typedef std::unordered_map<uint32, PointOfInterest> PointOfInterestContainer; - typedef std::vector<std::string> ScriptNameContainer; + class ScriptNameContainer + { + using NameMap = std::map<std::string, uint32>; + + NameMap NameToIndex; + std::vector<NameMap::const_iterator> IndexToName; + + public: + void reserve(size_t capacity); + void insert(std::string&& scriptName); + size_t size() const; + std::string const& operator[](size_t index) const; + uint32 operator[](std::string const& name) const; + + std::unordered_set<std::string> GetAllScriptNames() const; + }; typedef std::map<uint32, uint32> CharacterConversionMap; @@ -1588,7 +1603,7 @@ class TC_GAME_API ObjectMgr bool IsVendorItemValid(uint32 vendor_entry, VendorItem const& vItem, Player* player = nullptr, std::set<uint32>* skip_vendors = nullptr, uint32 ORnpcflag = 0) const; void LoadScriptNames(); - ScriptNameContainer const& GetAllScriptNames() const; + std::unordered_set<std::string> GetAllScriptNames() const; std::string const& GetScriptName(uint32 id) const; uint32 GetScriptId(std::string const& name); diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index fc7ac25b3da..f77b93c0d5e 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -1165,9 +1165,7 @@ void ScriptMgr::Initialize() sScriptMgr->SwapScriptContext(true); // Print unused script names. - std::unordered_set<std::string> unusedScriptNames( - sObjectMgr->GetAllScriptNames().begin(), - sObjectMgr->GetAllScriptNames().end()); + std::unordered_set<std::string> unusedScriptNames = sObjectMgr->GetAllScriptNames(); // Remove the used scripts from the given container. sScriptRegistryCompositum->RemoveUsedScriptsFromContainer(unusedScriptNames); |