mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
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:
@@ -1745,36 +1745,53 @@ PlayerbotAI* PlayerbotsMgr::GetPlayerbotAI(Player* player)
|
|||||||
// return nullptr;
|
// return nullptr;
|
||||||
|
|
||||||
// removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
|
// removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
|
||||||
if (!sPlayerbotAIConfig->enabled || !player)
|
if (!player || !sPlayerbotAIConfig->enabled)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
{ // protected read
|
// First read the GUID into a local variable, but ONLY after the check!
|
||||||
std::shared_lock lock(_aiMutex);
|
ObjectGuid guid = player->GetGUID(); // <-- OK here, we know that player != nullptr
|
||||||
auto itr = _playerbotsAIMap.find(player->GetGUID());
|
{
|
||||||
if (itr != _playerbotsAIMap.end() && itr->second->IsBotAI())
|
std::shared_lock rlock(_aiMutex);
|
||||||
return reinterpret_cast<PlayerbotAI*>(itr->second);
|
auto it = _playerbotsAIMap.find(guid);
|
||||||
|
if (it != _playerbotsAIMap.end() && it->second->IsBotAI())
|
||||||
|
return static_cast<PlayerbotAI*>(it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
// does the player still exist?
|
// Transient state: NEVER break the master ⇄ bots relationship here.
|
||||||
if (!ObjectAccessor::FindPlayer(player->GetGUID()))
|
if (!ObjectAccessor::FindPlayer(guid))
|
||||||
RemovePlayerbotAI(player->GetGUID()); // orphaned AI -> cleanup
|
{
|
||||||
|
RemovePlayerbotAI(guid, /*removeMgrEntry=*/false);
|
||||||
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
|
// 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;
|
delete it->second;
|
||||||
_playerbotsAIMap.erase(itr);
|
_playerbotsAIMap.erase(it);
|
||||||
LOG_DEBUG("playerbots", "Removed stale AI entry for GUID {}", static_cast<uint64>(guid.GetRawValue()));
|
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)
|
PlayerbotMgr* PlayerbotsMgr::GetPlayerbotMgr(Player* player)
|
||||||
|
|||||||
@@ -115,7 +115,11 @@ public:
|
|||||||
void RemovePlayerBotData(ObjectGuid const& guid, bool is_AI);
|
void RemovePlayerBotData(ObjectGuid const& guid, bool is_AI);
|
||||||
|
|
||||||
PlayerbotAI* GetPlayerbotAI(Player* player);
|
PlayerbotAI* GetPlayerbotAI(Player* player);
|
||||||
void RemovePlayerbotAI(ObjectGuid const& guid); // removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
|
PlayerbotAI* GetPlayerbotAIByGuid(ObjectGuid guid); // removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
|
||||||
|
// void RemovePlayerbotAI(ObjectGuid const& guid); // removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
|
||||||
|
// removeMgrEntry = true => "hard" purge (AI + manager relation), for real logouts
|
||||||
|
// removeMgrEntry = false => "soft" purge (AI only), for detected "stale" cases
|
||||||
|
void RemovePlayerbotAI(ObjectGuid const& guid, bool removeMgrEntry = true);
|
||||||
PlayerbotMgr* GetPlayerbotMgr(Player* player);
|
PlayerbotMgr* GetPlayerbotMgr(Player* player);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -126,4 +130,23 @@ private:
|
|||||||
|
|
||||||
#define sPlayerbotsMgr PlayerbotsMgr::instance()
|
#define sPlayerbotsMgr PlayerbotsMgr::instance()
|
||||||
|
|
||||||
|
// Temporary addition If it keeps crashing, we will use them.
|
||||||
|
// Like
|
||||||
|
// BEFORE : PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
|
||||||
|
// AFTER (safe) : PlayerbotAI* botAI = GET_PLAYERBOT_AI_SAFE(bot);
|
||||||
|
// BEFORE : if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player)) { ... }
|
||||||
|
// AFTER (safe) : if (PlayerbotAI* botAI = GET_PLAYERBOT_AI_SAFE(player)) { ... }
|
||||||
|
// --- SAFE helpers (append to PlayerbotMgr.h) ---
|
||||||
|
inline PlayerbotAI* GET_PLAYERBOT_AI_SAFE(Player* p)
|
||||||
|
{
|
||||||
|
// Avoid any dereference during transient states (nullptr, teleport, flight, etc.)
|
||||||
|
return p ? sPlayerbotsMgr->GetPlayerbotAI(p) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PlayerbotMgr* GET_PLAYERBOT_MGR_SAFE(Player* p)
|
||||||
|
{
|
||||||
|
return p ? sPlayerbotsMgr->GetPlayerbotMgr(p) : nullptr;
|
||||||
|
}
|
||||||
|
// --- end SAFE helpers ---
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user