Always allow addclass bots login and init (#946)

* Change the way to check addclass bots and allow adding them by characters name

* Always addclass bots login and init

* Comments and message
This commit is contained in:
Yunfan Li
2025-02-05 12:56:37 +08:00
committed by GitHub
parent 308c0b437e
commit 14bdc0ec5a
4 changed files with 63 additions and 68 deletions

View File

@@ -39,17 +39,16 @@ private:
uint32 masterAccountId; uint32 masterAccountId;
PlayerbotHolder* playerbotHolder; PlayerbotHolder* playerbotHolder;
public: public:
PlayerbotLoginQueryHolder(PlayerbotHolder* playerbotHolder, uint32 masterAccount, uint32 accountId, ObjectGuid guid, bool byAddClass) PlayerbotLoginQueryHolder(PlayerbotHolder* playerbotHolder, uint32 masterAccount, uint32 accountId, ObjectGuid guid)
: LoginQueryHolder(accountId, guid), masterAccountId(masterAccount), playerbotHolder(playerbotHolder), byAddClass(byAddClass) : LoginQueryHolder(accountId, guid), masterAccountId(masterAccount), playerbotHolder(playerbotHolder)
{ {
} }
uint32 GetMasterAccountId() const { return masterAccountId; } uint32 GetMasterAccountId() const { return masterAccountId; }
PlayerbotHolder* GetPlayerbotHolder() { return playerbotHolder; } PlayerbotHolder* GetPlayerbotHolder() { return playerbotHolder; }
bool byAddClass;
}; };
void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId, bool byAddClass) void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId)
{ {
// bot is loading // bot is loading
if (botLoading.find(playerGuid) != botLoading.end()) if (botLoading.find(playerGuid) != botLoading.end())
@@ -71,12 +70,13 @@ void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId
bool sameAccount = sPlayerbotAIConfig->allowAccountBots && accountId == masterAccountId; bool sameAccount = sPlayerbotAIConfig->allowAccountBots && accountId == masterAccountId;
Guild* guild = masterPlayer ? sGuildMgr->GetGuildById(masterPlayer->GetGuildId()) : nullptr; Guild* guild = masterPlayer ? sGuildMgr->GetGuildById(masterPlayer->GetGuildId()) : nullptr;
bool sameGuild = sPlayerbotAIConfig->allowGuildBots && guild && guild->GetMember(playerGuid); bool sameGuild = sPlayerbotAIConfig->allowGuildBots && guild && guild->GetMember(playerGuid);
bool addClassBot = sRandomPlayerbotMgr->IsAddclassBot(playerGuid.GetCounter());
bool allowed = true; bool allowed = true;
std::ostringstream out; std::ostringstream out;
std::string botName; std::string botName;
sCharacterCache->GetCharacterNameByGuid(playerGuid, botName); sCharacterCache->GetCharacterNameByGuid(playerGuid, botName);
if (!isRndbot && !sameAccount && !sameGuild && !byAddClass) if (!isRndbot && !sameAccount && !sameGuild && !addClassBot)
{ {
allowed = false; allowed = false;
out << "Failure: You are not allowed to control bot " << botName.c_str(); out << "Failure: You are not allowed to control bot " << botName.c_str();
@@ -106,7 +106,7 @@ void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId
return; return;
} }
std::shared_ptr<PlayerbotLoginQueryHolder> holder = std::shared_ptr<PlayerbotLoginQueryHolder> holder =
std::make_shared<PlayerbotLoginQueryHolder>(this, masterAccountId, accountId, playerGuid, byAddClass); std::make_shared<PlayerbotLoginQueryHolder>(this, masterAccountId, accountId, playerGuid);
if (!holder->Initialize()) if (!holder->Initialize())
{ {
return; return;
@@ -131,7 +131,6 @@ void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId
void PlayerbotHolder::HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder const& holder) void PlayerbotHolder::HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder const& holder)
{ {
uint32 botAccountId = holder.GetAccountId(); uint32 botAccountId = holder.GetAccountId();
bool byAddClass = holder.byAddClass;
// At login DBC locale should be what the server is set to use by default (as spells etc are hardcoded to ENUS this // At login DBC locale should be what the server is set to use by default (as spells etc are hardcoded to ENUS this
// allows channels to work as intended) // allows channels to work as intended)
WorldSession* botSession = new WorldSession(botAccountId, "", nullptr, SEC_PLAYER, EXPANSION_WRATH_OF_THE_LICH_KING, WorldSession* botSession = new WorldSession(botAccountId, "", nullptr, SEC_PLAYER, EXPANSION_WRATH_OF_THE_LICH_KING,
@@ -161,7 +160,7 @@ void PlayerbotHolder::HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder con
} }
sRandomPlayerbotMgr->OnPlayerLogin(bot); sRandomPlayerbotMgr->OnPlayerLogin(bot);
OnBotLogin(bot, byAddClass); OnBotLogin(bot);
botLoading.erase(holder.GetGuid()); botLoading.erase(holder.GetGuid());
} }
@@ -404,8 +403,6 @@ void PlayerbotHolder::DisablePlayerBot(ObjectGuid guid)
void PlayerbotHolder::RemoveFromPlayerbotsMap(ObjectGuid guid) void PlayerbotHolder::RemoveFromPlayerbotsMap(ObjectGuid guid)
{ {
playerBots.erase(guid); playerBots.erase(guid);
if (addClassBots.find(guid) != addClassBots.end())
addClassBots.erase(guid);
} }
Player* PlayerbotHolder::GetPlayerBot(ObjectGuid playerGuid) const Player* PlayerbotHolder::GetPlayerBot(ObjectGuid playerGuid) const
@@ -421,7 +418,7 @@ Player* PlayerbotHolder::GetPlayerBot(ObjectGuid::LowType lowGuid) const
return (it == playerBots.end()) ? 0 : it->second; return (it == playerBots.end()) ? 0 : it->second;
} }
void PlayerbotHolder::OnBotLogin(Player* const bot, bool byAddClass) void PlayerbotHolder::OnBotLogin(Player* const bot)
{ {
// Prevent duplicate login // Prevent duplicate login
if (playerBots.find(bot->GetGUID()) != playerBots.end()) if (playerBots.find(bot->GetGUID()) != playerBots.end())
@@ -431,8 +428,6 @@ void PlayerbotHolder::OnBotLogin(Player* const bot, bool byAddClass)
sPlayerbotsMgr->AddPlayerbotData(bot, true); sPlayerbotsMgr->AddPlayerbotData(bot, true);
playerBots[bot->GetGUID()] = bot; playerBots[bot->GetGUID()] = bot;
if (byAddClass)
addClassBots.insert(bot->GetGUID());
OnBotLoginInternal(bot); OnBotLoginInternal(bot);
@@ -482,10 +477,6 @@ void PlayerbotHolder::OnBotLogin(Player* const bot, bool byAddClass)
if (!groupValid) if (!groupValid)
{ {
bot->RemoveFromGroup(); bot->RemoveFromGroup();
// WorldPacket p;
// std::string const member = bot->GetName();
// p << uint32(PARTY_OP_LEAVE) << member << uint32(0);
// bot->GetSession()->HandleGroupDisbandOpcode(p);
} }
} }
@@ -557,7 +548,8 @@ void PlayerbotHolder::OnBotLogin(Player* const bot, bool byAddClass)
} }
bot->SaveToDB(false, false); bot->SaveToDB(false, false);
if (byAddClass && master && isRandomAccount && master->GetLevel() < bot->GetLevel()) bool addClassBot = sRandomPlayerbotMgr->IsAddclassBot(bot->GetGUID().GetCounter());
if (addClassBot && master && isRandomAccount && master->GetLevel() < bot->GetLevel())
{ {
// PlayerbotFactory factory(bot, master->GetLevel()); // PlayerbotFactory factory(bot, master->GetLevel());
// factory.Randomize(false); // factory.Randomize(false);
@@ -673,21 +665,10 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje
if (!bot) if (!bot)
return "bot not found"; return "bot not found";
bool addClassBot = true; bool addClassBot = sRandomPlayerbotMgr->IsAddclassBot(guid.GetCounter());
if (!isRandomAccount || isRandomBot)
{
addClassBot = false;
}
if (Player* master = GET_PLAYERBOT_AI(bot)->GetMaster())
{
PlayerbotMgr* masterMgr = GET_PLAYERBOT_MGR(master);
if (masterMgr && masterMgr->addClassBots.find(guid) == masterMgr->addClassBots.end())
addClassBot = false;
}
if (!addClassBot) if (!addClassBot)
return "ERROR: You can not use this command on non-addclass random bot."; return "ERROR: You can not use this command on non-addclass bot.";
if (!admin) if (!admin)
{ {
@@ -1066,15 +1047,16 @@ std::vector<std::string> PlayerbotHolder::HandlePlayerbotCommand(char const* arg
return messages; return messages;
} }
uint8 teamId = master->GetTeamId(true); uint8 teamId = master->GetTeamId(true);
std::vector<ObjectGuid> &guidCache = sRandomPlayerbotMgr->addclassCache[RandomPlayerbotMgr::GetTeamClassIdx(teamId == TEAM_ALLIANCE, claz)]; const std::unordered_set<ObjectGuid> &guidCache = sRandomPlayerbotMgr->addclassCache[RandomPlayerbotMgr::GetTeamClassIdx(teamId == TEAM_ALLIANCE, claz)];
for (size_t i = 0; i < guidCache.size(); i++) for (const ObjectGuid &guid: guidCache)
{ {
ObjectGuid guid = guidCache[i];
if (botLoading.find(guid) != botLoading.end()) if (botLoading.find(guid) != botLoading.end())
continue; continue;
if (ObjectAccessor::FindConnectedPlayer(guid)) if (ObjectAccessor::FindConnectedPlayer(guid))
continue; continue;
AddPlayerBot(guid, master->GetSession()->GetAccountId(), true); if (sCharacterCache->GetCharacterGuildIdByGuid(guid))
continue;
AddPlayerBot(guid, master->GetSession()->GetAccountId());
messages.push_back("Add class " + std::string(charname)); messages.push_back("Add class " + std::string(charname));
return messages; return messages;
} }

View File

@@ -27,7 +27,7 @@ public:
PlayerbotHolder(); PlayerbotHolder();
virtual ~PlayerbotHolder(){}; virtual ~PlayerbotHolder(){};
void AddPlayerBot(ObjectGuid guid, uint32 masterAccountId, bool byAddClass = false); void AddPlayerBot(ObjectGuid guid, uint32 masterAccountId);
void HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder const& holder); void HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder const& holder);
void LogoutPlayerBot(ObjectGuid guid); void LogoutPlayerBot(ObjectGuid guid);
@@ -43,7 +43,7 @@ public:
void HandleBotPackets(WorldSession* session); void HandleBotPackets(WorldSession* session);
void LogoutAllBots(); void LogoutAllBots();
void OnBotLogin(Player* const bot, bool byAddClass = false); void OnBotLogin(Player* const bot);
std::vector<std::string> HandlePlayerbotCommand(char const* args, Player* master = nullptr); 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, std::string const ProcessBotCommand(std::string const cmd, ObjectGuid guid, ObjectGuid masterguid, bool admin,
@@ -59,7 +59,6 @@ protected:
virtual void OnBotLoginInternal(Player* const bot) = 0; virtual void OnBotLoginInternal(Player* const bot) = 0;
PlayerBotMap playerBots; PlayerBotMap playerBots;
std::unordered_set<ObjectGuid> addClassBots;
std::unordered_set<ObjectGuid> botLoading; std::unordered_set<ObjectGuid> botLoading;
}; };

View File

@@ -1709,37 +1709,34 @@ void RandomPlayerbotMgr::PrepareTeleportCache()
void RandomPlayerbotMgr::PrepareAddclassCache() void RandomPlayerbotMgr::PrepareAddclassCache()
{ {
int32 maxAccountId = sPlayerbotAIConfig->randomBotAccounts.back(); /// @FIXME: Modifying RandomBotAccountCount may cause the original addclass bots to be converted into rndbots,
int32 minIdx = sPlayerbotAIConfig->randomBotAccounts.size() - 1 >= sPlayerbotAIConfig->addClassAccountPoolSize // which needs to be fixed by separating the two accounts in implementation
? sPlayerbotAIConfig->randomBotAccounts.size() - sPlayerbotAIConfig->addClassAccountPoolSize size_t poolSize = sPlayerbotAIConfig->addClassAccountPoolSize;
: 0; size_t start = sPlayerbotAIConfig->randomBotAccounts.size() > poolSize ? sPlayerbotAIConfig->randomBotAccounts.size() - poolSize : 0;
int32 minAccountId = sPlayerbotAIConfig->randomBotAccounts[minIdx];
if (minAccountId < 0)
{
LOG_ERROR("playerbots", "No available account for add class!");
}
int32 collected = 0; int32 collected = 0;
for (uint8 claz = CLASS_WARRIOR; claz <= CLASS_DRUID; claz++) for (size_t i = start; i < sPlayerbotAIConfig->randomBotAccounts.size(); i++)
{ {
if (claz == 10) for (uint8 claz = CLASS_WARRIOR; claz <= CLASS_DRUID; claz++)
continue;
QueryResult results = CharacterDatabase.Query(
"SELECT guid, race FROM characters "
"WHERE account >= {} AND account <= {} AND class = '{}' AND online = 0 AND "
"guid NOT IN ( SELECT guid FROM guild_member ) "
"ORDER BY account DESC",
minAccountId, maxAccountId, claz);
if (results)
{ {
do if (claz == 10)
continue;
QueryResult results = CharacterDatabase.Query(
"SELECT guid, race FROM characters "
"WHERE account = {} AND class = '{}' AND online = 0 "
"ORDER BY account DESC",
sPlayerbotAIConfig->randomBotAccounts[i], claz);
if (results)
{ {
Field* fields = results->Fetch(); do
ObjectGuid guid = ObjectGuid(HighGuid::Player, fields[0].Get<uint32>()); {
uint32 race = fields[1].Get<uint32>(); Field* fields = results->Fetch();
bool isAlliance = race == 1 || race == 3 || race == 4 || race == 7 || race == 11; ObjectGuid guid = ObjectGuid(HighGuid::Player, fields[0].Get<uint32>());
addclassCache[GetTeamClassIdx(isAlliance, claz)].push_back(guid); uint32 race = fields[1].Get<uint32>();
collected++; bool isAlliance = race == 1 || race == 3 || race == 4 || race == 7 || race == 11;
} while (results->NextRow()); addclassCache[GetTeamClassIdx(isAlliance, claz)].insert(guid);
collected++;
} while (results->NextRow());
}
} }
} }
LOG_INFO("playerbots", ">> {} characters collected for addclass command.", collected); LOG_INFO("playerbots", ">> {} characters collected for addclass command.", collected);
@@ -2113,6 +2110,22 @@ bool RandomPlayerbotMgr::IsRandomBot(ObjectGuid::LowType bot)
return false; return false;
} }
bool RandomPlayerbotMgr::IsAddclassBot(ObjectGuid::LowType bot)
{
ObjectGuid guid = ObjectGuid::Create<HighGuid::Player>(bot);
for (uint8 claz = CLASS_WARRIOR; claz <= CLASS_DRUID; claz++)
{
if (claz == 10)
continue;
for (uint8 isAlliance = 0; isAlliance <= 1; isAlliance++)
{
if (addclassCache[GetTeamClassIdx(isAlliance, claz)].find(guid) != addclassCache[GetTeamClassIdx(isAlliance, claz)].end())
return true;
}
}
return false;
}
void RandomPlayerbotMgr::GetBots() void RandomPlayerbotMgr::GetBots()
{ {
if (!currentBots.empty()) if (!currentBots.empty())

View File

@@ -111,6 +111,7 @@ public:
static bool HandlePlayerbotConsoleCommand(ChatHandler* handler, char const* args); static bool HandlePlayerbotConsoleCommand(ChatHandler* handler, char const* args);
bool IsRandomBot(Player* bot); bool IsRandomBot(Player* bot);
bool IsRandomBot(ObjectGuid::LowType bot); bool IsRandomBot(ObjectGuid::LowType bot);
bool IsAddclassBot(ObjectGuid::LowType bot);
void Randomize(Player* bot); void Randomize(Player* bot);
void Clear(Player* bot); void Clear(Player* bot);
void RandomizeFirst(Player* bot); void RandomizeFirst(Player* bot);
@@ -172,7 +173,7 @@ public:
void PrepareAddclassCache(); void PrepareAddclassCache();
void PrepareTeleportCache(); void PrepareTeleportCache();
void Init(); void Init();
std::map<uint8, std::vector<ObjectGuid>> addclassCache; std::map<uint8, std::unordered_set<ObjectGuid>> addclassCache;
std::map<uint8, std::vector<WorldLocation>> locsPerLevelCache; std::map<uint8, std::vector<WorldLocation>> locsPerLevelCache;
std::map<uint8, std::vector<WorldLocation>> allianceStarterPerLevelCache; std::map<uint8, std::vector<WorldLocation>> allianceStarterPerLevelCache;
std::map<uint8, std::vector<WorldLocation>> hordeStarterPerLevelCache; std::map<uint8, std::vector<WorldLocation>> hordeStarterPerLevelCache;