aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Cache/CharacterCache.cpp16
-rw-r--r--src/server/game/Cache/CharacterCache.h2
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp8
-rw-r--r--src/server/game/Server/WorldSession.h1
4 files changed, 26 insertions, 1 deletions
diff --git a/src/server/game/Cache/CharacterCache.cpp b/src/server/game/Cache/CharacterCache.cpp
index da119fc6cba..1bc9a4905a8 100644
--- a/src/server/game/Cache/CharacterCache.cpp
+++ b/src/server/game/Cache/CharacterCache.cpp
@@ -29,6 +29,7 @@ namespace
{
std::unordered_map<ObjectGuid, CharacterCacheEntry> _characterCacheStore;
std::unordered_map<std::string, CharacterCacheEntry*> _characterCacheByNameStore;
+ std::unordered_set<std::string> _characterCreationNameStore;
}
CharacterCache::CharacterCache()
@@ -201,6 +202,21 @@ CharacterCacheEntry const* CharacterCache::GetCharacterCacheByName(std::string c
return nullptr;
}
+std::shared_ptr<std::string const> CharacterCache::TryCreateCharacterWithName(std::string const& name) const
+{
+ auto itr = _characterCacheByNameStore.find(name);
+ if (itr != _characterCacheByNameStore.end())
+ return nullptr;
+
+ auto insertResult = _characterCreationNameStore.insert(name);
+ if (!insertResult.second)
+ return nullptr;
+
+ // shared_ptr with custom deleter that erases its held value from _characterCreationNameStore instead of deleting it (points to value inside the container)
+ return std::shared_ptr<std::string const>(&(*insertResult.first),
+ [this](std::string const* storedName) { _characterCreationNameStore.erase(*storedName); });
+}
+
ObjectGuid CharacterCache::GetCharacterGuidByName(std::string const& name) const
{
auto itr = _characterCacheByNameStore.find(name);
diff --git a/src/server/game/Cache/CharacterCache.h b/src/server/game/Cache/CharacterCache.h
index ed3239410c4..151b6dcba9e 100644
--- a/src/server/game/Cache/CharacterCache.h
+++ b/src/server/game/Cache/CharacterCache.h
@@ -55,7 +55,7 @@ class TC_GAME_API CharacterCache
bool HasCharacterCacheEntry(ObjectGuid const& guid) const;
CharacterCacheEntry const* GetCharacterCacheByGuid(ObjectGuid const& guid) const;
CharacterCacheEntry const* GetCharacterCacheByName(std::string const& name) const;
-
+ std::shared_ptr<std::string const> TryCreateCharacterWithName(std::string const& name) const;
ObjectGuid GetCharacterGuidByName(std::string const& name) const;
bool GetCharacterNameByGuid(ObjectGuid guid, std::string& name) const;
uint32 GetCharacterTeamByGuid(ObjectGuid guid) const;
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index ec4873b35ed..5e6534459e0 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -397,6 +397,14 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
}
}
+ // Reserve the name for the duration of callback chain
+ createInfo->NameToken = sCharacterCache->TryCreateCharacterWithName(createInfo->Name);
+ if (!createInfo->NameToken)
+ {
+ SendCharCreate(CHAR_CREATE_NAME_IN_USE);
+ return;
+ }
+
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME);
stmt->setString(0, createInfo->Name);
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 03e80c7e69e..ac5f4b981b0 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -220,6 +220,7 @@ class CharacterCreateInfo
/// Server side data
uint8 CharCount = 0;
+ std::shared_ptr<std::string const> NameToken;
};
struct CharacterRenameInfo