From 529fe61f23426eca23dceac4c732fde6c304ca6e Mon Sep 17 00:00:00 2001
From: Cj <161484149+CJ-SPT@users.noreply.github.com>
Date: Tue, 5 Aug 2025 11:24:59 -0400
Subject: [PATCH] Controller house keeping (#532)
* Cleanup BotController.cs
* More controller cleanup
* More dialogue changes
---
.../SPT_Data/database/locales/server/en.json | 1 +
.../Callbacks/CustomizationCallbacks.cs | 2 +-
.../Callbacks/DialogueCallbacks.cs | 32 ++++-
.../Controllers/BotController.cs | 129 +++++++++---------
.../Controllers/CustomizationController.cs | 48 +++----
.../Controllers/DialogueController.cs | 91 +++++++-----
.../Helpers/DialogueHelper.cs | 8 +-
.../Eft/Common/Tables/ProfileTemplate.cs | 2 +-
.../Eft/Dialog/ClearMailMessageRequest.cs | 3 +-
.../Dialog/GetMailDialogInfoRequestData.cs | 3 +-
.../Models/Eft/Dialog/PinDialogRequestData.cs | 3 +-
.../Eft/Dialog/RemoveDialogRequestData.cs | 3 +-
.../Eft/Dialog/SetDialogReadRequestData.cs | 3 +-
.../Models/Eft/Profile/SptProfile.cs | 4 +-
.../Models/Spt/Config/CoreConfig.cs | 3 +-
15 files changed, 189 insertions(+), 146 deletions(-)
diff --git a/Libraries/SPTarkov.Server.Assets/SPT_Data/database/locales/server/en.json b/Libraries/SPTarkov.Server.Assets/SPT_Data/database/locales/server/en.json
index 7e29d799..4b48f202 100644
--- a/Libraries/SPTarkov.Server.Assets/SPT_Data/database/locales/server/en.json
+++ b/Libraries/SPTarkov.Server.Assets/SPT_Data/database/locales/server/en.json
@@ -75,6 +75,7 @@
"dialog-chatbot_id_already_exists": "Chat bot: %s being registered already exists, unable to register bot",
"dialog-missing_item_template": "Unable to find item tpl {{tpl}} in db, cannot send message of type {{type}}, skipping",
"dialogue-unable_to_find_dialogs_in_profile": "No dialog object in profile: {{sessionId}}",
+ "dialogue-list_from_client_empty": "No dialog object sent from client: {{sessionId}}",
"dialogue-unable_to_find_in_profile": "No dialog in profile: {{sessionId}} found with id: {{dialogueId}}",
"event-unhandled_event": "[UNHANDLED EVENT] %s",
"executing_startup_callbacks": "Server: executing startup callbacks...",
diff --git a/Libraries/SPTarkov.Server.Core/Callbacks/CustomizationCallbacks.cs b/Libraries/SPTarkov.Server.Core/Callbacks/CustomizationCallbacks.cs
index 1e62d0bb..a9cd64d6 100644
--- a/Libraries/SPTarkov.Server.Core/Callbacks/CustomizationCallbacks.cs
+++ b/Libraries/SPTarkov.Server.Core/Callbacks/CustomizationCallbacks.cs
@@ -52,7 +52,7 @@ public class CustomizationCallbacks(
///
public ValueTask GetHideoutCustomisation(string url, EmptyRequestData _, MongoId sessionID)
{
- return new ValueTask(httpResponseUtil.GetBody(customizationController.GetHideoutCustomisation(sessionID)));
+ return new ValueTask(httpResponseUtil.GetBody(customizationController.GetHideoutCustomisation()));
}
///
diff --git a/Libraries/SPTarkov.Server.Core/Callbacks/DialogueCallbacks.cs b/Libraries/SPTarkov.Server.Core/Callbacks/DialogueCallbacks.cs
index 0ed78a25..14ad5416 100644
--- a/Libraries/SPTarkov.Server.Core/Callbacks/DialogueCallbacks.cs
+++ b/Libraries/SPTarkov.Server.Core/Callbacks/DialogueCallbacks.cs
@@ -37,7 +37,7 @@ public class DialogueCallbacks(TimeUtil timeUtil, HttpResponseUtil httpResponseU
{
new()
{
- Id = new Models.Common.MongoId(),
+ Id = new MongoId(),
RegistrationId = 20,
DateTime = timeUtil.GetTimeStamp(),
IsDeveloper = true,
@@ -80,7 +80,9 @@ public class DialogueCallbacks(TimeUtil timeUtil, HttpResponseUtil httpResponseU
///
public virtual ValueTask GetMailDialogInfo(string url, GetMailDialogInfoRequestData request, MongoId sessionID)
{
- return new ValueTask(httpResponseUtil.GetBody(dialogueController.GetDialogueInfo(request.DialogId, sessionID)));
+ return new ValueTask(
+ httpResponseUtil.GetBody(dialogueController.GetDialogueInfo(request.DialogId ?? MongoId.Empty(), sessionID))
+ );
}
///
@@ -89,7 +91,7 @@ public class DialogueCallbacks(TimeUtil timeUtil, HttpResponseUtil httpResponseU
///
public virtual ValueTask RemoveDialog(string url, RemoveDialogRequestData request, MongoId sessionID)
{
- dialogueController.RemoveDialogue(request.DialogId, sessionID);
+ dialogueController.RemoveDialogue(request.DialogId ?? MongoId.Empty(), sessionID);
return new ValueTask(httpResponseUtil.EmptyArrayResponse());
}
@@ -99,7 +101,7 @@ public class DialogueCallbacks(TimeUtil timeUtil, HttpResponseUtil httpResponseU
///
public virtual ValueTask PinDialog(string url, PinDialogRequestData request, MongoId sessionID)
{
- dialogueController.SetDialoguePin(request.DialogId, true, sessionID);
+ dialogueController.SetDialoguePin(request.DialogId ?? MongoId.Empty(), true, sessionID);
return new ValueTask(httpResponseUtil.EmptyArrayResponse());
}
@@ -109,7 +111,7 @@ public class DialogueCallbacks(TimeUtil timeUtil, HttpResponseUtil httpResponseU
///
public virtual ValueTask UnpinDialog(string url, PinDialogRequestData request, MongoId sessionID)
{
- dialogueController.SetDialoguePin(request.DialogId, false, sessionID);
+ dialogueController.SetDialoguePin(request.DialogId ?? MongoId.Empty(), false, sessionID);
return new ValueTask(httpResponseUtil.EmptyArrayResponse());
}
@@ -232,6 +234,10 @@ public class DialogueCallbacks(TimeUtil timeUtil, HttpResponseUtil httpResponseU
return new ValueTask(httpResponseUtil.NullResponse());
}
+ ///
+ /// Handle /client/mail/dialog/clear
+ ///
+ ///
public virtual ValueTask ClearMail(string url, ClearMailMessageRequest request, MongoId sessionID)
{
dialogueController.ClearMessages(sessionID, request);
@@ -239,21 +245,37 @@ public class DialogueCallbacks(TimeUtil timeUtil, HttpResponseUtil httpResponseU
return new ValueTask(httpResponseUtil.EmptyArrayResponse());
}
+ ///
+ /// Handle /client/mail/dialog/group/create
+ ///
+ ///
public virtual ValueTask CreateGroupMail(string url, CreateGroupMailRequest request, MongoId sessionID)
{
return new ValueTask(httpResponseUtil.EmptyArrayResponse());
}
+ ///
+ /// Handle /client/mail/dialog/group/owner/change
+ ///
+ ///
public virtual ValueTask ChangeMailGroupOwner(string url, ChangeGroupMailOwnerRequest request, MongoId sessionID)
{
return new ValueTask("Not Implemented!"); // Not implemented in Node
}
+ ///
+ /// Handle /client/mail/dialog/group/users/add
+ ///
+ ///
public virtual ValueTask AddUserToMail(string url, AddUserGroupMailRequest request, MongoId sessionID)
{
return new ValueTask("Not Implemented!"); // Not implemented in Node
}
+ ///
+ /// Handle /client/mail/dialog/group/users/remove
+ ///
+ ///
public virtual ValueTask RemoveUserFromMail(string url, RemoveUserGroupMailRequest request, MongoId sessionID)
{
return new ValueTask("Not Implemented!"); // Not implemented in Node
diff --git a/Libraries/SPTarkov.Server.Core/Controllers/BotController.cs b/Libraries/SPTarkov.Server.Core/Controllers/BotController.cs
index 4885d2f0..bee0bdba 100644
--- a/Libraries/SPTarkov.Server.Core/Controllers/BotController.cs
+++ b/Libraries/SPTarkov.Server.Core/Controllers/BotController.cs
@@ -23,24 +23,23 @@ namespace SPTarkov.Server.Core.Controllers;
[Injectable]
public class BotController(
- ISptLogger _logger,
- DatabaseService _databaseService,
- BotGenerator _botGenerator,
- BotHelper _botHelper,
- BotDifficultyHelper _botDifficultyHelper,
- ServerLocalisationService _serverLocalisationService,
- SeasonalEventService _seasonalEventService,
- MatchBotDetailsCacheService _matchBotDetailsCacheService,
- ProfileHelper _profileHelper,
- ConfigServer _configServer,
- ProfileActivityService _profileActivityService,
- RandomUtil _randomUtil,
- ICloner _cloner
+ ISptLogger logger,
+ DatabaseService databaseService,
+ BotGenerator botGenerator,
+ BotHelper botHelper,
+ BotDifficultyHelper botDifficultyHelper,
+ ServerLocalisationService serverLocalisationService,
+ SeasonalEventService seasonalEventService,
+ MatchBotDetailsCacheService matchBotDetailsCacheService,
+ ProfileHelper profileHelper,
+ ConfigServer configServer,
+ ProfileActivityService profileActivityService,
+ RandomUtil randomUtil,
+ ICloner cloner
)
{
- private readonly BotConfig _botConfig = _configServer.GetConfig();
- private readonly PmcConfig _pmcConfig = _configServer.GetConfig();
- private static readonly Lock _botListLock = new();
+ protected readonly BotConfig botConfig = configServer.GetConfig();
+ protected readonly PmcConfig pmcConfig = configServer.GetConfig();
///
/// Return the number of bot load-out varieties to be generated
@@ -49,9 +48,9 @@ public class BotController(
/// number of bots to generate
public int GetBotPresetGenerationLimit(string type)
{
- if (!_botConfig.PresetBatch.TryGetValue(type, out var limit))
+ if (!botConfig.PresetBatch.TryGetValue(type, out var limit))
{
- _logger.Warning(_serverLocalisationService.GetText("bot-bot_preset_count_value_missing", type));
+ logger.Warning(serverLocalisationService.GetText("bot-bot_preset_count_value_missing", type));
return 10;
}
@@ -66,7 +65,7 @@ public class BotController(
///
public Dictionary GetBotCoreDifficulty()
{
- return _databaseService.GetBots().Core!;
+ return databaseService.GetBots().Core;
}
///
@@ -82,11 +81,11 @@ public class BotController(
{
var difficulty = diffLevel.ToLowerInvariant();
- var raidConfig = _profileActivityService.GetProfileActivityRaidData(sessionId).RaidConfiguration;
+ var raidConfig = profileActivityService.GetProfileActivityRaidData(sessionId).RaidConfiguration;
if (!(raidConfig != null || ignoreRaidSettings))
{
- _logger.Error(_serverLocalisationService.GetText("bot-missing_application_context", "RAID_CONFIGURATION"));
+ logger.Error(serverLocalisationService.GetText("bot-missing_application_context", "RAID_CONFIGURATION"));
}
// Check value chosen in pre-raid difficulty dropdown
@@ -94,11 +93,11 @@ public class BotController(
var botDifficultyDropDownValue = raidConfig?.WavesSettings?.BotDifficulty?.ToString().ToLowerInvariant() ?? "asonline";
if (botDifficultyDropDownValue != "asonline")
{
- difficulty = _botDifficultyHelper.ConvertBotDifficultyDropdownToBotDifficulty(botDifficultyDropDownValue);
+ difficulty = botDifficultyHelper.ConvertBotDifficultyDropdownToBotDifficulty(botDifficultyDropDownValue);
}
- var botDb = _databaseService.GetBots();
- return _botDifficultyHelper.GetBotDifficultySettings(type, difficulty, botDb);
+ var botDb = databaseService.GetBots();
+ return botDifficultyHelper.GetBotDifficultySettings(type, difficulty, botDb);
}
///
@@ -109,7 +108,7 @@ public class BotController(
{
var result = new Dictionary>();
- var botTypesDb = _databaseService.GetBots().Types;
+ var botTypesDb = databaseService.GetBots().Types;
if (botTypesDb is null)
{
return result;
@@ -128,9 +127,9 @@ public class BotController(
{
// No bot of this type found, copy details from assault
result[botTypeLower] = result[Roles.Assault];
- if (_logger.IsLogEnabled(LogLevel.Debug))
+ if (logger.IsLogEnabled(LogLevel.Debug))
{
- _logger.Debug($"Unable to find bot: {botTypeLower} in db, copying: '{Roles.Assault}'");
+ logger.Debug($"Unable to find bot: {botTypeLower} in db, copying: '{Roles.Assault}'");
}
continue;
@@ -139,7 +138,7 @@ public class BotController(
if (botDetails?.BotDifficulty is null)
{
// Bot has no difficulty values, skip
- _logger.Warning($"Unable to find bot: {botTypeLower} difficulty values in db, skipping");
+ logger.Warning($"Unable to find bot: {botTypeLower} difficulty values in db, skipping");
continue;
}
@@ -166,9 +165,9 @@ public class BotController(
/// Session/Player id
///
/// List of bots
- public async Task> Generate(MongoId sessionId, GenerateBotsRequestData request)
+ public async Task> Generate(MongoId sessionId, GenerateBotsRequestData request)
{
- var pmcProfile = _profileHelper.GetPmcProfile(sessionId);
+ var pmcProfile = profileHelper.GetPmcProfile(sessionId);
return await GenerateBotWaves(sessionId, request, pmcProfile);
}
@@ -180,7 +179,7 @@ public class BotController(
/// Client bot generation request
/// Player profile generating bots
/// List of generated bots
- protected async Task> GenerateBotWaves(MongoId sessionId, GenerateBotsRequestData request, PmcData? pmcProfile)
+ protected async Task> GenerateBotWaves(MongoId sessionId, GenerateBotsRequestData request, PmcData? pmcProfile)
{
if (request.Conditions is null || !request.Conditions.Any())
{
@@ -191,7 +190,7 @@ public class BotController(
// Get chosen raid settings from app context
var raidSettings = GetMostRecentRaidSettings(sessionId);
- var allPmcsHaveSameNameAsPlayer = _randomUtil.GetChance100(_pmcConfig.AllPMCsHavePlayerNameWithRandomPrefixChance);
+ var allPmcsHaveSameNameAsPlayer = randomUtil.GetChance100(pmcConfig.AllPMCsHavePlayerNameWithRandomPrefixChance);
// Split each bot wave into its own task
var waveGenerationTasks = request.Conditions.Select(condition =>
@@ -213,9 +212,9 @@ public class BotController(
var results = await Task.WhenAll(waveGenerationTasks);
stopwatch.Stop();
- if (_logger.IsLogEnabled(LogLevel.Debug))
+ if (logger.IsLogEnabled(LogLevel.Debug))
{
- _logger.Debug($"Took {stopwatch.ElapsedMilliseconds}ms to GenerateMultipleBotsAndCache()");
+ logger.Debug($"Took {stopwatch.ElapsedMilliseconds}ms to GenerateMultipleBotsAndCache()");
}
// Merge + flatten results of all wave generations
@@ -229,7 +228,7 @@ public class BotController(
///
///
/// Result of generating bot wave
- protected IEnumerable GenerateBotWave(
+ protected IEnumerable GenerateBotWave(
MongoId sessionId,
GenerateCondition generateRequest,
BotGenerationDetails botGenerationDetails
@@ -240,33 +239,33 @@ public class BotController(
{
// Add eventRole data + reassign role property to be base type
botGenerationDetails.EventRole = generateRequest.Role;
- botGenerationDetails.Role = _seasonalEventService.GetBaseRoleForEventBot(botGenerationDetails.EventRole);
+ botGenerationDetails.Role = seasonalEventService.GetBaseRoleForEventBot(botGenerationDetails.EventRole);
}
// Event role must take priority to generate correctly
var role = botGenerationDetails.EventRole ?? botGenerationDetails.Role;
- if (_logger.IsLogEnabled(LogLevel.Debug))
+ if (logger.IsLogEnabled(LogLevel.Debug))
{
- _logger.Debug(
+ logger.Debug(
$"Generating wave of: {botGenerationDetails.BotCountToGenerate} bots of type: {role} {botGenerationDetails.BotDifficulty}"
);
}
var generatedBots = Enumerable
.Range(0, botGenerationDetails.BotCountToGenerate)
- .AsParallel() // Parallelise above range of values so they can each generate a bot
+ .AsParallel() // Parallelize above range of values so they can each generate a bot
.Select(i => TryGenerateSingleBot(sessionId, botGenerationDetails, i))
.Where(bot =>
bot is not null
) // Skip failed bots
; // Materialise parallel query into data
- if (_logger.IsLogEnabled(LogLevel.Debug))
+ if (logger.IsLogEnabled(LogLevel.Debug))
{
- _logger.Debug(
+ logger.Debug(
$"Generated: {botGenerationDetails.BotCountToGenerate} {botGenerationDetails.Role}"
- + $"({botGenerationDetails.EventRole ?? botGenerationDetails.Role ?? ""}) {botGenerationDetails.BotDifficulty} bots"
+ + $"({botGenerationDetails.EventRole ?? botGenerationDetails.Role}) {botGenerationDetails.BotDifficulty} bots"
);
}
@@ -282,22 +281,22 @@ public class BotController(
try
{
// Clone for thread safety TODO: confirm if clone is necessary (likely not)
- var bot = _botGenerator.PrepareAndGenerateBot(sessionId, _cloner.Clone(generationDetails));
+ var bot = botGenerator.PrepareAndGenerateBot(sessionId, cloner.Clone(generationDetails)!);
// Client expects Side for PMCs to be `Savage`, must be altered here before it's cached
- if (bot.Info.Side is Sides.Bear or Sides.Usec)
+ if (bot.Info?.Side is Sides.Bear or Sides.Usec)
{
bot.Info.Side = Sides.Savage;
}
// Store bot details in cache before returning.
- _matchBotDetailsCacheService.CacheBot(bot);
+ matchBotDetailsCacheService.CacheBot(bot);
return bot;
}
catch (Exception e)
{
- _logger.Error($"Failed to generate bot #{botIndex + 1} ({generationDetails.Role}): {e.Message}");
+ logger.Error($"Failed to generate bot #{botIndex + 1} ({generationDetails.Role}): {e.Message}");
return null;
}
}
@@ -308,11 +307,11 @@ public class BotController(
/// GetRaidConfigurationRequestData if it exists
protected GetRaidConfigurationRequestData? GetMostRecentRaidSettings(MongoId sessionId)
{
- var raidConfiguration = _profileActivityService.GetProfileActivityRaidData(sessionId)?.RaidConfiguration;
+ var raidConfiguration = profileActivityService.GetProfileActivityRaidData(sessionId).RaidConfiguration;
if (raidConfiguration is null)
{
- _logger.Warning(_serverLocalisationService.GetText("bot-unable_to_load_raid_settings_from_appcontext"));
+ logger.Warning(serverLocalisationService.GetText("bot-unable_to_load_raid_settings_from_appcontext"));
}
return raidConfiguration;
@@ -323,9 +322,9 @@ public class BotController(
///
/// Map name e.g. factory4_day
/// MinMax values
- protected MinMax GetPmcLevelRangeForMap(string? location)
+ protected MinMax? GetPmcLevelRangeForMap(string? location)
{
- return _pmcConfig.LocationSpecificPmcLevelOverride!.GetValueOrDefault(location?.ToLowerInvariant() ?? "", null);
+ return pmcConfig.LocationSpecificPmcLevelOverride!.GetValueOrDefault(location?.ToLowerInvariant() ?? "", null);
}
///
@@ -343,18 +342,18 @@ public class BotController(
GetRaidConfigurationRequestData? raidSettings
)
{
- var generateAsPmc = _botHelper.IsBotPmc(condition.Role);
+ var generateAsPmc = botHelper.IsBotPmc(condition.Role);
return new BotGenerationDetails
{
IsPmc = generateAsPmc,
- Side = generateAsPmc ? _botHelper.GetPmcSideByRole(condition.Role ?? string.Empty) : "Savage",
- Role = condition.Role,
+ Side = generateAsPmc ? botHelper.GetPmcSideByRole(condition.Role ?? string.Empty) : "Savage",
+ Role = condition.Role!,
PlayerLevel = pmcProfile?.Info?.Level ?? 1,
PlayerName = pmcProfile?.Info?.Nickname,
- BotRelativeLevelDeltaMax = _pmcConfig.BotRelativeLevelDelta.Max,
- BotRelativeLevelDeltaMin = _pmcConfig.BotRelativeLevelDelta.Min,
- BotCountToGenerate = Math.Max(GetBotPresetGenerationLimit(condition.Role), condition.Limit), // Choose largest between value passed in from request vs what's in bot.config
+ BotRelativeLevelDeltaMax = pmcConfig.BotRelativeLevelDelta.Max,
+ BotRelativeLevelDeltaMin = pmcConfig.BotRelativeLevelDelta.Min,
+ BotCountToGenerate = Math.Max(GetBotPresetGenerationLimit(condition.Role!), condition.Limit), // Choose largest between value passed in from request vs what's in bot.config
BotDifficulty = condition.Difficulty,
LocationSpecificPmcLevelOverride = GetPmcLevelRangeForMap(raidSettings?.Location), // Min/max levels for PMCs to generate within
IsPlayerScav = false,
@@ -371,14 +370,14 @@ public class BotController(
/// bot cap for map
public int GetBotCap(string location)
{
- if (!_botConfig.MaxBotCap.TryGetValue(location.ToLowerInvariant(), out var maxCap))
+ if (!botConfig.MaxBotCap.TryGetValue(location.ToLowerInvariant(), out var maxCap))
{
- return _botConfig.MaxBotCap["default"];
+ return botConfig.MaxBotCap["default"];
}
if (location == "default")
{
- _logger.Warning(_serverLocalisationService.GetText("bot-no_bot_cap_found_for_location", location.ToLowerInvariant()));
+ logger.Warning(serverLocalisationService.GetText("bot-no_bot_cap_found_for_location", location.ToLowerInvariant()));
}
return maxCap;
@@ -392,9 +391,9 @@ public class BotController(
{
return new AiBotBrainTypes
{
- PmcType = _pmcConfig.PmcType,
- Assault = _botConfig.AssaultBrainType,
- PlayerScav = _botConfig.PlayerScavBrainType,
+ PmcType = pmcConfig.PmcType,
+ Assault = botConfig.AssaultBrainType,
+ PlayerScav = botConfig.PlayerScavBrainType,
};
}
}
@@ -402,11 +401,11 @@ public class BotController(
public record AiBotBrainTypes
{
[JsonPropertyName("pmc")]
- public Dictionary>> PmcType { get; set; }
+ public required Dictionary>> PmcType { get; set; }
[JsonPropertyName("assault")]
- public Dictionary> Assault { get; set; }
+ public required Dictionary> Assault { get; set; }
[JsonPropertyName("playerScav")]
- public Dictionary> PlayerScav { get; set; }
+ public required Dictionary> PlayerScav { get; set; }
}
diff --git a/Libraries/SPTarkov.Server.Core/Controllers/CustomizationController.cs b/Libraries/SPTarkov.Server.Core/Controllers/CustomizationController.cs
index b1d30ec3..b993ae2a 100644
--- a/Libraries/SPTarkov.Server.Core/Controllers/CustomizationController.cs
+++ b/Libraries/SPTarkov.Server.Core/Controllers/CustomizationController.cs
@@ -13,6 +13,7 @@ using SPTarkov.Server.Core.Routers;
using SPTarkov.Server.Core.Servers;
using SPTarkov.Server.Core.Services;
using SPTarkov.Server.Core.Utils.Cloners;
+using Customization = SPTarkov.Server.Core.Models.Eft.Common.Tables.Customization;
namespace SPTarkov.Server.Core.Controllers;
@@ -38,7 +39,7 @@ public class CustomizationController(
{
var pmcData = profileHelper.GetPmcProfile(sessionId);
var clothing = databaseService.GetCustomization();
- var suits = databaseService.GetTrader(traderId).Suits;
+ var suits = databaseService.GetTrader(traderId)?.Suits;
var matchingSuits = suits?.Where(s => clothing.ContainsKey(s.SuiteId));
matchingSuits = matchingSuits?.Where(s =>
@@ -99,7 +100,7 @@ public class CustomizationController(
Type = CustomisationType.SUITE,
};
- profile.CustomisationUnlocks.Add(rewardToStore);
+ profile.CustomisationUnlocks?.Add(rewardToStore);
return output;
}
@@ -115,7 +116,7 @@ public class CustomizationController(
var fullProfile = profileHelper.GetFullProfile(sessionId);
// Check if clothing can be found by id
- return fullProfile.CustomisationUnlocks.Exists(customisation => Equals(customisation.Id, suitId));
+ return fullProfile.CustomisationUnlocks?.Exists(customisation => Equals(customisation.Id, suitId)) ?? false;
}
///
@@ -158,11 +159,11 @@ public class CustomizationController(
{
var options = new ProcessBuyTradeRequestData
{
- SchemeItems = [new IdWithCount { Count = inventoryItemToProcess.Count.Value, Id = inventoryItemToProcess.Id }],
+ SchemeItems = [new IdWithCount { Count = inventoryItemToProcess.Count!.Value, Id = inventoryItemToProcess.Id }],
TransactionId = Traders.RAGMAN,
Action = "BuyCustomization",
Type = "",
- ItemId = "",
+ ItemId = MongoId.Empty(),
Count = 0,
SchemeId = 0,
};
@@ -183,7 +184,7 @@ public class CustomizationController(
foreach (var (traderId, trader) in traders)
{
- if (trader.Base?.CustomizationSeller is not null && trader.Base.CustomizationSeller.Value)
+ if (trader.Base.CustomizationSeller is not null && trader.Base.CustomizationSeller.Value)
{
result.AddRange(GetTraderSuits(traderId, sessionId));
}
@@ -195,11 +196,10 @@ public class CustomizationController(
///
/// Handle client/hideout/customization/offer/list
///
- /// Session/Player id
- ///
- public HideoutCustomisation GetHideoutCustomisation(MongoId sessionId)
+ /// Hideout customizations
+ public HideoutCustomisation GetHideoutCustomisation()
{
- return databaseService.GetHideout().Customisation!;
+ return databaseService.GetHideout().Customisation;
}
///
@@ -212,10 +212,6 @@ public class CustomizationController(
var customisationResultsClone = cloner.Clone(databaseService.GetTemplates().CustomisationStorage);
var profile = profileHelper.GetFullProfile(sessionId);
- if (profile is null)
- {
- return customisationResultsClone!;
- }
customisationResultsClone!.AddRange(profile.CustomisationUnlocks ?? []);
@@ -231,7 +227,7 @@ public class CustomizationController(
/// ItemEventRouterResponse
public ItemEventRouterResponse SetCustomisation(MongoId sessionId, CustomizationSetRequest request, PmcData pmcData)
{
- foreach (var customisation in request.Customizations)
+ foreach (var customisation in request.Customizations!)
{
switch (customisation.Type)
{
@@ -268,19 +264,19 @@ public class CustomizationController(
return;
}
- // Body
- if (dbSuit.Parent == CustomisationTypeId.UPPER)
- {
- pmcData.Customization.Body = dbSuit.Properties.Body;
- pmcData.Customization.Hands = dbSuit.Properties.Hands;
+ pmcData.Customization ??= new Customization();
- return;
- }
-
- // Feet
- if (dbSuit.Parent == CustomisationTypeId.LOWER)
+ switch (dbSuit?.Parent)
{
- pmcData.Customization.Feet = dbSuit.Properties.Feet;
+ // Body
+ case CustomisationTypeId.UPPER:
+ pmcData.Customization.Body = dbSuit.Properties.Body;
+ pmcData.Customization.Hands = dbSuit.Properties.Hands;
+ return;
+ // Feet
+ case CustomisationTypeId.LOWER:
+ pmcData.Customization.Feet = dbSuit.Properties.Feet;
+ break;
}
}
}
diff --git a/Libraries/SPTarkov.Server.Core/Controllers/DialogueController.cs b/Libraries/SPTarkov.Server.Core/Controllers/DialogueController.cs
index bd573baa..46d6f79f 100644
--- a/Libraries/SPTarkov.Server.Core/Controllers/DialogueController.cs
+++ b/Libraries/SPTarkov.Server.Core/Controllers/DialogueController.cs
@@ -73,22 +73,30 @@ public class DialogueController(
// Add any friends the user has after the chatbots
var profile = profileHelper.GetFullProfile(sessionId);
- if (profile?.FriendProfileIds is not null)
+
+ if (profile.FriendProfileIds is null)
{
- foreach (var friendId in profile.FriendProfileIds)
+ return new GetFriendListDataResponse
{
- var friendProfile = profileHelper.GetChatRoomMemberFromSessionId(friendId);
- if (friendProfile is not null)
- {
- friends.Add(
- new UserDialogInfo
- {
- Id = friendProfile.Id,
- Aid = friendProfile.Aid,
- Info = friendProfile.Info,
- }
- );
- }
+ Friends = friends,
+ Ignore = [],
+ InIgnoreList = [],
+ };
+ }
+
+ foreach (var friendId in profile.FriendProfileIds)
+ {
+ var friendProfile = profileHelper.GetChatRoomMemberFromSessionId(friendId);
+ if (friendProfile is not null)
+ {
+ friends.Add(
+ new UserDialogInfo
+ {
+ Id = friendProfile.Id,
+ Aid = friendProfile.Aid,
+ Info = friendProfile.Info,
+ }
+ );
}
}
@@ -100,6 +108,10 @@ public class DialogueController(
};
}
+ ///
+ /// Get all active chatbots
+ ///
+ /// Active chatbots
public List GetActiveChatBots()
{
var activeBots = new List();
@@ -109,7 +121,7 @@ public class DialogueController(
foreach (var bot in _dialogueChatBots)
{
var botData = bot.GetChatBot();
- if (chatBotConfig.EnabledBots.ContainsKey(botData.Id!))
+ if (chatBotConfig.EnabledBots.ContainsKey(botData.Id))
{
activeBots.Add(botData);
}
@@ -148,10 +160,10 @@ public class DialogueController(
/// Dialog id
/// Session Id
/// DialogueInfo
- public virtual DialogueInfo? GetDialogueInfo(string? dialogueId, MongoId sessionId)
+ public virtual DialogueInfo? GetDialogueInfo(MongoId dialogueId, MongoId sessionId)
{
var dialogs = dialogueHelper.GetDialogsForProfile(sessionId);
- var dialogue = dialogs!.GetValueOrDefault(dialogueId);
+ var dialogue = dialogs.GetValueOrDefault(dialogueId);
return GetDialogueInfo(dialogue, sessionId);
}
@@ -162,9 +174,9 @@ public class DialogueController(
/// Dialog
/// Session Id
/// DialogueInfo
- public virtual DialogueInfo? GetDialogueInfo(Dialogue dialogue, MongoId sessionId)
+ public virtual DialogueInfo? GetDialogueInfo(Dialogue? dialogue, MongoId sessionId)
{
- if (!dialogue.Messages.Any())
+ if (dialogue is null || dialogue.Messages?.Count == 0)
{
return null;
}
@@ -236,7 +248,7 @@ public class DialogueController(
var fullProfile = saveServer.GetProfile(sessionId);
var dialogue = GetDialogByIdFromProfile(fullProfile, request);
- if (!dialogue.Messages.Any())
+ if (dialogue.Messages?.Count == 0)
{
return new GetMailDialogViewResponseData
{
@@ -250,7 +262,7 @@ public class DialogueController(
dialogue.New = 0;
// Set number of new attachments, but ignore those that have expired.
- dialogue.AttachmentsNew = GetUnreadMessagesWithAttachmentsCount(sessionId, dialogueId!);
+ dialogue.AttachmentsNew = GetUnreadMessagesWithAttachmentsCount(sessionId, dialogueId);
return new GetMailDialogViewResponseData
{
@@ -268,12 +280,12 @@ public class DialogueController(
/// Dialogue
protected Dialogue GetDialogByIdFromProfile(SptProfile profile, GetMailDialogViewRequestData request)
{
- if (profile.DialogueRecords is null || profile.DialogueRecords.ContainsKey(request.DialogId!))
+ if (profile.DialogueRecords is null || profile.DialogueRecords.ContainsKey(request.DialogId))
{
- return profile.DialogueRecords?[request.DialogId!] ?? throw new NullReferenceException();
+ return profile.DialogueRecords?[request.DialogId] ?? throw new NullReferenceException();
}
- profile.DialogueRecords[request.DialogId!] = new Dialogue
+ profile.DialogueRecords[request.DialogId] = new Dialogue
{
Id = request.DialogId,
AttachmentsNew = 0,
@@ -285,22 +297,22 @@ public class DialogueController(
if (request.Type != MessageType.UserMessage)
{
- return profile.DialogueRecords[request.DialogId!];
+ return profile.DialogueRecords[request.DialogId];
}
- var dialogue = profile.DialogueRecords[request.DialogId!];
+ var dialogue = profile.DialogueRecords[request.DialogId];
dialogue.Users = [];
var chatBot = _dialogueChatBots.FirstOrDefault(cb => cb.GetChatBot().Id == request.DialogId);
if (chatBot is null)
{
- return profile.DialogueRecords[request.DialogId!];
+ return profile.DialogueRecords[request.DialogId];
}
dialogue.Users ??= [];
dialogue.Users.Add(chatBot.GetChatBot());
- return profile.DialogueRecords[request.DialogId!];
+ return profile.DialogueRecords[request.DialogId];
}
///
@@ -352,7 +364,7 @@ public class DialogueController(
/// Session id
/// Dialog id
/// Count of messages with attachments
- protected int GetUnreadMessagesWithAttachmentsCount(MongoId sessionId, string dialogueId)
+ protected int GetUnreadMessagesWithAttachmentsCount(MongoId sessionId, MongoId dialogueId)
{
var newAttachmentCount = 0;
var activeMessages = GetActiveMessagesFromDialog(sessionId, dialogueId);
@@ -373,7 +385,7 @@ public class DialogueController(
/// Session/Player id
/// Dialog to get mail attachments from
/// Message array
- protected List GetActiveMessagesFromDialog(MongoId sessionId, string dialogueId)
+ protected List GetActiveMessagesFromDialog(MongoId sessionId, MongoId dialogueId)
{
var timeNow = timeUtil.GetTimeStamp();
var dialogs = dialogueHelper.GetDialogsForProfile(sessionId);
@@ -403,10 +415,10 @@ public class DialogueController(
///
/// id of the dialog to remove
/// Player id
- public virtual void RemoveDialogue(string? dialogueId, MongoId sessionId)
+ public virtual void RemoveDialogue(MongoId dialogueId, MongoId sessionId)
{
var profile = saveServer.GetProfile(sessionId);
- if (!profile.DialogueRecords.Remove(dialogueId))
+ if (!profile.DialogueRecords?.Remove(dialogueId) ?? false)
{
logger.Error(serverLocalisationService.GetText("dialogue-unable_to_find_in_profile", new { sessionId, dialogueId }));
}
@@ -418,7 +430,7 @@ public class DialogueController(
///
///
/// Session/Player id
- public virtual void SetDialoguePin(string? dialogueId, bool shouldPin, MongoId sessionId)
+ public virtual void SetDialoguePin(MongoId dialogueId, bool shouldPin, MongoId sessionId)
{
var dialog = dialogueHelper.GetDialogsForProfile(sessionId).GetValueOrDefault(dialogueId);
if (dialog is null)
@@ -437,10 +449,17 @@ public class DialogueController(
///
/// Dialog ids to set as read
/// Player profile id
- public virtual void SetRead(List? dialogueIds, MongoId sessionId)
+ public virtual void SetRead(List? dialogueIds, MongoId sessionId)
{
+ if (dialogueIds is null)
+ {
+ logger.Error(serverLocalisationService.GetText("dialogue-list_from_client_empty", new { sessionId }));
+
+ return;
+ }
+
var dialogs = dialogueHelper.GetDialogsForProfile(sessionId);
- if (dialogs.Any() != true)
+ if (dialogs.Count == 0)
{
logger.Error(serverLocalisationService.GetText("dialogue-unable_to_find_dialogs_in_profile", new { sessionId }));
@@ -629,7 +648,7 @@ public class DialogueController(
public void ClearMessages(MongoId sessionId, ClearMailMessageRequest request)
{
var profile = saveServer.GetProfile(sessionId);
- if (!profile.DialogueRecords.TryGetValue(request.DialogId, out var dialogToClear))
+ if (profile.DialogueRecords is null || !profile.DialogueRecords.TryGetValue(request.DialogId, out var dialogToClear))
{
logger.Warning($"unable to clear messages from dialog: {request.DialogId} as it cannot be found in profile: {sessionId}");
diff --git a/Libraries/SPTarkov.Server.Core/Helpers/DialogueHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/DialogueHelper.cs
index 1c888fd3..dddb30c7 100644
--- a/Libraries/SPTarkov.Server.Core/Helpers/DialogueHelper.cs
+++ b/Libraries/SPTarkov.Server.Core/Helpers/DialogueHelper.cs
@@ -17,7 +17,7 @@ public class DialogueHelper(ISptLogger logger, ProfileHelper pro
public MessagePreview GetMessagePreview(Models.Eft.Profile.Dialogue? dialogue)
{
// The last message of the dialogue should be shown on the preview.
- var message = dialogue.Messages.LastOrDefault();
+ var message = dialogue?.Messages?.LastOrDefault();
MessagePreview result = new()
{
@@ -92,10 +92,10 @@ public class DialogueHelper(ISptLogger logger, ProfileHelper pro
///
/// Session/player id
/// Dialog dictionary
- public Dictionary GetDialogsForProfile(MongoId sessionId)
+ public Dictionary GetDialogsForProfile(MongoId sessionId)
{
var profile = profileHelper.GetFullProfile(sessionId);
- return profile.DialogueRecords ?? (profile.DialogueRecords = new Dictionary());
+ return profile.DialogueRecords ?? (profile.DialogueRecords = new Dictionary());
}
///
@@ -104,7 +104,7 @@ public class DialogueHelper(ISptLogger logger, ProfileHelper pro
/// Profile to look in
/// Dialog to return
/// Dialogue
- public Models.Eft.Profile.Dialogue? GetDialogueFromProfile(MongoId profileId, string dialogueId)
+ public Models.Eft.Profile.Dialogue? GetDialogueFromProfile(MongoId profileId, MongoId dialogueId)
{
var dialogues = GetDialogsForProfile(profileId);
if (dialogues.TryGetValue(dialogueId, out var dialogue))
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 87f79f30..edae8d98 100644
--- a/Libraries/SPTarkov.Server.Core/Models/Eft/Common/Tables/ProfileTemplate.cs
+++ b/Libraries/SPTarkov.Server.Core/Models/Eft/Common/Tables/ProfileTemplate.cs
@@ -31,7 +31,7 @@ public record TemplateSide
public List? Suits { get; set; }
[JsonPropertyName("dialogues")]
- public Dictionary? Dialogues { get; set; }
+ public Dictionary? Dialogues { get; set; }
[JsonPropertyName("userbuilds")]
public UserBuilds? UserBuilds { get; set; }
diff --git a/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/ClearMailMessageRequest.cs b/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/ClearMailMessageRequest.cs
index 3c74c85e..2fb9f011 100644
--- a/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/ClearMailMessageRequest.cs
+++ b/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/ClearMailMessageRequest.cs
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
+using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Utils;
namespace SPTarkov.Server.Core.Models.Eft.Dialog;
@@ -9,5 +10,5 @@ public record ClearMailMessageRequest : IRequestData
public Dictionary? ExtensionData { get; set; }
[JsonPropertyName("dialogId")]
- public string? DialogId { get; set; }
+ public required MongoId DialogId { get; set; }
}
diff --git a/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/GetMailDialogInfoRequestData.cs b/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/GetMailDialogInfoRequestData.cs
index c40acdc7..b000d127 100644
--- a/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/GetMailDialogInfoRequestData.cs
+++ b/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/GetMailDialogInfoRequestData.cs
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
+using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Utils;
namespace SPTarkov.Server.Core.Models.Eft.Dialog;
@@ -9,5 +10,5 @@ public record GetMailDialogInfoRequestData : IRequestData
public Dictionary? ExtensionData { get; set; }
[JsonPropertyName("dialogId")]
- public string? DialogId { get; set; }
+ public MongoId? DialogId { get; set; }
}
diff --git a/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/PinDialogRequestData.cs b/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/PinDialogRequestData.cs
index a9a8907b..a91e7289 100644
--- a/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/PinDialogRequestData.cs
+++ b/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/PinDialogRequestData.cs
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
+using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Utils;
namespace SPTarkov.Server.Core.Models.Eft.Dialog;
@@ -9,5 +10,5 @@ public record PinDialogRequestData : IRequestData
public Dictionary? ExtensionData { get; set; }
[JsonPropertyName("dialogId")]
- public string? DialogId { get; set; }
+ public MongoId? DialogId { get; set; }
}
diff --git a/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/RemoveDialogRequestData.cs b/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/RemoveDialogRequestData.cs
index 5159baf1..6e60742a 100644
--- a/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/RemoveDialogRequestData.cs
+++ b/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/RemoveDialogRequestData.cs
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
+using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Utils;
namespace SPTarkov.Server.Core.Models.Eft.Dialog;
@@ -9,5 +10,5 @@ public record RemoveDialogRequestData : IRequestData
public Dictionary? ExtensionData { get; set; }
[JsonPropertyName("dialogId")]
- public string? DialogId { get; set; }
+ public MongoId? DialogId { get; set; }
}
diff --git a/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/SetDialogReadRequestData.cs b/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/SetDialogReadRequestData.cs
index cc5e64cc..97b067ac 100644
--- a/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/SetDialogReadRequestData.cs
+++ b/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/SetDialogReadRequestData.cs
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
+using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Utils;
namespace SPTarkov.Server.Core.Models.Eft.Dialog;
@@ -9,5 +10,5 @@ public record SetDialogReadRequestData : IRequestData
public Dictionary? ExtensionData { get; set; }
[JsonPropertyName("dialogs")]
- public List? Dialogs { get; set; }
+ public List? Dialogs { get; set; }
}
diff --git a/Libraries/SPTarkov.Server.Core/Models/Eft/Profile/SptProfile.cs b/Libraries/SPTarkov.Server.Core/Models/Eft/Profile/SptProfile.cs
index 0b9f0648..a6951af2 100644
--- a/Libraries/SPTarkov.Server.Core/Models/Eft/Profile/SptProfile.cs
+++ b/Libraries/SPTarkov.Server.Core/Models/Eft/Profile/SptProfile.cs
@@ -30,7 +30,7 @@ public record SptProfile
public UserBuilds? UserBuildData { get; set; }
[JsonPropertyName("dialogues")]
- public Dictionary? DialogueRecords { get; set; }
+ public Dictionary? DialogueRecords { get; set; }
[JsonPropertyName("spt")]
public Spt? SptData { get; set; }
@@ -249,7 +249,7 @@ public record DialogueInfo
public int? New { get; set; }
[JsonPropertyName("_id")]
- public string? Id { get; set; }
+ public MongoId Id { get; set; }
[JsonPropertyName("type")]
public MessageType? Type { get; set; }
diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/CoreConfig.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/CoreConfig.cs
index 51274b0f..0c39e6eb 100644
--- a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/CoreConfig.cs
+++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/CoreConfig.cs
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
+using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Eft.Game;
namespace SPTarkov.Server.Core.Models.Spt.Config;
@@ -258,7 +259,7 @@ public record ChatbotFeatures
/// Bot Ids player is allowed to interact with
///
[JsonPropertyName("enabledBots")]
- public required Dictionary EnabledBots { get; set; }
+ public required Dictionary EnabledBots { get; set; }
}
public record CommandoFeatures