diff --git a/Libraries/SPTarkov.Server.Core/Controllers/BotController.cs b/Libraries/SPTarkov.Server.Core/Controllers/BotController.cs
index 7525b2a7..78f8ae2c 100644
--- a/Libraries/SPTarkov.Server.Core/Controllers/BotController.cs
+++ b/Libraries/SPTarkov.Server.Core/Controllers/BotController.cs
@@ -1,3 +1,4 @@
+using System.Collections.Concurrent;
using System.Diagnostics;
using System.Text.Json.Serialization;
using SPTarkov.Common.Annotations;
@@ -179,7 +180,7 @@ public class BotController(
/// List of generated bots
protected List GenerateBotWaves(GenerateBotsRequestData request, PmcData? pmcProfile, string sessionId)
{
- var result = new List();
+ var result = new ConcurrentBag();
var raidSettings = GetMostRecentRaidSettings();
@@ -201,8 +202,12 @@ public class BotController(
condition.Limit), // Choose largest between value passed in from request vs what's in bot.config
_botHelper.IsBotPmc(condition.Role));
- result.AddRange(GenerateBotWave(condition, botWaveGenerationDetails, sessionId));
- })).ToArray());
+ var wave = GenerateBotWave(condition, botWaveGenerationDetails, sessionId);
+ foreach (var bot in wave)
+ {
+ result.Add(bot);
+ }
+ })));
stopwatch.Stop();
if (_logger.IsLogEnabled(LogLevel.Debug))
@@ -210,7 +215,7 @@ public class BotController(
_logger.Debug($"Took {stopwatch.ElapsedMilliseconds}ms to GenerateMultipleBotsAndCache()");
}
- return result;
+ return result.ToList();
}
///
@@ -239,30 +244,38 @@ public class BotController(
_logger.Debug($"Generating wave of: {botGenerationDetails.BotCountToGenerate} bots of type: {role} {botGenerationDetails.BotDifficulty}");
}
- var results = new List();
+ var results = new ConcurrentBag();
+ var tasks = new Task[botGenerationDetails.BotCountToGenerate.Value];
+
for (var i = 0; i < botGenerationDetails.BotCountToGenerate; i++)
{
- try
+ var task = Task.Run(() =>
{
- var bot = _botGenerator.PrepareAndGenerateBot(sessionId, _cloner.Clone(botGenerationDetails));
-
- // The client expects the Side for PMCs to be `Savage`
- // We do this here so it's after we cache the bot in the match details lookup, as when you die, they will have the right side
- if (bot.Info.Side is "Bear" or "Usec")
+ try
{
- bot.Info.Side = "Savage";
- }
+ var bot = _botGenerator.PrepareAndGenerateBot(sessionId, _cloner.Clone(botGenerationDetails));
- results.Add(bot);
- // Store bot details in cache so post-raid PMC messages can use data
- _matchBotDetailsCacheService.CacheBot(_cloner.Clone(bot));
- }
- catch (Exception e)
- {
- _logger.Error($"Failed to generate bot: {botGenerationDetails.Role} #{i + 1}: {e.Message} {e.StackTrace}");
- }
+ // The client expects the Side for PMCs to be `Savage`
+ // We do this here so it's after we cache the bot in the match details lookup, as when you die, they will have the right side
+ if (bot.Info.Side is "Bear" or "Usec")
+ {
+ bot.Info.Side = "Savage";
+ }
+
+ results.Add(bot);
+ // Store bot details in cache so post-raid PMC messages can use data
+ _matchBotDetailsCacheService.CacheBot(_cloner.Clone(bot));
+ }
+ catch (Exception e)
+ {
+ _logger.Error($"Failed to generate bot: {botGenerationDetails.Role} #{i + 1}: {e.Message} {e.StackTrace}");
+ }
+ });
+ tasks[i] = task;
}
+ Task.WaitAll(tasks);
+
if (_logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
@@ -271,7 +284,7 @@ public class BotController(
);
}
- return results;
+ return results.ToList();
}
///