diff --git a/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs b/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs index 5b801b21..69dffde9 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs @@ -8,6 +8,7 @@ using SPTarkov.Server.Core.Models.Spt.Config; using SPTarkov.Server.Core.Models.Spt.Mod; using SPTarkov.Server.Core.Servers; using SPTarkov.Server.Core.Services; +using SPTarkov.Server.Core.Services.Mod; using SPTarkov.Server.Core.Utils; using Info = SPTarkov.Server.Core.Models.Eft.Profile.Info; @@ -22,6 +23,7 @@ public class LauncherController( ProfileHelper profileHelper, DatabaseService databaseService, ServerLocalisationService serverLocalisationService, + ProfileDataService profileDataService, ConfigServer configServer ) { @@ -168,6 +170,9 @@ public class LauncherController( var profileInfo = saveServer.GetProfile(sessionId).ProfileInfo; profileInfo!.Edition = info.Edition; profileInfo.IsWiped = true; + + // Clear any data modders may have stored + profileDataService.ClearProfileData(sessionId); } return sessionId; diff --git a/Libraries/SPTarkov.Server.Core/Services/Mod/ProfileDataService.cs b/Libraries/SPTarkov.Server.Core/Services/Mod/ProfileDataService.cs index 486b427d..288be464 100644 --- a/Libraries/SPTarkov.Server.Core/Services/Mod/ProfileDataService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/Mod/ProfileDataService.cs @@ -11,22 +11,27 @@ public class ProfileDataService(ISptLogger logger, FileUtil protected const string ProfileDataFilepath = "user/profileData/"; private readonly ConcurrentDictionary _profileDataCache = new(); + /// + /// Check if a specfici mod file exists for a profile + /// + /// Profile to look up + /// Name of json file to look up public bool ProfileDataExists(string profileId, string modKey) { - return fileUtil.FileExists($"{ProfileDataFilepath}{profileId}/{modKey}.json"); + return fileUtil.FileExists(Path.Combine(ProfileDataFilepath, profileId, $"{modKey}.json")); } public T? GetProfileData(string profileId, string modKey) { - var profileDataKey = $"{profileId}:{modKey}"; + var profileDataKey = GetCacheKey(profileId, modKey); if (!_profileDataCache.TryGetValue(profileDataKey, out var value)) { - if (fileUtil.FileExists($"{ProfileDataFilepath}{profileId}/{modKey}.json")) + if (ProfileDataExists(profileId, modKey)) { - value = jsonUtil.Deserialize(fileUtil.ReadFile($"{ProfileDataFilepath}{profileId}/{modKey}.json")); + value = jsonUtil.Deserialize(fileUtil.ReadFile(Path.Combine(ProfileDataFilepath, profileId, $"{modKey}.json"))); if (value != null) { - _profileDataCache[$"{profileId}:{modKey}"] = value; + _profileDataCache[GetCacheKey(profileId, modKey)] = value; } } else @@ -42,13 +47,45 @@ public class ProfileDataService(ISptLogger logger, FileUtil { ArgumentNullException.ThrowIfNull(profileData); - var data = jsonUtil.Serialize(profileData, profileData.GetType(), true); - if (data == null) + var data = + jsonUtil.Serialize(profileData, profileData.GetType(), true) + ?? throw new Exception("The profile data when serialized resulted in a null value"); + + _profileDataCache[GetCacheKey(profileId, modKey)] = profileData; + + fileUtil.WriteFile(Path.Combine(ProfileDataFilepath, profileId, $"{modKey}.json"), data); + } + + /// + /// Clear all data for a profile + /// + /// Id of profile to delete files for + public void ClearProfileData(string profileId) + { + if (!fileUtil.DirectoryExists(Path.Combine(ProfileDataFilepath, profileId))) { - throw new Exception("The profile data when serialized resulted in a null value"); + return; } - _profileDataCache[$"{profileId}:{modKey}"] = profileData; - fileUtil.WriteFile($"{ProfileDataFilepath}{profileId}/{modKey}.json", data); + var profileFiles = fileUtil.GetFiles(Path.Combine(ProfileDataFilepath, profileId)); + foreach (var filepPath in profileFiles) + { + fileUtil.DeleteFile(filepPath); + } + + var keysInCacheToRemove = _profileDataCache.Keys.Where(key => key.StartsWith($"{profileId}:")).ToList(); // ToList so we can iterate over results without modifying collection + + foreach (var key in keysInCacheToRemove) + { + _profileDataCache.TryRemove(key, out _); + } + } + + /// + /// Get the cache key in specific format + /// + protected string GetCacheKey(string profileId, string modKey) + { + return $"{profileId}:{modKey}"; } }