From fb31786ee2724117485cd409a916e431f629bfd0 Mon Sep 17 00:00:00 2001 From: Chomp Date: Sat, 7 Jun 2025 12:17:28 +0100 Subject: [PATCH] Updated profile templates to be a dictionary, cleaned up all uses of it throughout code Added `profileHelper.GetProfileTemplateForSide` --- .../Controllers/LauncherController.cs | 32 +++------ .../Controllers/LauncherV2Controller.cs | 18 +---- .../Helpers/HealthHelper.cs | 22 +++--- .../Helpers/ProfileHelper.cs | 19 +++++ .../Helpers/TraderHelper.cs | 40 ++++++----- .../Eft/Common/Tables/ProfileTemplate.cs | 69 ------------------- .../Models/Spt/Templates/Templates.cs | 2 +- .../Services/CreateProfileService.cs | 5 +- .../Services/DatabaseService.cs | 2 +- 9 files changed, 64 insertions(+), 145 deletions(-) diff --git a/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs b/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs index 21bf90ab..1b6ffb44 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs @@ -1,4 +1,3 @@ -using SPTarkov.Common.Extensions; using SPTarkov.DI.Annotations; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Eft.Common.Tables; @@ -38,43 +37,30 @@ public class LauncherController( public ConnectResponse Connect() { // Get all possible profile types + filter out any that are blacklisted - - var profiles = typeof(ProfileTemplates).GetProperties() - .Where(p => p.CanWrite) - .Select(p => p.GetJsonName()) - .Where(profileName => !_coreConfig.Features.CreateNewProfileTypesBlacklist.Contains(profileName)) - .ToList(); + var profileTemplates = _databaseService.GetProfileTemplates() + .Where(profile => !_coreConfig.Features.CreateNewProfileTypesBlacklist.Contains(profile.Key)) + .ToDictionary(); return new ConnectResponse { BackendUrl = _httpServerHelper.GetBackendUrl(), Name = _coreConfig.ServerName, - Editions = profiles, - ProfileDescriptions = GetProfileDescriptions() + Editions = profileTemplates.Select(x => x.Key).ToList(), + ProfileDescriptions = GetProfileDescriptions(profileTemplates) }; } /// /// Get descriptive text for each of the profile editions a player can choose, keyed by profile.json profile type e.g. "Edge Of Darkness" /// + /// Profiles to get descriptions of /// Dictionary of profile types with related descriptive text - protected Dictionary GetProfileDescriptions() + protected Dictionary GetProfileDescriptions(Dictionary profileTemplates) { var result = new Dictionary(); - var dbProfiles = _databaseService.GetProfiles(); - foreach (var templatesProperty in typeof(ProfileTemplates).GetProperties() - .Where(p => p.CanWrite - && !string.Equals(p.Name, "extensiondata", StringComparison.InvariantCultureIgnoreCase))) + foreach (var (profileKey, profile) in profileTemplates) { - var propertyValue = templatesProperty.GetValue(dbProfiles); - if (propertyValue == null) - { - _logger.Warning(_localisationService.GetText("launcher-missing_property", templatesProperty.Name)); - continue; - } - - var casterPropertyValue = propertyValue as ProfileSides; - result[templatesProperty.GetJsonName()] = _localisationService.GetText(casterPropertyValue?.DescriptionLocaleKey!); + result.TryAdd(profileKey, _localisationService.GetText(profile.DescriptionLocaleKey)); } return result; diff --git a/Libraries/SPTarkov.Server.Core/Controllers/LauncherV2Controller.cs b/Libraries/SPTarkov.Server.Core/Controllers/LauncherV2Controller.cs index 9e8a69df..9d5ea553 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/LauncherV2Controller.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/LauncherV2Controller.cs @@ -1,6 +1,4 @@ -using SPTarkov.Common.Extensions; using SPTarkov.DI.Annotations; -using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Eft.Launcher; using SPTarkov.Server.Core.Models.Eft.Profile; using SPTarkov.Server.Core.Models.Spt.Config; @@ -46,21 +44,11 @@ public class LauncherV2Controller( public Dictionary Types() { var result = new Dictionary(); - var dbProfiles = _databaseService.GetProfiles(); + var dbProfiles = _databaseService.GetProfileTemplates(); - foreach (var templatesProperty in typeof(ProfileTemplates).GetProperties() - .Where(p => p.CanWrite - && !string.Equals(p.Name, "extensiondata", StringComparison.InvariantCultureIgnoreCase))) + foreach (var profileKvP in dbProfiles) { - var propertyValue = templatesProperty.GetValue(dbProfiles); - if (propertyValue == null) - { - _logger.Warning(_localisationService.GetText("launcher-missing_property", templatesProperty.Name)); - continue; - } - - var casterPropertyValue = propertyValue as ProfileSides; - result[templatesProperty.GetJsonName()] = _localisationService.GetText(casterPropertyValue?.DescriptionLocaleKey!); + result.TryAdd(profileKvP.Key, _localisationService.GetText(profileKvP.Value.DescriptionLocaleKey)); } return result; diff --git a/Libraries/SPTarkov.Server.Core/Helpers/HealthHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/HealthHelper.cs index aa91c8e3..8470b119 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/HealthHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/HealthHelper.cs @@ -1,11 +1,9 @@ -using SPTarkov.Common.Extensions; using SPTarkov.DI.Annotations; using SPTarkov.Server.Core.Models.Eft.Common; using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Eft.Profile; using SPTarkov.Server.Core.Models.Spt.Config; using SPTarkov.Server.Core.Servers; -using SPTarkov.Server.Core.Services; using SPTarkov.Server.Core.Utils; using BodyPartHealth = SPTarkov.Server.Core.Models.Eft.Common.Tables.BodyPartHealth; using Vitality = SPTarkov.Server.Core.Models.Eft.Profile.Vitality; @@ -16,7 +14,7 @@ namespace SPTarkov.Server.Core.Helpers; public class HealthHelper( TimeUtil _timeUtil, SaveServer _saveServer, - DatabaseService _databaseService, + ProfileHelper _profileHelper, ConfigServer _configServer ) { @@ -128,8 +126,6 @@ public class HealthHelper( /// Post raid data /// Session id /// Is player dead - /// Should effects be added to profile (default - true) - /// Should all prior effects be removed before apply new ones (default - true) public void UpdateProfileHealthPostRaid( PmcData pmcData, BotBaseHealth postRaidHealth, @@ -139,16 +135,14 @@ public class HealthHelper( var fullProfile = _saveServer.GetProfile(sessionID); var profileEdition = fullProfile.ProfileInfo.Edition; var profileSide = fullProfile.CharacterData.PmcData.Info.Side; + + // Get matching 'side e.g. USEC + var matchingSide = _profileHelper.GetProfileTemplateForSide(profileEdition, profileSide); - var defaultTemperature = - _databaseService.GetProfiles() - .GetByJsonProp(profileEdition) - .GetByJsonProp(profileSide.ToLower()) - ?.Character?.Health?.Temperature ?? - new CurrentMinMax - { - Current = 36.6 - }; + var defaultTemperature = matchingSide?.Character?.Health?.Temperature ?? new CurrentMinMax + { + Current = 36.6 + }; StoreHydrationEnergyTempInProfile( fullProfile, diff --git a/Libraries/SPTarkov.Server.Core/Helpers/ProfileHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/ProfileHelper.cs index a1cd6f26..431ce184 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/ProfileHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/ProfileHelper.cs @@ -754,4 +754,23 @@ public class ProfileHelper( fullProfile.SptData.ExtraRepeatableQuests[repeatableId] += rewardValue; } } + + /// + /// Get a profile template by the account and side + /// + /// Edition of profile desired, e.g. "Standard" + /// Side of profile desired, e.g. "Bear" + /// + public TemplateSide GetProfileTemplateForSide(string accountEdition, string side) + { + var profileTemplates = _databaseService.GetProfileTemplates(); + + // Get matching profile 'type' e.g. 'standard' + profileTemplates.TryGetValue(accountEdition, out var matchingProfileTemplate); + + // Get matching profile by 'side' e.g. USEC + return string.Equals(side, "bear", StringComparison.OrdinalIgnoreCase) + ? matchingProfileTemplate.Bear + : matchingProfileTemplate.Usec; + } } diff --git a/Libraries/SPTarkov.Server.Core/Helpers/TraderHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/TraderHelper.cs index 7f42f161..33912f6a 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/TraderHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/TraderHelper.cs @@ -1,4 +1,4 @@ -using SPTarkov.Common.Extensions; +using System.Security.Principal; using SPTarkov.DI.Annotations; using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Eft.Common; @@ -136,7 +136,7 @@ public class TraderHelper( /// trader id to reset public void ResetTrader(string sessionID, string traderID) { - var profiles = _databaseService.GetProfiles(); + var profiles = _databaseService.GetProfileTemplates(); var trader = _databaseService.GetTrader(traderID); var fullProfile = _profileHelper.GetFullProfile(sessionID); @@ -145,34 +145,34 @@ public class TraderHelper( throw new Exception(_localisationService.GetText("trader-unable_to_find_profile_by_id", sessionID)); } + // Get matching profile 'type' e.g. 'standard' + profiles.TryGetValue(fullProfile.ProfileInfo.Edition, out var matchingProfileTemplate); var pmcData = fullProfile.CharacterData.PmcData; - var rawProfileTemplate = profiles.GetByJsonProp(fullProfile.ProfileInfo.Edition) - .GetByJsonProp(pmcData.Info.Side.ToLower()) - .Trader; + var matchingSide = _profileHelper.GetProfileTemplateForSide(fullProfile.ProfileInfo.Edition, pmcData.Info.Side); + + // Profiles trader settings + var profileTemplateTraderData = matchingSide.Trader; var newTraderData = new TraderInfo { Disabled = false, - LoyaltyLevel = rawProfileTemplate.InitialLoyaltyLevel.GetValueOrDefault(traderID, 1), - SalesSum = rawProfileTemplate.InitialSalesSum, - Standing = GetStartingStanding(traderID, rawProfileTemplate), + LoyaltyLevel = profileTemplateTraderData.InitialLoyaltyLevel.GetValueOrDefault(traderID, 1), + SalesSum = profileTemplateTraderData.InitialSalesSum, + Standing = GetStartingStanding(traderID, profileTemplateTraderData), NextResupply = trader.Base.NextResupply, Unlocked = trader.Base.UnlockedByDefault }; - if (!pmcData.TradersInfo.TryAdd(traderID, newTraderData)) - { - pmcData.TradersInfo[traderID] = newTraderData; - } - + // Add trader to profile if it doesn't already + pmcData.TradersInfo.TryAdd(traderID, newTraderData); // Check if trader should be locked by default - if (rawProfileTemplate.LockedByDefaultOverride?.Contains(traderID) ?? false) + if (profileTemplateTraderData.LockedByDefaultOverride?.Contains(traderID) ?? false) { pmcData.TradersInfo[traderID].Unlocked = true; } - if (rawProfileTemplate.PurchaseAllClothingByDefaultForTrader?.Contains(traderID) ?? false) + if (profileTemplateTraderData.PurchaseAllClothingByDefaultForTrader?.Contains(traderID) ?? false) { // Get traders clothing var clothing = _databaseService.GetTrader(traderID).Suits; @@ -186,16 +186,18 @@ public class TraderHelper( } } - if ((rawProfileTemplate.FleaBlockedDays ?? 0) > 0) + // Template has flea block + if ((profileTemplateTraderData.FleaBlockedDays ?? 0) > 0) { - var newBanDateTime = _timeUtil.GetTimeStampFromNowDays(rawProfileTemplate.FleaBlockedDays ?? 0); - var existingBan = pmcData.Info.Bans.FirstOrDefault(ban => ban.BanType == BanType.RagFair); + var newBanDateTime = _timeUtil.GetTimeStampFromNowDays(profileTemplateTraderData.FleaBlockedDays ?? 0); + var existingBan = pmcData.Info.Bans?.FirstOrDefault(ban => ban.BanType == BanType.RagFair); if (existingBan is not null) { existingBan.DateTime = newBanDateTime; } else { + pmcData.Info.Bans ??= []; pmcData.Info.Bans.Add( new Ban { @@ -208,7 +210,7 @@ public class TraderHelper( if (traderID == Traders.JAEGER) { - pmcData.TradersInfo[traderID].Unlocked = rawProfileTemplate.JaegerUnlocked; + pmcData.TradersInfo[traderID].Unlocked = profileTemplateTraderData.JaegerUnlocked; } } diff --git a/Libraries/SPTarkov.Server.Core/Models/Eft/Common/Tables/ProfileTemplate.cs b/Libraries/SPTarkov.Server.Core/Models/Eft/Common/Tables/ProfileTemplate.cs index 39e5b498..8a15511e 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Eft/Common/Tables/ProfileTemplate.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Eft/Common/Tables/ProfileTemplate.cs @@ -3,75 +3,6 @@ using SPTarkov.Server.Core.Models.Eft.Profile; namespace SPTarkov.Server.Core.Models.Eft.Common.Tables; -public record ProfileTemplates -{ - [JsonExtensionData] - public Dictionary ExtensionData { get; set; } - - [JsonPropertyName("Standard")] - public ProfileSides? Standard - { - get; - set; - } - - [JsonPropertyName("Left Behind")] - public ProfileSides? LeftBehind - { - get; - set; - } - - [JsonPropertyName("Prepare To Escape")] - public ProfileSides? PrepareToEscape - { - get; - set; - } - - [JsonPropertyName("Edge Of Darkness")] - public ProfileSides? EdgeOfDarkness - { - get; - set; - } - - [JsonPropertyName("Unheard")] - public ProfileSides? Unheard - { - get; - set; - } - - [JsonPropertyName("Tournament")] - public ProfileSides? Tournament - { - get; - set; - } - - [JsonPropertyName("SPT Developer")] - public ProfileSides? SPTDeveloper - { - get; - set; - } - - [JsonPropertyName("SPT Easy start")] - public ProfileSides? SPTEasyStart - { - get; - set; - } - - [JsonPropertyName("SPT Zero to hero")] - public ProfileSides? SPTZeroToHero - { - get; - set; - } -} - public record ProfileSides { [JsonExtensionData] diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Templates/Templates.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Templates/Templates.cs index c984ebd1..cbe3206d 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Templates/Templates.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Templates/Templates.cs @@ -69,7 +69,7 @@ public record Templates /// The profile templates listed in the launcher on profile creation, split by account type (e.g. Standard) then side (e.g. bear/usec) /// [JsonPropertyName("profiles")] - public ProfileTemplates? Profiles + public Dictionary? Profiles { get; set; diff --git a/Libraries/SPTarkov.Server.Core/Services/CreateProfileService.cs b/Libraries/SPTarkov.Server.Core/Services/CreateProfileService.cs index 941fbc23..93050ffd 100644 --- a/Libraries/SPTarkov.Server.Core/Services/CreateProfileService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/CreateProfileService.cs @@ -43,9 +43,8 @@ public class CreateProfileService( public string CreateProfile(string sessionId, ProfileCreateRequestData request) { var account = _cloner.Clone(_saveServer.GetProfile(sessionId)); - var profileTemplateClone = _cloner.Clone( - _databaseService.GetProfiles()?.GetByJsonProp(account.ProfileInfo.Edition)?.GetByJsonProp(request.Side.ToLower()) - ); + var profileTemplateClone = _cloner.Clone(_profileHelper.GetProfileTemplateForSide(account.ProfileInfo.Edition, request.Side)); + var pmcData = profileTemplateClone.Character; // Delete existing profile diff --git a/Libraries/SPTarkov.Server.Core/Services/DatabaseService.cs b/Libraries/SPTarkov.Server.Core/Services/DatabaseService.cs index cdc06e1b..12d073c7 100644 --- a/Libraries/SPTarkov.Server.Core/Services/DatabaseService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/DatabaseService.cs @@ -257,7 +257,7 @@ public class DatabaseService( } /// assets/database/templates/profiles.json - public ProfileTemplates GetProfiles() + public Dictionary GetProfileTemplates() { if (_databaseServer.GetTables().Templates?.Profiles == null) {