java-topology/defects/regamedll-0001/patch/regamedll-0001.patch

45 lines
1.8 KiB
Diff

# UNDF: UNDF-2026-000001005
--- a/regamedll/game_shared/bot/bot_profile.cpp
+++ b/regamedll/game_shared/bot/bot_profile.cpp
@@ -590,13 +590,24 @@
}
// Return random unused profile that matches the given difficulty level
+// DEFECT: UTIL_IsNameTaken called per-profile O(P*C) where P=profiles, C=clients
+// FIX: build taken-name set once O(C), then check O(1) per profile
const BotProfile *BotProfileManager::GetRandomProfile(BotDifficultyType difficulty, BotProfileTeamType team) const
{
#ifdef RANDOM_LONG
BotProfileList::const_iterator iter;
+ // Build set of taken names once, instead of scanning players per profile
+ std::set<std::string> takenNames;
+ for (int i = 1; i <= gpGlobals->maxClients; ++i)
+ {
+ CBasePlayer *player = static_cast<CBasePlayer *>(UTIL_PlayerByIndex(i));
+ if (player && player->IsBot())
+ takenNames.insert(static_cast<CBot *>(player)->GetProfile()->GetName());
+ else if (player && !FNullEnt(player->pev) && STRING(player->pev->netname)[0])
+ takenNames.insert(STRING(player->pev->netname));
+ }
+
// count up valid profiles
int validCount = 0;
for (iter = m_profileList.begin(); iter != m_profileList.end(); ++iter)
@@ -604,7 +615,7 @@
const BotProfile *profile = (*iter);
- if (profile->IsDifficulty(difficulty) && !UTIL_IsNameTaken(profile->GetName()) && profile->IsValidForTeam(team))
+ if (profile->IsDifficulty(difficulty) && takenNames.find(profile->GetName()) == takenNames.end() && profile->IsValidForTeam(team))
++validCount;
}
@@ -616,7 +627,7 @@
{
const BotProfile *profile = (*iter);
- if (profile->IsDifficulty(difficulty) && !UTIL_IsNameTaken(profile->GetName()) && profile->IsValidForTeam(team))
+ if (profile->IsDifficulty(difficulty) && takenNames.find(profile->GetName()) == takenNames.end() && profile->IsValidForTeam(team))
{
if (which-- == 0)
return profile;