[Revert] Threading leftover which belonged to other related PRs's (once green needs be merged) (#1583)

* Revert "Correct side effects of  merge f5ef5bd1c2 (#1512)"

This reverts commit 966bf1d6af.

* Revert "Fix ACCESS_VIOLATION in mod-playerbots: purge stale AIs, add thread-safety, and harden HasRealPlayerMaster (#1507)"

This reverts commit f5ef5bd1c2.
This commit is contained in:
bash
2025-08-20 20:13:45 +02:00
committed by GitHub
parent 957a60cd1d
commit c9b4cfa184
4 changed files with 14 additions and 117 deletions

View File

@@ -4124,37 +4124,15 @@ bool IsAlliance(uint8 race)
bool PlayerbotAI::HasRealPlayerMaster()
{
// if (master)
// {
// PlayerbotAI* masterBotAI = GET_PLAYERBOT_AI(master);
// return !masterBotAI || masterBotAI->IsRealPlayer();
// }
//
// return false;
// Removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
/* 1) The "master" pointer can be null if the bot was created
without a master player or if the master was just removed. */
if (!master)
return false;
/* 2) Is the master player still present in the world?
If FindPlayer fails, we invalidate "master" and stop here. */
if (!ObjectAccessor::FindPlayer(master->GetGUID()))
if (master)
{
master = nullptr; // avoids repeating the check on the next tick
return false;
PlayerbotAI* masterBotAI = GET_PLAYERBOT_AI(master);
return !masterBotAI || masterBotAI->IsRealPlayer();
}
/* 3) If the master is a bot, we check that it is itself controlled
by a real player. Otherwise, it's already a real player → true. */
if (PlayerbotAI* masterBotAI = GET_PLAYERBOT_AI(master))
return masterBotAI->IsRealPlayer(); // bot controlled by a player?
return true; // master = real player
return false;
}
bool PlayerbotAI::HasActivePlayerMaster() { return master && !GET_PLAYERBOT_AI(master); }
bool PlayerbotAI::IsAlt() { return HasRealPlayerMaster() && !sRandomPlayerbotMgr->IsRandomBot(bot); }

View File

@@ -38,8 +38,6 @@
#include "WorldSessionMgr.h"
#include "DatabaseEnv.h" // Added for gender choice
#include <algorithm> // Added for gender choice
#include "Log.h" // removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
#include <shared_mutex> // removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
class BotInitGuard
{
@@ -1728,72 +1726,23 @@ void PlayerbotsMgr::RemovePlayerBotData(ObjectGuid const& guid, bool is_AI)
PlayerbotAI* PlayerbotsMgr::GetPlayerbotAI(Player* player)
{
// if (!(sPlayerbotAIConfig->enabled) || !player)
// {
if (!(sPlayerbotAIConfig->enabled) || !player)
{
return nullptr;
}
// if (player->GetSession()->isLogingOut() || player->IsDuringRemoveFromWorld()) {
// return nullptr;
// }
// // if (player->GetSession()->isLogingOut() || player->IsDuringRemoveFromWorld()) {
// // return nullptr;
// // }
// auto itr = _playerbotsAIMap.find(player->GetGUID());
// if (itr != _playerbotsAIMap.end())
// {
// if (itr->second->IsBotAI())
// return reinterpret_cast<PlayerbotAI*>(itr->second);
// }
//
// return nullptr;
// removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
if (!player || !sPlayerbotAIConfig->enabled)
return nullptr;
// First read the GUID into a local variable, but ONLY after the check!
ObjectGuid guid = player->GetGUID(); // <-- OK here, we know that player != nullptr
auto itr = _playerbotsAIMap.find(player->GetGUID());
if (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);
if (itr->second->IsBotAI())
return reinterpret_cast<PlayerbotAI*>(itr->second);
}
// 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)
PlayerbotAI* PlayerbotsMgr::GetPlayerbotAIByGuid(ObjectGuid guid)
{
if (!sPlayerbotAIConfig->enabled)
return nullptr;
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 it->second;
_playerbotsAIMap.erase(it);
LOG_DEBUG("playerbots", "Removed stale AI for GUID {}",
static_cast<uint64>(guid.GetRawValue()));
}
if (removeMgrEntry)
_playerbotsMgrMap.erase(guid); // we NO longer touch the relation in a "soft" purge
}
PlayerbotMgr* PlayerbotsMgr::GetPlayerbotMgr(Player* player)
{
if (!(sPlayerbotAIConfig->enabled) || !player)

View File

@@ -12,7 +12,6 @@
#include "PlayerbotAIBase.h"
#include "QueryHolder.h"
#include "QueryResult.h"
#include <shared_mutex> // removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
class ChatHandler;
class PlayerbotAI;
@@ -115,38 +114,13 @@ public:
void RemovePlayerBotData(ObjectGuid const& guid, bool is_AI);
PlayerbotAI* GetPlayerbotAI(Player* player);
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);
private:
std::unordered_map<ObjectGuid, PlayerbotAIBase*> _playerbotsAIMap;
std::unordered_map<ObjectGuid, PlayerbotAIBase*> _playerbotsMgrMap;
mutable std::shared_mutex _aiMutex; // removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
};
#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

View File

@@ -377,10 +377,6 @@ public:
void OnPlayerbotLogout(Player* player) override
{
// immediate purge of the bot's AI upon disconnection
if (player && player->GetSession()->IsBot())
sPlayerbotsMgr->RemovePlayerbotAI(player->GetGUID()); // removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
{
PlayerbotAI* botAI = GET_PLAYERBOT_AI(player);