5 Commits

Author SHA1 Message Date
kadeshar
ceb27c5ae4 - code fix 2025-05-26 22:18:23 +02:00
kadeshar
ccbe8ae63f - Added logout checks to prevent crash 2025-05-26 22:15:06 +02:00
Dustin Hendrickson
d7b1618cc0 Merge pull request #41 from DustinHendrickson/Dustin/Performance
[Enhancement] Throttling the amount of bots adjusted and spreading the process out.
2025-05-25 13:44:19 -07:00
Dustin Hendrickson
894bc68f4e Cleanup 2025-05-25 13:43:36 -07:00
Dustin Hendrickson
2cb23fe201 Adding new config option and setting default performance mode, uses the pending reset system to process X number of bots based on the config each X seconds instead of just doing one big update batch, locking the server up for 10's of seconds at a time. 2025-05-25 13:40:24 -07:00
2 changed files with 89 additions and 31 deletions

View File

@@ -32,10 +32,16 @@ BotLevelBrackets.CheckFrequency = 300
# #
# BotLevelBrackets.CheckFlaggedFrequency # BotLevelBrackets.CheckFlaggedFrequency
# Description: The frequency (in seconds) at which the bot level reset is performed for flagged bots that failed safety checks initially. # Description: The frequency (in seconds) at which the bot level reset is performed for processing safe bots and checking flagged bots that failed safety checks initially.
# Default: 15 # Default: 15
BotLevelBrackets.CheckFlaggedFrequency = 15 BotLevelBrackets.CheckFlaggedFrequency = 15
# BotLevelBrackets.FlaggedProcessLimit
# Description: Maximum number of flagged bots to process per flagged check step.
# 0 = unlimited (process all flagged bots each step)
# Default: 5
BotLevelBrackets.FlaggedProcessLimit = 5
# #
# BotLevelBrackets.IgnoreGuildBotsWithRealPlayers # BotLevelBrackets.IgnoreGuildBotsWithRealPlayers
# Description: When enabled, bots that are in a guild with at least one real (non-bot) player online are excluded # Description: When enabled, bots that are in a guild with at least one real (non-bot) player online are excluded

View File

@@ -57,6 +57,8 @@ static bool g_BotDistFullDebugMode = false;
static bool g_BotDistLiteDebugMode = false; static bool g_BotDistLiteDebugMode = false;
static bool g_UseDynamicDistribution = false; static bool g_UseDynamicDistribution = false;
static bool g_IgnoreFriendListed = true; static bool g_IgnoreFriendListed = true;
static uint32 g_FlaggedProcessLimit = 5; // 0 = unlimited
// Real player weight to boost bracket contributions. // Real player weight to boost bracket contributions.
static float g_RealPlayerWeight = 1.0f; static float g_RealPlayerWeight = 1.0f;
@@ -85,6 +87,7 @@ static void LoadBotLevelBracketsConfig()
g_RealPlayerWeight = sConfigMgr->GetOption<float>("BotLevelBrackets.Dynamic.RealPlayerWeight", 1.0f); g_RealPlayerWeight = sConfigMgr->GetOption<float>("BotLevelBrackets.Dynamic.RealPlayerWeight", 1.0f);
g_SyncFactions = sConfigMgr->GetOption<bool>("BotLevelBrackets.Dynamic.SyncFactions", false); g_SyncFactions = sConfigMgr->GetOption<bool>("BotLevelBrackets.Dynamic.SyncFactions", false);
g_IgnoreFriendListed = sConfigMgr->GetOption<bool>("BotLevelBrackets.IgnoreFriendListed", true); g_IgnoreFriendListed = sConfigMgr->GetOption<bool>("BotLevelBrackets.IgnoreFriendListed", true);
g_FlaggedProcessLimit = sConfigMgr->GetOption<uint32>("BotLevelBrackets.FlaggedProcessLimit", 5);
// Load the bot level restrictions. // Load the bot level restrictions.
g_RandomBotMinLevel = static_cast<uint8>(sConfigMgr->GetOption<uint32>("AiPlayerbot.RandomBotMinLevel", 1)); g_RandomBotMinLevel = static_cast<uint8>(sConfigMgr->GetOption<uint32>("AiPlayerbot.RandomBotMinLevel", 1));
@@ -360,10 +363,6 @@ static bool BotInFriendList(Player* bot)
for (size_t i = 0; i < SocialFriendsList.size(); ++i) for (size_t i = 0; i < SocialFriendsList.size(); ++i)
{ {
if (g_BotDistFullDebugMode)
{
LOG_INFO("server.loading", "[BotLevelBrackets] Check bot {} against SocialFriendsList Array Character GUID {}", bot->GetName(), SocialFriendsList[i]);
}
if (SocialFriendsList[i] == bot->GetGUID().GetRawValue()) if (SocialFriendsList[i] == bot->GetGUID().GetRawValue())
{ {
if (g_BotDistFullDebugMode) if (g_BotDistFullDebugMode)
@@ -468,6 +467,14 @@ static bool IsBotSafeForLevelReset(Player* bot)
} }
return false; return false;
} }
if (bot->GetSession()->isLogingOut())
{
if (g_BotDistFullDebugMode)
{
LOG_INFO("server.loading", "[BotLevelBrackets] Bot {} (Level {}) is logging out.", bot->GetName(), bot->GetLevel());
}
return false;
}
if (!bot->IsInWorld()) if (!bot->IsInWorld())
{ {
if (g_BotDistFullDebugMode) if (g_BotDistFullDebugMode)
@@ -538,6 +545,11 @@ static std::vector<PendingResetEntry> g_PendingLevelResets;
static void ProcessPendingLevelResets() static void ProcessPendingLevelResets()
{ {
if (!sRandomPlayerbotMgr->GetDisabledWithoutRealPlayerLogoutInProgress())
{
g_PendingLevelResets.clear();
return;
}
if (g_BotDistFullDebugMode) if (g_BotDistFullDebugMode)
{ {
LOG_INFO("server.loading", "[BotLevelBrackets] Processing {} pending resets...", g_PendingLevelResets.size()); LOG_INFO("server.loading", "[BotLevelBrackets] Processing {} pending resets...", g_PendingLevelResets.size());
@@ -547,34 +559,40 @@ static void ProcessPendingLevelResets()
return; return;
} }
// Limit the number of resets processed in one cycle if configured.
uint32 processed = 0;
for (auto it = g_PendingLevelResets.begin(); it != g_PendingLevelResets.end(); ) for (auto it = g_PendingLevelResets.begin(); it != g_PendingLevelResets.end(); )
{
Player* bot = it->bot;
int targetRange = it->targetRange;
if (g_IgnoreGuildBotsWithRealPlayers && BotInGuildWithRealPlayer(bot))
{ {
it = g_PendingLevelResets.erase(it); if (g_FlaggedProcessLimit > 0 && processed >= g_FlaggedProcessLimit)
continue; break;
}
if (g_IgnoreFriendListed && BotInFriendList(bot)) Player* bot = it->bot;
{ int targetRange = it->targetRange;
it = g_PendingLevelResets.erase(it); if (g_IgnoreGuildBotsWithRealPlayers && BotInGuildWithRealPlayer(bot))
continue;
}
if (bot && bot->IsInWorld() && IsBotSafeForLevelReset(bot))
{
AdjustBotToRange(bot, targetRange, it->factionRanges);
if (g_BotDistFullDebugMode)
{ {
LOG_INFO("server.loading", "[BotLevelBrackets] Bot '{}' successfully reset to level range {}-{}.", bot->GetName(), it->factionRanges[targetRange].lower, it->factionRanges[targetRange].upper); it = g_PendingLevelResets.erase(it);
continue;
}
if (g_IgnoreFriendListed && BotInFriendList(bot))
{
it = g_PendingLevelResets.erase(it);
continue;
}
if (bot && bot->IsInWorld() && IsBotSafeForLevelReset(bot))
{
AdjustBotToRange(bot, targetRange, it->factionRanges);
if (g_BotDistFullDebugMode)
{
LOG_INFO("server.loading", "[BotLevelBrackets] Bot '{}' successfully reset to level range {}-{}.", bot->GetName(), it->factionRanges[targetRange].lower, it->factionRanges[targetRange].upper);
}
it = g_PendingLevelResets.erase(it);
++processed;
}
else
{
++it;
} }
it = g_PendingLevelResets.erase(it);
} }
else
{
++it;
}
}
} }
// This function returns a valid bracket index for the given player's level. // This function returns a valid bracket index for the given player's level.
@@ -1003,7 +1021,24 @@ public:
LOG_INFO("server.loading", "[BotLevelBrackets] !!!! Adjusting alliance bot '{}' from range {} to range {} ({}-{}).", LOG_INFO("server.loading", "[BotLevelBrackets] !!!! Adjusting alliance bot '{}' from range {} to range {} ({}-{}).",
bot->GetName(), i + 1, targetRange + 1, g_AllianceLevelRanges[targetRange].lower, g_AllianceLevelRanges[targetRange].upper); bot->GetName(), i + 1, targetRange + 1, g_AllianceLevelRanges[targetRange].lower, g_AllianceLevelRanges[targetRange].upper);
} }
AdjustBotToRange(bot, targetRange, g_AllianceLevelRanges.data()); bool alreadyFlagged = false;
for (auto& entry : g_PendingLevelResets)
{
if (entry.bot == bot)
{
alreadyFlagged = true;
break;
}
}
if (!alreadyFlagged)
{
g_PendingLevelResets.push_back({bot, targetRange, g_AllianceLevelRanges.data()});
if (g_BotDistFullDebugMode)
{
LOG_INFO("server.loading", "[BotLevelBrackets] Alliance bot '{}' flagged for pending level reset to range {}-{}.",
bot->GetName(), g_AllianceLevelRanges[targetRange].lower, g_AllianceLevelRanges[targetRange].upper);
}
}
allianceActualCounts[i]--; allianceActualCounts[i]--;
allianceActualCounts[targetRange]++; allianceActualCounts[targetRange]++;
} }
@@ -1154,7 +1189,24 @@ public:
LOG_INFO("server.loading", "[BotLevelBrackets] !!!! Adjusting horde bot '{}' from range {} to range {} ({}-{}).", LOG_INFO("server.loading", "[BotLevelBrackets] !!!! Adjusting horde bot '{}' from range {} to range {} ({}-{}).",
bot->GetName(), i + 1, targetRange + 1, g_HordeLevelRanges[targetRange].lower, g_HordeLevelRanges[targetRange].upper); bot->GetName(), i + 1, targetRange + 1, g_HordeLevelRanges[targetRange].lower, g_HordeLevelRanges[targetRange].upper);
} }
AdjustBotToRange(bot, targetRange, g_HordeLevelRanges.data()); bool alreadyFlagged = false;
for (auto& entry : g_PendingLevelResets)
{
if (entry.bot == bot)
{
alreadyFlagged = true;
break;
}
}
if (!alreadyFlagged)
{
g_PendingLevelResets.push_back({bot, targetRange, g_HordeLevelRanges.data()});
if (g_BotDistFullDebugMode)
{
LOG_INFO("server.loading", "[BotLevelBrackets] Horde bot '{}' flagged for pending level reset to range {}-{}.",
bot->GetName(), g_HordeLevelRanges[targetRange].lower, g_HordeLevelRanges[targetRange].upper);
}
}
hordeActualCounts[i]--; hordeActualCounts[i]--;
hordeActualCounts[targetRange]++; hordeActualCounts[targetRange]++;
} }