Correct side effects of merge f5ef5bd1c2 (#1512)

* Update PlayerbotMgr.h

* Update PlayerbotMgr.cpp

* Update PlayerbotMgr.cpp

* Update PlayerbotMgr.cpp

* Update PlayerbotMgr.cpp

* Update PlayerbotMgr.cpp

* Update PlayerbotMgr.cpp

* Update PlayerbotMgr.h

* Update PlayerbotMgr.cpp

* Update PlayerbotMgr.h

* Update PlayerbotMgr.cpp

* Update PlayerbotMgr.h

* Update PlayerbotMgr.h
This commit is contained in:
Alex Dcnh
2025-08-08 20:36:03 +02:00
committed by GitHub
parent f5ef5bd1c2
commit 966bf1d6af
2 changed files with 59 additions and 19 deletions

View File

@@ -1745,36 +1745,53 @@ PlayerbotAI* PlayerbotsMgr::GetPlayerbotAI(Player* player)
// return nullptr;
// removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
if (!sPlayerbotAIConfig->enabled || !player)
if (!player || !sPlayerbotAIConfig->enabled)
return nullptr;
{ // protected read
std::shared_lock lock(_aiMutex);
auto itr = _playerbotsAIMap.find(player->GetGUID());
if (itr != _playerbotsAIMap.end() && itr->second->IsBotAI())
return reinterpret_cast<PlayerbotAI*>(itr->second);
// First read the GUID into a local variable, but ONLY after the check!
ObjectGuid guid = player->GetGUID(); // <-- OK here, we know that player != nullptr
{
std::shared_lock rlock(_aiMutex);
auto it = _playerbotsAIMap.find(guid);
if (it != _playerbotsAIMap.end() && it->second->IsBotAI())
return static_cast<PlayerbotAI*>(it->second);
}
// does the player still exist?
if (!ObjectAccessor::FindPlayer(player->GetGUID()))
RemovePlayerbotAI(player->GetGUID()); // orphaned AI -> cleanup
// Transient state: NEVER break the master ⇄ bots relationship here.
if (!ObjectAccessor::FindPlayer(guid))
{
RemovePlayerbotAI(guid, /*removeMgrEntry=*/false);
}
return nullptr;
}
// removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
void PlayerbotsMgr::RemovePlayerbotAI(ObjectGuid const& guid)
PlayerbotAI* PlayerbotsMgr::GetPlayerbotAIByGuid(ObjectGuid guid)
{
std::unique_lock lock(_aiMutex);
if (!sPlayerbotAIConfig->enabled)
return nullptr;
if (auto itr = _playerbotsAIMap.find(guid); itr != _playerbotsAIMap.end())
std::shared_lock rlock(_aiMutex);
auto it = _playerbotsAIMap.find(guid);
if (it != _playerbotsAIMap.end() && it->second->IsBotAI())
return static_cast<PlayerbotAI*>(it->second);
return nullptr;
}
void PlayerbotsMgr::RemovePlayerbotAI(ObjectGuid const& guid, bool removeMgrEntry /*= true*/)
{
std::unique_lock wlock(_aiMutex);
if (auto it = _playerbotsAIMap.find(guid); it != _playerbotsAIMap.end())
{
delete itr->second;
_playerbotsAIMap.erase(itr);
LOG_DEBUG("playerbots", "Removed stale AI entry for GUID {}", static_cast<uint64>(guid.GetRawValue()));
delete it->second;
_playerbotsAIMap.erase(it);
LOG_DEBUG("playerbots", "Removed stale AI for GUID {}",
static_cast<uint64>(guid.GetRawValue()));
}
_playerbotsMgrMap.erase(guid);
if (removeMgrEntry)
_playerbotsMgrMap.erase(guid); // we NO longer touch the relation in a "soft" purge
}
PlayerbotMgr* PlayerbotsMgr::GetPlayerbotMgr(Player* player)