Updated profile templates to be a dictionary, cleaned up all uses of it throughout code

Added `profileHelper.GetProfileTemplateForSide`
This commit is contained in:
Chomp
2025-06-07 12:17:28 +01:00
parent e444a9a3b6
commit fb31786ee2
9 changed files with 64 additions and 145 deletions
@@ -1,4 +1,3 @@
using SPTarkov.Common.Extensions;
using SPTarkov.DI.Annotations; using SPTarkov.DI.Annotations;
using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Helpers;
using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Eft.Common.Tables;
@@ -38,43 +37,30 @@ public class LauncherController(
public ConnectResponse Connect() public ConnectResponse Connect()
{ {
// Get all possible profile types + filter out any that are blacklisted // Get all possible profile types + filter out any that are blacklisted
var profileTemplates = _databaseService.GetProfileTemplates()
var profiles = typeof(ProfileTemplates).GetProperties() .Where(profile => !_coreConfig.Features.CreateNewProfileTypesBlacklist.Contains(profile.Key))
.Where(p => p.CanWrite) .ToDictionary();
.Select(p => p.GetJsonName())
.Where(profileName => !_coreConfig.Features.CreateNewProfileTypesBlacklist.Contains(profileName))
.ToList();
return new ConnectResponse return new ConnectResponse
{ {
BackendUrl = _httpServerHelper.GetBackendUrl(), BackendUrl = _httpServerHelper.GetBackendUrl(),
Name = _coreConfig.ServerName, Name = _coreConfig.ServerName,
Editions = profiles, Editions = profileTemplates.Select(x => x.Key).ToList(),
ProfileDescriptions = GetProfileDescriptions() ProfileDescriptions = GetProfileDescriptions(profileTemplates)
}; };
} }
/// <summary> /// <summary>
/// Get descriptive text for each of the profile editions a player can choose, keyed by profile.json profile type e.g. "Edge Of Darkness" /// Get descriptive text for each of the profile editions a player can choose, keyed by profile.json profile type e.g. "Edge Of Darkness"
/// </summary> /// </summary>
/// <param name="profileTemplates">Profiles to get descriptions of</param>
/// <returns>Dictionary of profile types with related descriptive text</returns> /// <returns>Dictionary of profile types with related descriptive text</returns>
protected Dictionary<string, string> GetProfileDescriptions() protected Dictionary<string, string> GetProfileDescriptions(Dictionary<string, ProfileSides> profileTemplates)
{ {
var result = new Dictionary<string, string>(); var result = new Dictionary<string, string>();
var dbProfiles = _databaseService.GetProfiles(); foreach (var (profileKey, profile) in profileTemplates)
foreach (var templatesProperty in typeof(ProfileTemplates).GetProperties()
.Where(p => p.CanWrite
&& !string.Equals(p.Name, "extensiondata", StringComparison.InvariantCultureIgnoreCase)))
{ {
var propertyValue = templatesProperty.GetValue(dbProfiles); result.TryAdd(profileKey, _localisationService.GetText(profile.DescriptionLocaleKey));
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!);
} }
return result; return result;
@@ -1,6 +1,4 @@
using SPTarkov.Common.Extensions;
using SPTarkov.DI.Annotations; 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.Launcher;
using SPTarkov.Server.Core.Models.Eft.Profile; using SPTarkov.Server.Core.Models.Eft.Profile;
using SPTarkov.Server.Core.Models.Spt.Config; using SPTarkov.Server.Core.Models.Spt.Config;
@@ -46,21 +44,11 @@ public class LauncherV2Controller(
public Dictionary<string, string> Types() public Dictionary<string, string> Types()
{ {
var result = new Dictionary<string, string>(); var result = new Dictionary<string, string>();
var dbProfiles = _databaseService.GetProfiles(); var dbProfiles = _databaseService.GetProfileTemplates();
foreach (var templatesProperty in typeof(ProfileTemplates).GetProperties() foreach (var profileKvP in dbProfiles)
.Where(p => p.CanWrite
&& !string.Equals(p.Name, "extensiondata", StringComparison.InvariantCultureIgnoreCase)))
{ {
var propertyValue = templatesProperty.GetValue(dbProfiles); result.TryAdd(profileKvP.Key, _localisationService.GetText(profileKvP.Value.DescriptionLocaleKey));
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!);
} }
return result; return result;
@@ -1,11 +1,9 @@
using SPTarkov.Common.Extensions;
using SPTarkov.DI.Annotations; using SPTarkov.DI.Annotations;
using SPTarkov.Server.Core.Models.Eft.Common; using SPTarkov.Server.Core.Models.Eft.Common;
using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Eft.Common.Tables;
using SPTarkov.Server.Core.Models.Eft.Profile; using SPTarkov.Server.Core.Models.Eft.Profile;
using SPTarkov.Server.Core.Models.Spt.Config; using SPTarkov.Server.Core.Models.Spt.Config;
using SPTarkov.Server.Core.Servers; using SPTarkov.Server.Core.Servers;
using SPTarkov.Server.Core.Services;
using SPTarkov.Server.Core.Utils; using SPTarkov.Server.Core.Utils;
using BodyPartHealth = SPTarkov.Server.Core.Models.Eft.Common.Tables.BodyPartHealth; using BodyPartHealth = SPTarkov.Server.Core.Models.Eft.Common.Tables.BodyPartHealth;
using Vitality = SPTarkov.Server.Core.Models.Eft.Profile.Vitality; using Vitality = SPTarkov.Server.Core.Models.Eft.Profile.Vitality;
@@ -16,7 +14,7 @@ namespace SPTarkov.Server.Core.Helpers;
public class HealthHelper( public class HealthHelper(
TimeUtil _timeUtil, TimeUtil _timeUtil,
SaveServer _saveServer, SaveServer _saveServer,
DatabaseService _databaseService, ProfileHelper _profileHelper,
ConfigServer _configServer ConfigServer _configServer
) )
{ {
@@ -128,8 +126,6 @@ public class HealthHelper(
/// <param name="postRaidHealth">Post raid data</param> /// <param name="postRaidHealth">Post raid data</param>
/// <param name="sessionID">Session id</param> /// <param name="sessionID">Session id</param>
/// <param name="isDead">Is player dead</param> /// <param name="isDead">Is player dead</param>
/// <param name="addEffects">Should effects be added to profile (default - true)</param>
/// <param name="deleteExistingEffects">Should all prior effects be removed before apply new ones (default - true)</param>
public void UpdateProfileHealthPostRaid( public void UpdateProfileHealthPostRaid(
PmcData pmcData, PmcData pmcData,
BotBaseHealth postRaidHealth, BotBaseHealth postRaidHealth,
@@ -139,16 +135,14 @@ public class HealthHelper(
var fullProfile = _saveServer.GetProfile(sessionID); var fullProfile = _saveServer.GetProfile(sessionID);
var profileEdition = fullProfile.ProfileInfo.Edition; var profileEdition = fullProfile.ProfileInfo.Edition;
var profileSide = fullProfile.CharacterData.PmcData.Info.Side; var profileSide = fullProfile.CharacterData.PmcData.Info.Side;
// Get matching 'side e.g. USEC
var matchingSide = _profileHelper.GetProfileTemplateForSide(profileEdition, profileSide);
var defaultTemperature = var defaultTemperature = matchingSide?.Character?.Health?.Temperature ?? new CurrentMinMax
_databaseService.GetProfiles() {
.GetByJsonProp<ProfileSides>(profileEdition) Current = 36.6
.GetByJsonProp<TemplateSide>(profileSide.ToLower()) };
?.Character?.Health?.Temperature ??
new CurrentMinMax
{
Current = 36.6
};
StoreHydrationEnergyTempInProfile( StoreHydrationEnergyTempInProfile(
fullProfile, fullProfile,
@@ -754,4 +754,23 @@ public class ProfileHelper(
fullProfile.SptData.ExtraRepeatableQuests[repeatableId] += rewardValue; fullProfile.SptData.ExtraRepeatableQuests[repeatableId] += rewardValue;
} }
} }
/// <summary>
/// Get a profile template by the account and side
/// </summary>
/// <param name="accountEdition">Edition of profile desired, e.g. "Standard"</param>
/// <param name="side">Side of profile desired, e.g. "Bear"</param>
/// <returns></returns>
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;
}
} }
@@ -1,4 +1,4 @@
using SPTarkov.Common.Extensions; using System.Security.Principal;
using SPTarkov.DI.Annotations; using SPTarkov.DI.Annotations;
using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Eft.Common; using SPTarkov.Server.Core.Models.Eft.Common;
@@ -136,7 +136,7 @@ public class TraderHelper(
/// <param name="traderID">trader id to reset</param> /// <param name="traderID">trader id to reset</param>
public void ResetTrader(string sessionID, string traderID) public void ResetTrader(string sessionID, string traderID)
{ {
var profiles = _databaseService.GetProfiles(); var profiles = _databaseService.GetProfileTemplates();
var trader = _databaseService.GetTrader(traderID); var trader = _databaseService.GetTrader(traderID);
var fullProfile = _profileHelper.GetFullProfile(sessionID); 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)); 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 pmcData = fullProfile.CharacterData.PmcData;
var rawProfileTemplate = profiles.GetByJsonProp<ProfileSides>(fullProfile.ProfileInfo.Edition) var matchingSide = _profileHelper.GetProfileTemplateForSide(fullProfile.ProfileInfo.Edition, pmcData.Info.Side);
.GetByJsonProp<TemplateSide>(pmcData.Info.Side.ToLower())
.Trader; // Profiles trader settings
var profileTemplateTraderData = matchingSide.Trader;
var newTraderData = new TraderInfo var newTraderData = new TraderInfo
{ {
Disabled = false, Disabled = false,
LoyaltyLevel = rawProfileTemplate.InitialLoyaltyLevel.GetValueOrDefault(traderID, 1), LoyaltyLevel = profileTemplateTraderData.InitialLoyaltyLevel.GetValueOrDefault(traderID, 1),
SalesSum = rawProfileTemplate.InitialSalesSum, SalesSum = profileTemplateTraderData.InitialSalesSum,
Standing = GetStartingStanding(traderID, rawProfileTemplate), Standing = GetStartingStanding(traderID, profileTemplateTraderData),
NextResupply = trader.Base.NextResupply, NextResupply = trader.Base.NextResupply,
Unlocked = trader.Base.UnlockedByDefault Unlocked = trader.Base.UnlockedByDefault
}; };
if (!pmcData.TradersInfo.TryAdd(traderID, newTraderData)) // Add trader to profile if it doesn't already
{ pmcData.TradersInfo.TryAdd(traderID, newTraderData);
pmcData.TradersInfo[traderID] = newTraderData;
}
// Check if trader should be locked by default // 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; pmcData.TradersInfo[traderID].Unlocked = true;
} }
if (rawProfileTemplate.PurchaseAllClothingByDefaultForTrader?.Contains(traderID) ?? false) if (profileTemplateTraderData.PurchaseAllClothingByDefaultForTrader?.Contains(traderID) ?? false)
{ {
// Get traders clothing // Get traders clothing
var clothing = _databaseService.GetTrader(traderID).Suits; 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 newBanDateTime = _timeUtil.GetTimeStampFromNowDays(profileTemplateTraderData.FleaBlockedDays ?? 0);
var existingBan = pmcData.Info.Bans.FirstOrDefault(ban => ban.BanType == BanType.RagFair); var existingBan = pmcData.Info.Bans?.FirstOrDefault(ban => ban.BanType == BanType.RagFair);
if (existingBan is not null) if (existingBan is not null)
{ {
existingBan.DateTime = newBanDateTime; existingBan.DateTime = newBanDateTime;
} }
else else
{ {
pmcData.Info.Bans ??= [];
pmcData.Info.Bans.Add( pmcData.Info.Bans.Add(
new Ban new Ban
{ {
@@ -208,7 +210,7 @@ public class TraderHelper(
if (traderID == Traders.JAEGER) if (traderID == Traders.JAEGER)
{ {
pmcData.TradersInfo[traderID].Unlocked = rawProfileTemplate.JaegerUnlocked; pmcData.TradersInfo[traderID].Unlocked = profileTemplateTraderData.JaegerUnlocked;
} }
} }
@@ -3,75 +3,6 @@ using SPTarkov.Server.Core.Models.Eft.Profile;
namespace SPTarkov.Server.Core.Models.Eft.Common.Tables; namespace SPTarkov.Server.Core.Models.Eft.Common.Tables;
public record ProfileTemplates
{
[JsonExtensionData]
public Dictionary<string, object> 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 public record ProfileSides
{ {
[JsonExtensionData] [JsonExtensionData]
@@ -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) /// The profile templates listed in the launcher on profile creation, split by account type (e.g. Standard) then side (e.g. bear/usec)
/// </summary> /// </summary>
[JsonPropertyName("profiles")] [JsonPropertyName("profiles")]
public ProfileTemplates? Profiles public Dictionary<string, ProfileSides>? Profiles
{ {
get; get;
set; set;
@@ -43,9 +43,8 @@ public class CreateProfileService(
public string CreateProfile(string sessionId, ProfileCreateRequestData request) public string CreateProfile(string sessionId, ProfileCreateRequestData request)
{ {
var account = _cloner.Clone(_saveServer.GetProfile(sessionId)); var account = _cloner.Clone(_saveServer.GetProfile(sessionId));
var profileTemplateClone = _cloner.Clone( var profileTemplateClone = _cloner.Clone(_profileHelper.GetProfileTemplateForSide(account.ProfileInfo.Edition, request.Side));
_databaseService.GetProfiles()?.GetByJsonProp<ProfileSides>(account.ProfileInfo.Edition)?.GetByJsonProp<TemplateSide>(request.Side.ToLower())
);
var pmcData = profileTemplateClone.Character; var pmcData = profileTemplateClone.Character;
// Delete existing profile // Delete existing profile
@@ -257,7 +257,7 @@ public class DatabaseService(
} }
/// <returns> assets/database/templates/profiles.json </returns> /// <returns> assets/database/templates/profiles.json </returns>
public ProfileTemplates GetProfiles() public Dictionary<string, ProfileSides> GetProfileTemplates()
{ {
if (_databaseServer.GetTables().Templates?.Profiles == null) if (_databaseServer.GetTables().Templates?.Profiles == null)
{ {