mirror of
https://github.com/mod-playerbots/mod-playerbots.git
synced 2026-02-08 13:11:10 +00:00
Improper singletons migration to clean Meyer's singletons (cherry-pick) (#2082)
# Pull Request
- Applies the clean and corrected singletons, Meyer pattern. (cherry
picked from @SmashingQuasar )
Testing by just playing the game in various ways. Been tested by myself
@Celandriel and @SmashingQuasar
---
## Complexity & Impact
- Does this change add new decision branches?
- [x] No
- [ ] Yes (**explain below**)
- Does this change increase per-bot or per-tick processing?
- [x] No
- [ ] Yes (**describe and justify impact**)
- Could this logic scale poorly under load?
- [x] No
- [ ] Yes (**explain why**)
---
## Defaults & Configuration
- Does this change modify default bot behavior?
- [x] No
- [ ] Yes (**explain why**)
---
## AI Assistance
- Was AI assistance (e.g. ChatGPT or similar tools) used while working
on this change?
- [x] No
- [ ] Yes (**explain below**)
---
## Final Checklist
- [x] Stability is not compromised
- [x] Performance impact is understood, tested, and acceptable
- [x] Added logic complexity is justified and explained
- [x] Documentation updated if needed
---
## Notes for Reviewers
Anything that significantly improves realism at the cost of stability or
performance should be carefully discussed
before merging.
---------
Co-authored-by: Nicolas Lebacq <nicolas.cordier@outlook.com>
Co-authored-by: Keleborn <22352763+Celandriel@users.noreply.github.com>
This commit is contained in:
@@ -22,7 +22,6 @@
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DatabaseLoader.h"
|
||||
#include "GuildTaskMgr.h"
|
||||
#include "Metric.h"
|
||||
#include "PlayerScript.h"
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "PlayerbotGuildMgr.h"
|
||||
@@ -98,24 +97,24 @@ public:
|
||||
{
|
||||
if (!player->GetSession()->IsBot())
|
||||
{
|
||||
sPlayerbotsMgr->AddPlayerbotData(player, false);
|
||||
sRandomPlayerbotMgr->OnPlayerLogin(player);
|
||||
PlayerbotsMgr::instance().AddPlayerbotData(player, false);
|
||||
sRandomPlayerbotMgr.OnPlayerLogin(player);
|
||||
|
||||
// Before modifying the following messages, please make sure it does not violate the AGPLv3.0 license
|
||||
// especially if you are distributing a repack or hosting a public server
|
||||
// e.g. you can replace the URL with your own repository,
|
||||
// but it should be publicly accessible and include all modifications you've made
|
||||
if (sPlayerbotAIConfig->enabled)
|
||||
if (sPlayerbotAIConfig.enabled)
|
||||
{
|
||||
ChatHandler(player->GetSession()).SendSysMessage(
|
||||
"|cff00ff00This server runs with |cff00ccffmod-playerbots|r "
|
||||
"|cffcccccchttps://github.com/mod-playerbots/mod-playerbots|r");
|
||||
}
|
||||
|
||||
if (sPlayerbotAIConfig->enabled || sPlayerbotAIConfig->randomBotAutologin)
|
||||
if (sPlayerbotAIConfig.enabled || sPlayerbotAIConfig.randomBotAutologin)
|
||||
{
|
||||
std::string roundedTime =
|
||||
std::to_string(std::ceil((sPlayerbotAIConfig->maxRandomBots * 0.11 / 60) * 10) / 10.0);
|
||||
std::to_string(std::ceil((sPlayerbotAIConfig.maxRandomBots * 0.11 / 60) * 10) / 10.0);
|
||||
roundedTime = roundedTime.substr(0, roundedTime.find('.') + 2);
|
||||
|
||||
ChatHandler(player->GetSession()).SendSysMessage(
|
||||
@@ -125,54 +124,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool OnPlayerBeforeTeleport(Player* /*player*/, uint32 /*mapid*/, float /*x*/, float /*y*/, float /*z*/, float /*orientation*/, uint32 /*options*/, Unit* /*target*/) override
|
||||
{
|
||||
/* for now commmented out until proven its actually required
|
||||
* havent seen any proof CleanVisibilityReferences() is needed
|
||||
|
||||
// If the player is not safe to touch, do nothing
|
||||
if (!player)
|
||||
return true;
|
||||
|
||||
// If same map or not in world do nothing
|
||||
if (!player->IsInWorld() || player->GetMapId() == mapid)
|
||||
return true;
|
||||
|
||||
// If real player do nothing
|
||||
PlayerbotAI* ai = GET_PLAYERBOT_AI(player);
|
||||
if (!ai || ai->IsRealPlayer())
|
||||
return true;
|
||||
|
||||
// Cross-map bot teleport: defer visibility reference cleanup.
|
||||
// CleanVisibilityReferences() erases this bot's GUID from other objects' visibility containers.
|
||||
// This is intentionally done via the event queue (instead of directly here) because erasing
|
||||
// from other players' visibility maps inside the teleport call stack can hit unsafe re-entrancy
|
||||
// or iterator invalidation while visibility updates are in progress
|
||||
ObjectGuid guid = player->GetGUID();
|
||||
player->m_Events.AddEventAtOffset(
|
||||
[guid, mapid]()
|
||||
{
|
||||
// do nothing, if the player is not safe to touch
|
||||
Player* p = ObjectAccessor::FindPlayer(guid);
|
||||
if (!p || !p->IsInWorld() || p->IsDuringRemoveFromWorld())
|
||||
return;
|
||||
|
||||
// do nothing if we are already on the target map
|
||||
if (p->GetMapId() == mapid)
|
||||
return;
|
||||
|
||||
p->GetObjectVisibilityContainer().CleanVisibilityReferences();
|
||||
},
|
||||
Milliseconds(0));
|
||||
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnPlayerAfterUpdate(Player* player, uint32 diff) override
|
||||
{
|
||||
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player))
|
||||
PlayerbotAI* const botAI = PlayerbotsMgr::instance().GetPlayerbotAI(player);
|
||||
|
||||
if (botAI != nullptr)
|
||||
{
|
||||
botAI->UpdateAI(diff);
|
||||
}
|
||||
@@ -185,19 +141,26 @@ public:
|
||||
|
||||
bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Player* receiver) override
|
||||
{
|
||||
if (type == CHAT_MSG_WHISPER)
|
||||
if (type != CHAT_MSG_WHISPER)
|
||||
{
|
||||
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(receiver))
|
||||
{
|
||||
botAI->HandleCommand(type, msg, player);
|
||||
|
||||
// hotfix; otherwise the server will crash when whispering logout
|
||||
// https://github.com/mod-playerbots/mod-playerbots/pull/1838
|
||||
// TODO: find the root cause and solve it. (does not happen in party chat)
|
||||
if (msg == "logout")
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
PlayerbotAI* const botAI = PlayerbotsMgr::instance().GetPlayerbotAI(receiver);
|
||||
|
||||
if (botAI == nullptr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
botAI->HandleCommand(type, msg, player);
|
||||
|
||||
// hotfix; otherwise the server will crash when whispering logout
|
||||
// https://github.com/mod-playerbots/mod-playerbots/pull/1838
|
||||
// TODO: find the root cause and solve it. (does not happen in party chat)
|
||||
if (msg == "logout")
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -205,56 +168,77 @@ public:
|
||||
{
|
||||
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
|
||||
{
|
||||
if (Player* member = itr->GetSource())
|
||||
Player* const member = itr->GetSource();
|
||||
|
||||
if (member == nullptr)
|
||||
{
|
||||
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(member))
|
||||
{
|
||||
botAI->HandleCommand(type, msg, player);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
PlayerbotAI* const botAI = PlayerbotsMgr::instance().GetPlayerbotAI(member);
|
||||
|
||||
if (botAI == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
botAI->HandleCommand(type, msg, player);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Guild* guild) override
|
||||
{
|
||||
if (type == CHAT_MSG_GUILD)
|
||||
if (type != CHAT_MSG_GUILD)
|
||||
{
|
||||
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
|
||||
{
|
||||
for (PlayerBotMap::const_iterator it = playerbotMgr->GetPlayerBotsBegin();
|
||||
it != playerbotMgr->GetPlayerBotsEnd(); ++it)
|
||||
{
|
||||
if (Player* const bot = it->second)
|
||||
{
|
||||
if (bot->GetGuildId() == player->GetGuildId())
|
||||
{
|
||||
GET_PLAYERBOT_AI(bot)->HandleCommand(type, msg, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
PlayerbotMgr* playerbotMgr = PlayerbotsMgr::instance().GetPlayerbotMgr(player);
|
||||
|
||||
if (playerbotMgr == nullptr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for (PlayerBotMap::const_iterator it = playerbotMgr->GetPlayerBotsBegin(); it != playerbotMgr->GetPlayerBotsEnd(); ++it)
|
||||
{
|
||||
Player* const bot = it->second;
|
||||
|
||||
if (bot == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bot->GetGuildId() != player->GetGuildId())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
PlayerbotsMgr::instance().GetPlayerbotAI(bot)->HandleCommand(type, msg, player);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Channel* channel) override
|
||||
{
|
||||
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
|
||||
PlayerbotMgr* const playerbotMgr = PlayerbotsMgr::instance().GetPlayerbotMgr(player);
|
||||
|
||||
if (playerbotMgr != nullptr && channel->GetFlags() & 0x18)
|
||||
{
|
||||
if (channel->GetFlags() & 0x18)
|
||||
{
|
||||
playerbotMgr->HandleCommand(type, msg);
|
||||
}
|
||||
playerbotMgr->HandleCommand(type, msg);
|
||||
}
|
||||
|
||||
sRandomPlayerbotMgr->HandleCommand(type, msg, player);
|
||||
sRandomPlayerbotMgr.HandleCommand(type, msg, player);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnPlayerBeforeAchievementComplete(Player* player, AchievementEntry const* achievement) override
|
||||
{
|
||||
if ((sRandomPlayerbotMgr->IsRandomBot(player) || sRandomPlayerbotMgr->IsAddclassBot(player)) &&
|
||||
if ((sRandomPlayerbotMgr.IsRandomBot(player) || sRandomPlayerbotMgr.IsAddclassBot(player)) &&
|
||||
(achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL)))
|
||||
{
|
||||
return false;
|
||||
@@ -266,11 +250,11 @@ public:
|
||||
void OnPlayerGiveXP(Player* player, uint32& amount, Unit* /*victim*/, uint8 /*xpSource*/) override
|
||||
{
|
||||
// early return
|
||||
if (sPlayerbotAIConfig->randomBotXPRate == 1.0 || !player)
|
||||
if (sPlayerbotAIConfig.randomBotXPRate == 1.0 || !player)
|
||||
return;
|
||||
|
||||
// no XP multiplier, when player is no bot.
|
||||
if (!player->GetSession()->IsBot() || !sRandomPlayerbotMgr->IsRandomBot(player))
|
||||
if (!player->GetSession()->IsBot() || !sRandomPlayerbotMgr.IsRandomBot(player))
|
||||
return;
|
||||
|
||||
// no XP multiplier, when bot is in a group with a real player.
|
||||
@@ -292,7 +276,7 @@ public:
|
||||
}
|
||||
|
||||
// otherwise apply bot XP multiplier.
|
||||
amount = static_cast<uint32>(std::round(static_cast<float>(amount) * sPlayerbotAIConfig->randomBotXPRate));
|
||||
amount = static_cast<uint32>(std::round(static_cast<float>(amount) * sPlayerbotAIConfig.randomBotXPRate));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -303,7 +287,9 @@ public:
|
||||
|
||||
void OnDestructPlayer(Player* player) override
|
||||
{
|
||||
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player))
|
||||
PlayerbotAI* botAI = PlayerbotsMgr::instance().GetPlayerbotAI(player);
|
||||
|
||||
if (botAI != nullptr)
|
||||
{
|
||||
delete botAI;
|
||||
}
|
||||
@@ -360,20 +346,20 @@ public:
|
||||
LOG_INFO("server.loading", " ");
|
||||
LOG_INFO("server.loading", "Load Playerbots Config...");
|
||||
|
||||
sPlayerbotAIConfig->Initialize();
|
||||
sPlayerbotAIConfig.Initialize();
|
||||
|
||||
LOG_INFO("server.loading", ">> Loaded playerbots config in {} ms", GetMSTimeDiffToNow(oldMSTime));
|
||||
LOG_INFO("server.loading", " ");
|
||||
|
||||
sPlayerbotSpellRepository->Initialize();
|
||||
PlayerbotSpellRepository::Instance().Initialize();
|
||||
|
||||
LOG_INFO("server.loading", "Playerbots World Thread Processor initialized");
|
||||
}
|
||||
|
||||
void OnUpdate(uint32 diff) override
|
||||
{
|
||||
sPlayerbotWorldProcessor->Update(diff);
|
||||
sRandomPlayerbotMgr->UpdateAI(diff); // World thread only
|
||||
PlayerbotWorldThreadProcessor::instance().Update(diff);
|
||||
sRandomPlayerbotMgr.UpdateAI(diff); // World thread only
|
||||
}
|
||||
};
|
||||
|
||||
@@ -385,10 +371,12 @@ public:
|
||||
bool OnPlayerbotCheckLFGQueue(lfg::Lfg5Guids const& guidsList) override
|
||||
{
|
||||
bool nonBotFound = false;
|
||||
|
||||
for (ObjectGuid const& guid : guidsList.guids)
|
||||
{
|
||||
Player* player = ObjectAccessor::FindPlayer(guid);
|
||||
if (guid.IsGroup() || (player && !GET_PLAYERBOT_AI(player)))
|
||||
|
||||
if (guid.IsGroup() || (player && !PlayerbotsMgr::instance().GetPlayerbotAI(player)))
|
||||
{
|
||||
nonBotFound = true;
|
||||
break;
|
||||
@@ -401,32 +389,48 @@ public:
|
||||
void OnPlayerbotCheckKillTask(Player* player, Unit* victim) override
|
||||
{
|
||||
if (player)
|
||||
sGuildTaskMgr->CheckKillTask(player, victim);
|
||||
GuildTaskMgr::instance().CheckKillTask(player, victim);
|
||||
}
|
||||
|
||||
void OnPlayerbotCheckPetitionAccount(Player* player, bool& found) override
|
||||
{
|
||||
if (found && GET_PLAYERBOT_AI(player))
|
||||
if (!found)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (PlayerbotsMgr::instance().GetPlayerbotAI(player) != nullptr)
|
||||
{
|
||||
found = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool OnPlayerbotCheckUpdatesToSend(Player* player) override
|
||||
{
|
||||
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player))
|
||||
return botAI->IsRealPlayer();
|
||||
PlayerbotAI* botAI = PlayerbotsMgr::instance().GetPlayerbotAI(player);
|
||||
|
||||
return true;
|
||||
if (botAI == nullptr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return botAI->IsRealPlayer();
|
||||
}
|
||||
|
||||
void OnPlayerbotPacketSent(Player* player, WorldPacket const* packet) override
|
||||
{
|
||||
if (!player)
|
||||
if (player == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player))
|
||||
PlayerbotAI* botAI = PlayerbotsMgr::instance().GetPlayerbotAI(player);
|
||||
|
||||
if (botAI != nullptr)
|
||||
{
|
||||
botAI->HandleBotOutgoingPacket(*packet);
|
||||
}
|
||||
|
||||
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
|
||||
{
|
||||
playerbotMgr->HandleMasterOutgoingPacket(*packet);
|
||||
@@ -435,7 +439,7 @@ public:
|
||||
|
||||
void OnPlayerbotUpdate(uint32 diff) override
|
||||
{
|
||||
sRandomPlayerbotMgr->UpdateSessions(); // Per-bot updates only
|
||||
sRandomPlayerbotMgr.UpdateSessions(); // Per-bot updates only
|
||||
}
|
||||
|
||||
void OnPlayerbotUpdateSessions(Player* player) override
|
||||
@@ -449,20 +453,21 @@ public:
|
||||
{
|
||||
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
|
||||
{
|
||||
PlayerbotAI* botAI = GET_PLAYERBOT_AI(player);
|
||||
if (!botAI || botAI->IsRealPlayer())
|
||||
PlayerbotAI* botAI = PlayerbotsMgr::instance().GetPlayerbotAI(player);
|
||||
|
||||
if (botAI == nullptr || botAI->IsRealPlayer())
|
||||
{
|
||||
playerbotMgr->LogoutAllBots();
|
||||
}
|
||||
}
|
||||
|
||||
sRandomPlayerbotMgr->OnPlayerLogout(player);
|
||||
sRandomPlayerbotMgr.OnPlayerLogout(player);
|
||||
}
|
||||
|
||||
void OnPlayerbotLogoutBots() override
|
||||
{
|
||||
LOG_INFO("playerbots", "Logging out all bots...");
|
||||
sRandomPlayerbotMgr->LogoutAllBots();
|
||||
sRandomPlayerbotMgr.LogoutAllBots();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user