From 4e3c755e908885e9cae1f5523e063d497bd82f51 Mon Sep 17 00:00:00 2001 From: Archangel Date: Fri, 30 May 2025 19:36:23 +0200 Subject: [PATCH] Remove AppContext, store profile related data in ProfileActivityService --- .../Callbacks/BotCallbacks.cs | 9 +- .../Callbacks/HttpCallbacks.cs | 1 - .../Context/ApplicationContext.cs | 90 ------------------- .../Context/ContextVariable.cs | 21 ----- .../Context/ContextVariableType.cs | 21 ----- .../Controllers/BotController.cs | 22 ++--- .../Controllers/GameController.cs | 5 +- .../Controllers/InRaidController.cs | 5 +- .../Controllers/LauncherController.cs | 4 +- .../Controllers/LauncherV2Controller.cs | 4 +- .../Controllers/MatchController.cs | 5 +- .../Generators/BotInventoryGenerator.cs | 7 +- .../Helpers/BotGeneratorHelper.cs | 7 +- .../Spt/Services/ProfileActivityData.cs | 20 +++++ .../Servers/HttpServer.cs | 1 - .../Services/BackupService.cs | 6 +- .../Services/LocationLifecycleService.cs | 25 +++--- .../Services/ProfileActivityService.cs | 58 ++++++++++-- .../Services/RaidTimeAdjustmentService.cs | 5 +- SPTarkov.Server/Program.cs | 6 -- 20 files changed, 108 insertions(+), 214 deletions(-) delete mode 100644 Libraries/SPTarkov.Server.Core/Context/ApplicationContext.cs delete mode 100644 Libraries/SPTarkov.Server.Core/Context/ContextVariable.cs delete mode 100644 Libraries/SPTarkov.Server.Core/Context/ContextVariableType.cs create mode 100644 Libraries/SPTarkov.Server.Core/Models/Spt/Services/ProfileActivityData.cs diff --git a/Libraries/SPTarkov.Server.Core/Callbacks/BotCallbacks.cs b/Libraries/SPTarkov.Server.Core/Callbacks/BotCallbacks.cs index 792e9841..f8322707 100644 --- a/Libraries/SPTarkov.Server.Core/Callbacks/BotCallbacks.cs +++ b/Libraries/SPTarkov.Server.Core/Callbacks/BotCallbacks.cs @@ -1,5 +1,4 @@ using SPTarkov.DI.Annotations; -using SPTarkov.Server.Core.Context; using SPTarkov.Server.Core.Controllers; using SPTarkov.Server.Core.Models.Eft.Bot; using SPTarkov.Server.Core.Models.Eft.Common; @@ -11,8 +10,7 @@ namespace SPTarkov.Server.Core.Callbacks; [Injectable] public class BotCallbacks( BotController _botController, - HttpResponseUtil _httpResponseUtil, - ApplicationContext _applicationContext + HttpResponseUtil _httpResponseUtil ) { /// @@ -41,10 +39,7 @@ public class BotCallbacks( return _httpResponseUtil.NoBody(_botController.GetBotCoreDifficulty()); } - var raidConfig = _applicationContext.GetLatestValue(ContextVariableType.RAID_CONFIGURATION) - ?.GetValue(); - - return _httpResponseUtil.NoBody(_botController.GetBotDifficulty(type, difficulty, raidConfig)); + return _httpResponseUtil.NoBody(_botController.GetBotDifficulty(sessionID, type, difficulty)); } /// diff --git a/Libraries/SPTarkov.Server.Core/Callbacks/HttpCallbacks.cs b/Libraries/SPTarkov.Server.Core/Callbacks/HttpCallbacks.cs index 4c92ea28..1461e016 100644 --- a/Libraries/SPTarkov.Server.Core/Callbacks/HttpCallbacks.cs +++ b/Libraries/SPTarkov.Server.Core/Callbacks/HttpCallbacks.cs @@ -1,5 +1,4 @@ using SPTarkov.DI.Annotations; -using SPTarkov.Server.Core.Context; using SPTarkov.Server.Core.DI; using SPTarkov.Server.Core.Servers; diff --git a/Libraries/SPTarkov.Server.Core/Context/ApplicationContext.cs b/Libraries/SPTarkov.Server.Core/Context/ApplicationContext.cs deleted file mode 100644 index 1b21019e..00000000 --- a/Libraries/SPTarkov.Server.Core/Context/ApplicationContext.cs +++ /dev/null @@ -1,90 +0,0 @@ -using SPTarkov.DI.Annotations; -using SPTarkov.Server.Core.Models.Utils; - -namespace SPTarkov.Server.Core.Context; - -[Injectable(InjectionType.Singleton)] -public class ApplicationContext -{ - private const short MaxSavedValues = 10; - - private static ApplicationContext? _applicationContext; - private readonly ISptLogger _logger; - private readonly Dictionary> _variables = new(); - private readonly Lock _lockObject = new(); - - /// - /// When ApplicationContext gets created by the DI container we store the singleton reference so we can provide it - /// statically for harmony patches! - /// - public ApplicationContext(ISptLogger logger) - { - _logger = logger; - _applicationContext = this; - } - - public static ApplicationContext? GetInstance() - { - return _applicationContext; - } - - public ContextVariable? GetLatestValue(ContextVariableType type) - { - lock (_lockObject) - { - if (_variables.TryGetValue(type, out var savedValues)) - { - return savedValues.Last!.Value; - } - - return null; - } - } - - public ICollection GetValues(ContextVariableType type) - { - lock (_lockObject) - { - var values = new List(); - if (_variables.TryGetValue(type, out var savedValues)) - { - values.AddRange(savedValues); - } - - return values; - } - } - - public void AddValue(ContextVariableType type, object value) - { - lock (_lockObject) - { - if (!_variables.TryGetValue(type, out var savedValues)) - { - savedValues = []; - if (!_variables.TryAdd(type, savedValues)) - { - _logger.Error($"Unable to add context variable type: {type}"); - } - } - - if (savedValues.Count >= MaxSavedValues) - { - savedValues.RemoveFirst(); - } - - savedValues.AddLast(new ContextVariable(value, type)); - } - } - - public void ClearValues(ContextVariableType type) - { - lock (_lockObject) - { - if (!_variables.Remove(type, out _)) - { - _logger.Error($"Unable to clear context variable type: {type}"); - } - } - } -} diff --git a/Libraries/SPTarkov.Server.Core/Context/ContextVariable.cs b/Libraries/SPTarkov.Server.Core/Context/ContextVariable.cs deleted file mode 100644 index d328ebe2..00000000 --- a/Libraries/SPTarkov.Server.Core/Context/ContextVariable.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace SPTarkov.Server.Core.Context; - -public class ContextVariable(object value, ContextVariableType contextVariableInternalType) -{ - private readonly DateTime _timestamp = DateTime.UtcNow; - - public T GetValue() - { - return (T) value; - } - - public DateTime GetTimestamp() - { - return _timestamp; - } - - public ContextVariableType GetContextType() - { - return contextVariableInternalType; - } -} diff --git a/Libraries/SPTarkov.Server.Core/Context/ContextVariableType.cs b/Libraries/SPTarkov.Server.Core/Context/ContextVariableType.cs deleted file mode 100644 index 919fdccc..00000000 --- a/Libraries/SPTarkov.Server.Core/Context/ContextVariableType.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace SPTarkov.Server.Core.Context; - -public enum ContextVariableType -{ - // Logged-in users session id - SESSION_ID = 0, - - // Currently active raid information - RAID_CONFIGURATION = 1, - - // SessionID + Timestamp when client first connected, has _ between values - CLIENT_START_TIMESTAMP = 2, - - // When player is loading into map and loot is requested - REGISTER_PLAYER_REQUEST = 3, - RAID_ADJUSTMENTS = 4, - - // Data returned from client request object from endLocalRaid() - TRANSIT_INFO = 5, - SERVICE_PROVIDER = 9 -} diff --git a/Libraries/SPTarkov.Server.Core/Controllers/BotController.cs b/Libraries/SPTarkov.Server.Core/Controllers/BotController.cs index 80564295..a6188b8e 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/BotController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/BotController.cs @@ -2,7 +2,6 @@ using System.Diagnostics; using System.Text.Json.Serialization; using SPTarkov.Server.Core.Constants; using SPTarkov.DI.Annotations; -using SPTarkov.Server.Core.Context; using SPTarkov.Server.Core.Generators; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Common; @@ -33,7 +32,7 @@ public class BotController( MatchBotDetailsCacheService _matchBotDetailsCacheService, ProfileHelper _profileHelper, ConfigServer _configServer, - ApplicationContext _applicationContext, + ProfileActivityService _profileActivityService, RandomUtil _randomUtil, ICloner _cloner ) @@ -73,15 +72,18 @@ public class BotController( /// Get bot difficulty settings /// Adjust PMC settings to ensure they engage the correct bot types /// + /// Which user is requesting his bot settings /// what bot the server is requesting settings for /// difficulty level server requested settings for /// OPTIONAL - applicationContext Data stored at start of raid /// OPTIONAL - should raid settings chosen pre-raid be ignored /// Difficulty object - public DifficultyCategories GetBotDifficulty(string type, string diffLevel, GetRaidConfigurationRequestData? raidConfig, bool ignoreRaidSettings = false) + public DifficultyCategories GetBotDifficulty(string sessionId, string type, string diffLevel, bool ignoreRaidSettings = false) { var difficulty = diffLevel.ToLower(); + var raidConfig = _profileActivityService.GetProfileActivityRaidData(sessionId)?.RaidConfiguration; + if (!(raidConfig != null || ignoreRaidSettings)) { _logger.Error(_localisationService.GetText("bot-missing_application_context", "RAID_CONFIGURATION")); @@ -152,7 +154,7 @@ public class BotController( } // Store all difficulty values in dict keyed by difficulty type e.g. easy/normal/impossible - result[botNameKey].Add(difficultyName, GetBotDifficulty(botNameKey, difficultyName, null, true)); + result[botNameKey].Add(difficultyName, GetBotDifficulty(string.Empty, botNameKey, difficultyName, true)); } } @@ -182,7 +184,7 @@ public class BotController( protected List GenerateBotWaves(GenerateBotsRequestData request, PmcData? pmcProfile, string sessionId) { var generatedBotList = new List(); - var raidSettings = GetMostRecentRaidSettings(); + var raidSettings = GetMostRecentRaidSettings(sessionId); var allPmcsHaveSameNameAsPlayer = _randomUtil.GetChance100( _pmcConfig.AllPMCsHavePlayerNameWithRandomPrefixChance ); @@ -287,18 +289,16 @@ public class BotController( /// Pull raid settings from Application context /// /// GetRaidConfigurationRequestData if it exists - protected GetRaidConfigurationRequestData? GetMostRecentRaidSettings() + protected GetRaidConfigurationRequestData? GetMostRecentRaidSettings(string sessionId) { - var raidSettings = _applicationContext - .GetLatestValue(ContextVariableType.RAID_CONFIGURATION) - ?.GetValue(); + var raidConfiguration = _profileActivityService.GetProfileActivityRaidData(sessionId)?.RaidConfiguration; - if (raidSettings is null) + if (raidConfiguration is null) { _logger.Warning(_localisationService.GetText("bot-unable_to_load_raid_settings_from_appcontext")); } - return raidSettings; + return raidConfiguration; } /// diff --git a/Libraries/SPTarkov.Server.Core/Controllers/GameController.cs b/Libraries/SPTarkov.Server.Core/Controllers/GameController.cs index 353928e1..60fedbf8 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/GameController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/GameController.cs @@ -1,5 +1,4 @@ using SPTarkov.DI.Annotations; -using SPTarkov.Server.Core.Context; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Eft.Common; using SPTarkov.Server.Core.Models.Eft.Game; @@ -42,7 +41,6 @@ public class GameController( RaidTimeAdjustmentService _raidTimeAdjustmentService, ProfileActivityService _profileActivityService, CreateProfileService _createProfileService, - ApplicationContext _applicationContext, ICloner _cloner ) { @@ -61,8 +59,7 @@ public class GameController( /// public void GameStart(string url, string? sessionId, long startTimeStampMs) { - // Store client start time in app context - _applicationContext.AddValue(ContextVariableType.CLIENT_START_TIMESTAMP, $"{sessionId}_{startTimeStampMs}"); + _profileActivityService.AddActiveProfile(sessionId, startTimeStampMs); if (sessionId is null) { diff --git a/Libraries/SPTarkov.Server.Core/Controllers/InRaidController.cs b/Libraries/SPTarkov.Server.Core/Controllers/InRaidController.cs index b529759a..38b0db8a 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/InRaidController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/InRaidController.cs @@ -1,5 +1,4 @@ using SPTarkov.DI.Annotations; -using SPTarkov.Server.Core.Context; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Eft.InRaid; using SPTarkov.Server.Core.Models.Spt.Config; @@ -12,7 +11,7 @@ namespace SPTarkov.Server.Core.Controllers; public class InRaidController( ISptLogger _logger, ProfileHelper _profileHelper, - ApplicationContext _applicationContext, + //ApplicationContext _applicationContext, ConfigServer _configServer ) { @@ -26,7 +25,7 @@ public class InRaidController( /// Register player request public void AddPlayer(string sessionId, RegisterPlayerRequestData info) { - _applicationContext.AddValue(ContextVariableType.REGISTER_PLAYER_REQUEST, info); + // _applicationContext.AddValue(ContextVariableType.REGISTER_PLAYER_REQUEST, info); } /// diff --git a/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs b/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs index ab0624fb..3e14e649 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs @@ -1,6 +1,5 @@ using SPTarkov.Common.Extensions; using SPTarkov.DI.Annotations; -using SPTarkov.Server.Core.Context; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Eft.Launcher; @@ -27,8 +26,7 @@ public class LauncherController( ProfileHelper _profileHelper, DatabaseService _databaseService, LocalisationService _localisationService, - ConfigServer _configServer, - ApplicationContext _applicationContext + ConfigServer _configServer ) { protected CoreConfig _coreConfig = _configServer.GetConfig(); diff --git a/Libraries/SPTarkov.Server.Core/Controllers/LauncherV2Controller.cs b/Libraries/SPTarkov.Server.Core/Controllers/LauncherV2Controller.cs index 4e056f00..67f42dd4 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/LauncherV2Controller.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/LauncherV2Controller.cs @@ -1,6 +1,5 @@ using SPTarkov.Common.Extensions; using SPTarkov.DI.Annotations; -using SPTarkov.Server.Core.Context; using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Eft.Launcher; using SPTarkov.Server.Core.Models.Eft.Profile; @@ -25,8 +24,7 @@ public class LauncherV2Controller( DatabaseService _databaseService, LocalisationService _localisationService, ConfigServer _configServer, - Watermark _watermark, - ApplicationContext _applicationContext + Watermark _watermark ) { protected CoreConfig _coreConfig = _configServer.GetConfig(); diff --git a/Libraries/SPTarkov.Server.Core/Controllers/MatchController.cs b/Libraries/SPTarkov.Server.Core/Controllers/MatchController.cs index d507a69e..f5c078c7 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/MatchController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/MatchController.cs @@ -1,5 +1,4 @@ using SPTarkov.DI.Annotations; -using SPTarkov.Server.Core.Context; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Eft.Match; using SPTarkov.Server.Core.Models.Spt.Config; @@ -17,8 +16,8 @@ public class MatchController( SaveServer _saveServer, MatchLocationService _matchLocationService, ConfigServer _configServer, - ApplicationContext _applicationContext, LocationLifecycleService _locationLifecycleService, + ProfileActivityService _profileActivityService, WeatherHelper _weatherHelper, ICloner _cloner ) @@ -104,7 +103,7 @@ public class MatchController( request.IsNightRaid = _weatherHelper.IsNightTime(request.TimeVariant, request.Location); // Store request data for access during bot generation - _applicationContext.AddValue(ContextVariableType.RAID_CONFIGURATION, request); + _profileActivityService.GetProfileActivityRaidData(sessionId).RaidConfiguration = request; // TODO: add code to strip PMC of equipment now they've started the raid diff --git a/Libraries/SPTarkov.Server.Core/Generators/BotInventoryGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/BotInventoryGenerator.cs index 40f6881a..8a65ab5a 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/BotInventoryGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/BotInventoryGenerator.cs @@ -1,6 +1,5 @@ using System.Collections.Frozen; using SPTarkov.DI.Annotations; -using SPTarkov.Server.Core.Context; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Eft.Match; @@ -21,7 +20,7 @@ public class BotInventoryGenerator( HashUtil _hashUtil, RandomUtil _randomUtil, DatabaseService _databaseService, - ApplicationContext _applicationContext, + ProfileActivityService _profileActivityService, BotWeaponGenerator _botWeaponGenerator, BotLootGenerator _botLootGenerator, BotGeneratorHelper _botGeneratorHelper, @@ -75,9 +74,7 @@ public class BotInventoryGenerator( var botInventory = GenerateInventoryBase(); // Get generated raid details bot will be spawned in - var raidConfig = _applicationContext - .GetLatestValue(ContextVariableType.RAID_CONFIGURATION) - ?.GetValue(); + var raidConfig = _profileActivityService.GetProfileActivityRaidData(sessionId).RaidConfiguration; GenerateAndAddEquipmentToBot( sessionId, diff --git a/Libraries/SPTarkov.Server.Core/Helpers/BotGeneratorHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/BotGeneratorHelper.cs index 1c7475d4..587f1aa4 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/BotGeneratorHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/BotGeneratorHelper.cs @@ -1,7 +1,6 @@ using System.Collections.Frozen; using SPTarkov.Server.Core.Constants; using SPTarkov.DI.Annotations; -using SPTarkov.Server.Core.Context; using SPTarkov.Server.Core.DI; using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Eft.Match; @@ -24,7 +23,7 @@ public class BotGeneratorHelper( ItemHelper _itemHelper, InventoryHelper _inventoryHelper, ContainerHelper _containerHelper, - ApplicationContext _applicationContext, + ProfileActivityService _profileActivityService, LocalisationService _localisationService, ConfigServer _configServer ) : IOnLoad @@ -59,9 +58,7 @@ public class BotGeneratorHelper( public Upd GenerateExtraPropertiesForItem(TemplateItem? itemTemplate, string? botRole = null) { // Get raid settings, if no raid, default to day - var raidSettings = _applicationContext - .GetLatestValue(ContextVariableType.RAID_CONFIGURATION) - ?.GetValue(); + var raidSettings = _profileActivityService.GetFirstProfileActivityRaidData()?.RaidConfiguration; RandomisedResourceDetails randomisationSettings = null; if (botRole is not null) diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Services/ProfileActivityData.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Services/ProfileActivityData.cs new file mode 100644 index 00000000..9b527c3a --- /dev/null +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Services/ProfileActivityData.cs @@ -0,0 +1,20 @@ +using SPTarkov.Server.Core.Models.Eft.Match; +using SPTarkov.Server.Core.Models.Spt.Location; + +namespace SPTarkov.Server.Core.Models.Spt.Services +{ + public class ProfileActivityData + { + public long ClientStartedTimestamp { get; set; } + public long LastActive { get; set; } + public ProfileActivityRaidData? RaidData { get; set; } = null; + } + + public class ProfileActivityRaidData + { + public GetRaidConfigurationRequestData? RaidConfiguration { get; set; } = null; + public RaidChanges? RaidAdjustments { get; set; } = null; + public LocationTransit? LocationTransit { get; set; } = null; + } + +} diff --git a/Libraries/SPTarkov.Server.Core/Servers/HttpServer.cs b/Libraries/SPTarkov.Server.Core/Servers/HttpServer.cs index 88c1d316..f872b4cc 100644 --- a/Libraries/SPTarkov.Server.Core/Servers/HttpServer.cs +++ b/Libraries/SPTarkov.Server.Core/Servers/HttpServer.cs @@ -4,7 +4,6 @@ using Microsoft.AspNetCore.Server.Kestrel.Https; using Microsoft.Extensions.Primitives; using SPTarkov.Common.Extensions; using SPTarkov.DI.Annotations; -using SPTarkov.Server.Core.Context; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Spt.Config; using SPTarkov.Server.Core.Models.Utils; diff --git a/Libraries/SPTarkov.Server.Core/Services/BackupService.cs b/Libraries/SPTarkov.Server.Core/Services/BackupService.cs index a60e440d..aea47c39 100644 --- a/Libraries/SPTarkov.Server.Core/Services/BackupService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/BackupService.cs @@ -1,5 +1,4 @@ using SPTarkov.DI.Annotations; -using SPTarkov.Server.Core.Context; using SPTarkov.Server.Core.Models.Spt.Config; using SPTarkov.Server.Core.Models.Spt.Mod; using SPTarkov.Server.Core.Models.Utils; @@ -15,7 +14,6 @@ public class BackupService protected const string _profileDir = "./user/profiles"; protected readonly List _activeServerMods; - protected ApplicationContext _applicationContext; protected BackupConfig _backupConfig; // Runs Init() every x minutes @@ -32,15 +30,13 @@ public class BackupService JsonUtil jsonUtil, TimeUtil timeUtil, ConfigServer configServer, - FileUtil fileUtil, - ApplicationContext applicationContext + FileUtil fileUtil ) { _logger = logger; _jsonUtil = jsonUtil; _timeUtil = timeUtil; _fileUtil = fileUtil; - _applicationContext = applicationContext; _loadedMods = loadedMods; _activeServerMods = GetActiveServerMods(); diff --git a/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs b/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs index 407da4bb..bbf207f2 100644 --- a/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs @@ -1,5 +1,4 @@ using SPTarkov.DI.Annotations; -using SPTarkov.Server.Core.Context; using SPTarkov.Server.Core.Generators; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Eft.Common; @@ -21,7 +20,7 @@ namespace SPTarkov.Server.Core.Services; [Injectable(InjectionType.Singleton)] public class LocationLifecycleService { - protected ApplicationContext _applicationContext; + protected ProfileActivityService _profileActivityService; protected BotGenerationCacheService _botGenerationCacheService; protected BotLootCacheService _botLootCacheService; protected BotNameService _botNameService; @@ -64,7 +63,7 @@ public class LocationLifecycleService DatabaseService databaseService, ProfileHelper profileHelper, HashUtil hashUtil, - ApplicationContext applicationContext, + ProfileActivityService profileActivityService, BotGenerationCacheService botGenerationCacheService, BotNameService botNameService, ICloner cloner, @@ -94,7 +93,7 @@ public class LocationLifecycleService _databaseService = databaseService; _profileHelper = profileHelper; _hashUtil = hashUtil; - _applicationContext = applicationContext; + _profileActivityService = profileActivityService; _botGenerationCacheService = botGenerationCacheService; _botNameService = botNameService; _cloner = cloner; @@ -150,7 +149,7 @@ public class LocationLifecycleService { InsuredItems = playerProfile.CharacterData.PmcData.InsuredItems }, - LocationLoot = GenerateLocationAndLoot(request.Location, !request.ShouldSkipLootGeneration ?? true), + LocationLoot = GenerateLocationAndLoot(sessionId, request.Location, !request.ShouldSkipLootGeneration ?? true), TransitionType = TransitionType.NONE, Transition = new Transition { @@ -169,9 +168,7 @@ public class LocationLifecycleService } // Get data stored at end of previous raid (if any) - var transitionData = _applicationContext - .GetLatestValue(ContextVariableType.TRANSIT_INFO) - ?.GetValue(); + var transitionData = _profileActivityService.GetProfileActivityRaidData(sessionId)?.LocationTransit; if (transitionData is not null) { @@ -184,7 +181,7 @@ public class LocationLifecycleService result.Transition.VisitedLocations.Add(transitionData.SptLastVisitedLocation); // Complete, clean up as no longer needed - _applicationContext.ClearValues(ContextVariableType.TRANSIT_INFO); + _profileActivityService.GetProfileActivityRaidData(sessionId).LocationTransit = null; } // Apply changes from pmcConfig to bot hostility values @@ -338,7 +335,7 @@ public class LocationLifecycleService /// /// Generate a maps base location (cloned) and loot /// - public virtual LocationBase GenerateLocationAndLoot(string name, bool generateLoot = true) + public virtual LocationBase GenerateLocationAndLoot(string sessionId, string name, bool generateLoot = true) { var location = _databaseService.GetLocation(name); var locationBaseClone = _cloner.Clone(location.Base); @@ -363,9 +360,7 @@ public class LocationLifecycleService // Adjust raid based on whether this is a scav run LocationConfig? locationConfigClone = null; - var raidAdjustments = _applicationContext - .GetLatestValue(ContextVariableType.RAID_ADJUSTMENTS) - ?.GetValue(); + var raidAdjustments = _profileActivityService.GetProfileActivityRaidData(sessionId).RaidAdjustments; if (raidAdjustments is not null) { locationConfigClone = _cloner.Clone(_locationConfig); // Clone values so they can be used to reset originals later @@ -405,7 +400,7 @@ public class LocationLifecycleService _locationConfig.StaticLootMultiplier = locationConfigClone.StaticLootMultiplier; _locationConfig.LooseLootMultiplier = locationConfigClone.LooseLootMultiplier; - _applicationContext.ClearValues(ContextVariableType.RAID_ADJUSTMENTS); + _profileActivityService.GetProfileActivityRaidData(sessionId).RaidAdjustments = null; } return locationBaseClone; @@ -457,7 +452,7 @@ public class LocationLifecycleService // TODO - Persist each players last visited location history over multiple transits, e.g using InMemoryCacheService, need to take care to not let data get stored forever // Store transfer data for later use in `startLocalRaid()` when next raid starts request.LocationTransit.SptExitName = request.Results.ExitName; - _applicationContext.AddValue(ContextVariableType.TRANSIT_INFO, request.LocationTransit); + _profileActivityService.GetProfileActivityRaidData(sessionId).LocationTransit = request.LocationTransit; } if (!isPmc) diff --git a/Libraries/SPTarkov.Server.Core/Services/ProfileActivityService.cs b/Libraries/SPTarkov.Server.Core/Services/ProfileActivityService.cs index b1b097cf..5b17d768 100644 --- a/Libraries/SPTarkov.Server.Core/Services/ProfileActivityService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/ProfileActivityService.cs @@ -1,5 +1,6 @@ using System.Collections.Concurrent; using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Models.Spt.Services; using SPTarkov.Server.Core.Utils; namespace SPTarkov.Server.Core.Services; @@ -9,7 +10,50 @@ public class ProfileActivityService( TimeUtil timeUtil ) { - private readonly ConcurrentDictionary _profileActivityTimestamps = new(); + private readonly ConcurrentDictionary _activeProfiles = []; + + public void AddActiveProfile(string sessionId, long clientStartedTimestamp) + { + _activeProfiles.AddOrUpdate( + sessionId, + // On add value + key => new ProfileActivityData + { + ClientStartedTimestamp = clientStartedTimestamp, + LastActive = timeUtil.GetTimeStamp() + }, + // On Update value, client was started before but crashed or user restarted + (key, existingValue) => + { + existingValue.ClientStartedTimestamp = clientStartedTimestamp; + existingValue.LastActive = timeUtil.GetTimeStamp(); + existingValue.RaidData = null; + return existingValue; + }); + } + + // Yes this is terrible, the other alternative is re-doing half of bot-gen which is currently doing guess-work anyway + public ProfileActivityRaidData? GetFirstProfileActivityRaidData() + { + if (!_activeProfiles.IsEmpty) + { + return _activeProfiles.First().Value.RaidData; + } + + return null; + } + + public ProfileActivityRaidData? GetProfileActivityRaidData(string sessionId) + { + if (_activeProfiles.TryGetValue(sessionId, out var currentActiveProfile)) + { + currentActiveProfile.RaidData ??= new(); + + return currentActiveProfile.RaidData; + } + + return null; + } /// /// Was the requested profile active within the last x minutes @@ -19,13 +63,13 @@ public class ProfileActivityService( /// True when profile was active within past x minutes public bool ActiveWithinLastMinutes(string sessionId, int minutes) { - if (!_profileActivityTimestamps.TryGetValue(sessionId, out var storedActivityTimestamp)) + if (!_activeProfiles.TryGetValue(sessionId, out var profileActivity)) { // No record, exit early return false; } - return timeUtil.GetTimeStamp() - storedActivityTimestamp < minutes * 60; + return timeUtil.GetTimeStamp() - profileActivity.LastActive < minutes * 60; } /// @@ -38,10 +82,10 @@ public class ProfileActivityService( var currentTimestamp = timeUtil.GetTimeStamp(); var result = new List(); - foreach (var (sessionId, lastActivityTimestamp) in _profileActivityTimestamps) + foreach (var (sessionId, activeProfile) in _activeProfiles) { // Profile was active in last x minutes, add to return list - if (currentTimestamp - lastActivityTimestamp < minutes * 60) + if (currentTimestamp - activeProfile.LastActive < minutes * 60) { result.Add(sessionId); } @@ -56,9 +100,9 @@ public class ProfileActivityService( /// Profile to update public void SetActivityTimestamp(string sessionId) { - if(!_profileActivityTimestamps.TryAdd(sessionId, timeUtil.GetTimeStamp())) + if(_activeProfiles.TryGetValue(sessionId, out var currentActiveProfile)) { - _profileActivityTimestamps[sessionId] = timeUtil.GetTimeStamp(); + currentActiveProfile.LastActive = timeUtil.GetTimeStamp(); } } } diff --git a/Libraries/SPTarkov.Server.Core/Services/RaidTimeAdjustmentService.cs b/Libraries/SPTarkov.Server.Core/Services/RaidTimeAdjustmentService.cs index b45e80ff..f6998a95 100644 --- a/Libraries/SPTarkov.Server.Core/Services/RaidTimeAdjustmentService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/RaidTimeAdjustmentService.cs @@ -1,5 +1,4 @@ using SPTarkov.DI.Annotations; -using SPTarkov.Server.Core.Context; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Eft.Common; using SPTarkov.Server.Core.Models.Eft.Game; @@ -18,7 +17,7 @@ public class RaidTimeAdjustmentService( DatabaseService _databaseService, RandomUtil _randomUtil, WeightedRandomHelper _weightedRandomHelper, - ApplicationContext _applicationContext, + ProfileActivityService _profileActivityService, ConfigServer _configServer ) { @@ -206,7 +205,7 @@ public class RaidTimeAdjustmentService( } // Store state to use in loot generation - _applicationContext.AddValue(ContextVariableType.RAID_ADJUSTMENTS, result); + _profileActivityService.GetProfileActivityRaidData(sessionId).RaidAdjustments = result; return result; } diff --git a/SPTarkov.Server/Program.cs b/SPTarkov.Server/Program.cs index 2ae6662a..8bead8f3 100644 --- a/SPTarkov.Server/Program.cs +++ b/SPTarkov.Server/Program.cs @@ -3,9 +3,6 @@ using System.Runtime.InteropServices; using SPTarkov.Common.Semver; using SPTarkov.Common.Semver.Implementations; using SPTarkov.DI; -using SPTarkov.Server.Core.Context; -using SPTarkov.Server.Core.Helpers; -using SPTarkov.Server.Core.Models.External; using SPTarkov.Server.Core.Models.Spt.Mod; using SPTarkov.Server.Core.Models.Utils; using SPTarkov.Server.Core.Servers; @@ -52,9 +49,6 @@ public static class Program { SetConsoleOutputMode(); - var appContext = serviceProvider.GetService(); - appContext?.AddValue(ContextVariableType.SERVICE_PROVIDER, serviceProvider); - // Get the Built app and run it var app = serviceProvider.GetService();