Files
mod-playerbots/src/PlayerbotMgr.h
Alex Dcnh 966bf1d6af 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
2025-08-08 20:36:03 +02:00

153 lines
5.6 KiB
C++

/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it
* and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_PLAYERBOTMGR_H
#define _PLAYERBOT_PLAYERBOTMGR_H
#include "Common.h"
#include "ObjectGuid.h"
#include "Player.h"
#include "PlayerbotAIBase.h"
#include "QueryHolder.h"
#include "QueryResult.h"
#include <shared_mutex> // removes a long-standing crash (0xC0000005 ACCESS_VIOLATION)
class ChatHandler;
class PlayerbotAI;
class PlayerbotLoginQueryHolder;
class WorldPacket;
typedef std::map<ObjectGuid, Player*> PlayerBotMap;
typedef std::map<std::string, std::set<std::string> > PlayerBotErrorMap;
class PlayerbotHolder : public PlayerbotAIBase
{
public:
PlayerbotHolder();
virtual ~PlayerbotHolder(){};
void AddPlayerBot(ObjectGuid guid, uint32 masterAccountId);
bool IsAccountLinked(uint32 accountId, uint32 masterAccountId);
void HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder const& holder);
void LogoutPlayerBot(ObjectGuid guid);
void DisablePlayerBot(ObjectGuid guid);
void RemoveFromPlayerbotsMap(ObjectGuid guid);
Player* GetPlayerBot(ObjectGuid guid) const;
Player* GetPlayerBot(ObjectGuid::LowType lowGuid) const;
PlayerBotMap::const_iterator GetPlayerBotsBegin() const { return playerBots.begin(); }
PlayerBotMap::const_iterator GetPlayerBotsEnd() const { return playerBots.end(); }
void UpdateAIInternal([[maybe_unused]] uint32 elapsed, [[maybe_unused]] bool minimal = false) override{};
void UpdateSessions();
void HandleBotPackets(WorldSession* session);
void LogoutAllBots();
void OnBotLogin(Player* const bot);
std::vector<std::string> HandlePlayerbotCommand(char const* args, Player* master = nullptr);
std::string const ProcessBotCommand(std::string const cmd, ObjectGuid guid, ObjectGuid masterguid, bool admin,
uint32 masterAccountId, uint32 masterGuildId);
uint32 GetAccountId(std::string const name);
uint32 GetAccountId(ObjectGuid guid);
std::string const ListBots(Player* master);
std::string const LookupBots(Player* master);
uint32 GetPlayerbotsCount() { return playerBots.size(); }
uint32 GetPlayerbotsCountByClass(uint32 cls);
protected:
virtual void OnBotLoginInternal(Player* const bot) = 0;
PlayerBotMap playerBots;
std::unordered_set<ObjectGuid> botLoading;
};
class PlayerbotMgr : public PlayerbotHolder
{
public:
PlayerbotMgr(Player* const master);
virtual ~PlayerbotMgr();
static bool HandlePlayerbotMgrCommand(ChatHandler* handler, char const* args);
void HandleMasterIncomingPacket(WorldPacket const& packet);
void HandleMasterOutgoingPacket(WorldPacket const& packet);
void HandleCommand(uint32 type, std::string const text);
void OnPlayerLogin(Player* player);
void CancelLogout();
void UpdateAIInternal(uint32 elapsed, bool minimal = false) override;
void TellError(std::string const botName, std::string const text);
Player* GetMaster() const { return master; };
void SaveToDB();
void HandleSetSecurityKeyCommand(Player* player, const std::string& key);
void HandleLinkAccountCommand(Player* player, const std::string& accountName, const std::string& key);
void HandleViewLinkedAccountsCommand(Player* player);
void HandleUnlinkAccountCommand(Player* player, const std::string& accountName);
protected:
void OnBotLoginInternal(Player* const bot) override;
void CheckTellErrors(uint32 elapsed);
private:
Player* const master;
PlayerBotErrorMap errors;
time_t lastErrorTell;
};
class PlayerbotsMgr
{
public:
PlayerbotsMgr() {}
~PlayerbotsMgr() {}
static PlayerbotsMgr* instance()
{
static PlayerbotsMgr instance;
return &instance;
}
void AddPlayerbotData(Player* player, bool isBotAI);
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