From 9a9c5f3c72a1ed46b6cf499b7c8e65e80960046d Mon Sep 17 00:00:00 2001 From: Chomp Date: Tue, 28 Jan 2025 08:49:01 +0000 Subject: [PATCH] Fixed issues caused by inclusion of multithreading Added stopwatch to bot generation --- Libraries/Core/Controllers/BotController.cs | 6 ++++- .../Generators/BotEquipmentModGenerator.cs | 2 +- .../Core/Generators/BotInventoryGenerator.cs | 2 +- .../Services/BotEquipmentModPoolService.cs | 18 +++++++-------- Libraries/Core/Services/BotNameService.cs | 23 ++++++++++++++++--- 5 files changed, 35 insertions(+), 16 deletions(-) diff --git a/Libraries/Core/Controllers/BotController.cs b/Libraries/Core/Controllers/BotController.cs index 2e6bc274..58b261eb 100644 --- a/Libraries/Core/Controllers/BotController.cs +++ b/Libraries/Core/Controllers/BotController.cs @@ -16,6 +16,8 @@ using Core.Utils; using Core.Utils.Cloners; using SptCommon.Extensions; using LogLevel = Core.Models.Spt.Logging.LogLevel; +using System.Diagnostics; +using Microsoft.Extensions.Logging; namespace Core.Controllers; @@ -150,7 +152,7 @@ public class BotController( var allPmcsHaveSameNameAsPlayer = _randomUtil.GetChance100( _pmcConfig.AllPMCsHavePlayerNameWithRandomPrefixChance ); - + var stopwatch = Stopwatch.StartNew(); var tasks = new List(); // Map conditions to promises for bot generation foreach (var condition in request.Conditions ?? []) @@ -176,6 +178,8 @@ public class BotController( } Task.WaitAll(tasks.ToArray()); + stopwatch.Stop(); + _logger.Info($"Took {stopwatch.ElapsedMilliseconds}ms to GenerateMultipleBotsAndCache"); return []; } diff --git a/Libraries/Core/Generators/BotEquipmentModGenerator.cs b/Libraries/Core/Generators/BotEquipmentModGenerator.cs index db544989..f43063eb 100644 --- a/Libraries/Core/Generators/BotEquipmentModGenerator.cs +++ b/Libraries/Core/Generators/BotEquipmentModGenerator.cs @@ -639,7 +639,7 @@ public class BotEquipmentModGenerator( var modFromService = _botEquipmentModPoolService.GetModsForWeaponSlot(modToAddTemplate.Value.Id); if (modFromService?.Keys.Count > 0) { - request.ModPool[modToAddTemplate.Value.Id] = modFromService; + request.ModPool[modToAddTemplate.Value.Id] = modFromService.ToDictionary(); containsModInPool = true; } } diff --git a/Libraries/Core/Generators/BotInventoryGenerator.cs b/Libraries/Core/Generators/BotInventoryGenerator.cs index 4947fbb6..0cdaf4da 100644 --- a/Libraries/Core/Generators/BotInventoryGenerator.cs +++ b/Libraries/Core/Generators/BotInventoryGenerator.cs @@ -543,7 +543,7 @@ public class BotInventoryGenerator( modPool[modSlot.Key] = filteredMods.ToHashSet(); } - return modPool; + return modPool.ToDictionary(); } /// diff --git a/Libraries/Core/Services/BotEquipmentModPoolService.cs b/Libraries/Core/Services/BotEquipmentModPoolService.cs index bef52805..47b67788 100644 --- a/Libraries/Core/Services/BotEquipmentModPoolService.cs +++ b/Libraries/Core/Services/BotEquipmentModPoolService.cs @@ -1,3 +1,4 @@ +using System.Collections.Concurrent; using SptCommon.Annotations; using Core.Models.Eft.Common.Tables; using Core.Models.Utils; @@ -19,8 +20,8 @@ public class BotEquipmentModPoolService protected bool _weaponPoolGenerated; protected bool _armorPoolGenerated; - protected Dictionary>> _weaponModPool; - protected Dictionary>> _gearModPool; + protected ConcurrentDictionary>> _weaponModPool; + protected ConcurrentDictionary>> _gearModPool; protected BotConfig _botConfig; public BotEquipmentModPoolService( @@ -38,8 +39,8 @@ public class BotEquipmentModPoolService _configServer = configServer; _botConfig = _configServer.GetConfig(); - _weaponModPool = new Dictionary>>(); - _gearModPool = new Dictionary>>(); + _weaponModPool = new ConcurrentDictionary>>(); + _gearModPool = new ConcurrentDictionary>>(); } /** @@ -75,10 +76,7 @@ public class BotEquipmentModPoolService } // Add base item (weapon/armor) to pool - if (!pool.ContainsKey(item.Id)) - { - pool[item.Id] = new Dictionary>(); - } + pool.TryAdd(item.Id, new ConcurrentDictionary>()); // iterate over each items mod slots e.g. mod_muzzle foreach (var slot in item.Properties.Slots) { @@ -143,7 +141,7 @@ public class BotEquipmentModPoolService * @param itemTpl items tpl to look up mods for * @returns Dictionary of mods (keys are mod slot names) with array of compatible mod tpls as value */ - public Dictionary> GetModsForGearSlot(string itemTpl) + public ConcurrentDictionary> GetModsForGearSlot(string itemTpl) { if (!_armorPoolGenerated) { @@ -160,7 +158,7 @@ public class BotEquipmentModPoolService * @param itemTpl Weapons tpl to look up mods for * @returns Dictionary of mods (keys are mod slot names) with array of compatible mod tpls as value */ - public Dictionary> GetModsForWeaponSlot(string itemTpl) + public ConcurrentDictionary> GetModsForWeaponSlot(string itemTpl) { if (!_weaponPoolGenerated) { diff --git a/Libraries/Core/Services/BotNameService.cs b/Libraries/Core/Services/BotNameService.cs index 9e4f14df..1758c813 100644 --- a/Libraries/Core/Services/BotNameService.cs +++ b/Libraries/Core/Services/BotNameService.cs @@ -21,6 +21,7 @@ public class BotNameService( { protected BotConfig _botConfig = _configServer.GetConfig(); protected HashSet _usedNameCache = new HashSet(); + protected object _lock = new(); /// /// Clear out any entries in Name Set @@ -42,7 +43,7 @@ public class BotNameService( BotType botJsonTemplate, BotGenerationDetails botGenerationDetails, string botRole, - List uniqueRoles = null) + List? uniqueRoles = null) { var isPmc = botGenerationDetails.IsPmc; @@ -77,7 +78,7 @@ public class BotNameService( if (roleShouldBeUnique.GetValueOrDefault(false)) { // Check name in cache - if (_usedNameCache.Contains(name)) + if (CacheContainsName(name)) { // Not unique if (attempts >= 5) @@ -97,7 +98,7 @@ public class BotNameService( } // Add bot name to cache to prevent being used again - _usedNameCache.Add(name); + AddNameToCache(name); return name; } @@ -106,6 +107,22 @@ public class BotNameService( return $"BOT {botRole} {botGenerationDetails.BotDifficulty}"; } + private bool AddNameToCache(string name) + { + lock (_lock) + { + return _usedNameCache.Add(name); + } + } + + protected bool CacheContainsName(string name) + { + lock (_lock) + { + return _usedNameCache.Contains(name); + } + } + /// /// Add random PMC name to bots MainProfileNickname property ///