aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2021-10-12 16:09:47 +0200
committerShauren <shauren.trinity@gmail.com>2021-10-12 16:09:47 +0200
commitb6b46924f682bd3d00e28c606c1a7f7054478f72 (patch)
treeddb9b1c88b5121b5bc17c8366a95dfcbc0eb1cb5 /src
parent6d9ce8e8baa100ecc7650d0ae56037c131bab2e0 (diff)
Core/Scripts: Make ObjectMgr::LoadScriptNames safe to call multiple times
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp71
-rw-r--r--src/server/game/Globals/ObjectMgr.h19
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp4
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);