diff --git a/Libraries/SPTarkov.Server.Core/Helpers/ModHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/ModHelper.cs
index 3c257120..d9c1909e 100644
--- a/Libraries/SPTarkov.Server.Core/Helpers/ModHelper.cs
+++ b/Libraries/SPTarkov.Server.Core/Helpers/ModHelper.cs
@@ -1,4 +1,4 @@
-using System.Reflection;
+using System.Reflection;
using SPTarkov.DI.Annotations;
using SPTarkov.Server.Core.Utils;
diff --git a/Libraries/SPTarkov.Server.Core/Helpers/NotificationSendHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/NotificationSendHelper.cs
index 97697719..9251081b 100644
--- a/Libraries/SPTarkov.Server.Core/Helpers/NotificationSendHelper.cs
+++ b/Libraries/SPTarkov.Server.Core/Helpers/NotificationSendHelper.cs
@@ -25,30 +25,31 @@ public class NotificationSendHelper(
///
/// Send notification message to the appropriate channel
///
- /// Session/player id
+ /// Session/player id
///
- public void SendMessage(MongoId sessionID, WsNotificationEvent notificationMessage)
+ public void SendMessage(MongoId sessionId, WsNotificationEvent notificationMessage)
{
if (logger.IsLogEnabled(LogLevel.Debug))
{
- logger.Debug($"Send message for {sessionID} started, message: {jsonUtil.Serialize(notificationMessage)}");
+ logger.Debug($"Send message for {sessionId} started, message: {jsonUtil.Serialize(notificationMessage)}");
}
- if (sptWebSocketConnectionHandler.IsWebSocketConnected(sessionID))
+
+ if (sptWebSocketConnectionHandler.IsWebSocketConnected(sessionId))
{
if (logger.IsLogEnabled(LogLevel.Debug))
{
- logger.Debug($"Send message for {sessionID} websocket available, message being sent");
+ logger.Debug($"Send message for {sessionId} websocket available, message being sent");
}
- sptWebSocketConnectionHandler.SendMessage(sessionID, notificationMessage);
+ sptWebSocketConnectionHandler.SendMessage(sessionId, notificationMessage);
+ return;
}
- else
+
+ if (logger.IsLogEnabled(LogLevel.Debug))
{
- if (logger.IsLogEnabled(LogLevel.Debug))
- {
- logger.Debug($"Send message for {sessionID} websocket not available, queueing into profile");
- }
- notificationService.Add(sessionID, notificationMessage);
+ logger.Debug($"Send message for {sessionId} websocket not available, queueing into profile");
}
+
+ notificationService.Add(sessionId, notificationMessage);
}
///
@@ -61,6 +62,11 @@ public class NotificationSendHelper(
public void SendMessageToPlayer(MongoId sessionId, UserDialogInfo senderDetails, string messageText, MessageType messageType)
{
var dialog = GetDialog(sessionId, messageType, senderDetails);
+ if (dialog is null)
+ {
+ // Error is logged in GetDialog
+ return;
+ }
dialog.New += 1;
var message = new Message
@@ -74,7 +80,18 @@ public class NotificationSendHelper(
RewardCollected = null,
Items = null,
};
- dialog.Messages.Add(message);
+
+ if (dialog.Messages != null)
+ {
+ dialog.Messages.Add(message);
+ }
+ else
+ {
+ logger.Error(
+ $"Could not add message Id: {message.Id.ToString()} to dialogue for player Id: {sessionId.ToString()}. dialog.Messages is null. Message was not sent."
+ );
+ return;
+ }
var notification = new WsChatMessageReceived
{
@@ -93,7 +110,7 @@ public class NotificationSendHelper(
/// Type of message to generate
/// Who is sending the message
/// Dialogue
- protected Models.Eft.Profile.Dialogue GetDialog(MongoId sessionId, MessageType messageType, UserDialogInfo senderDetails)
+ protected Models.Eft.Profile.Dialogue? GetDialog(MongoId sessionId, MessageType messageType, UserDialogInfo senderDetails)
{
// Use trader id if sender is trader, otherwise use nickname
var dialogKey = senderDetails.Id;
@@ -102,12 +119,23 @@ public class NotificationSendHelper(
var dialogueData = saveServer.GetProfile(sessionId).DialogueRecords;
// Ensure empty dialog exists based on sender details passed in
- dialogueData.TryAdd(dialogKey, GetEmptyDialogTemplate(dialogKey, messageType, senderDetails));
+ if (dialogueData?.TryAdd(dialogKey, GetEmptyDialogTemplate(dialogKey, messageType, senderDetails)) ?? false)
+ {
+ return dialogueData[dialogKey];
+ }
- return dialogueData[dialogKey];
+ logger.Error($"Could not add dialog key: {dialogKey.ToString()} to dialogueData for player Id: {sessionId.ToString()}.");
+ return null;
}
- protected Models.Eft.Profile.Dialogue GetEmptyDialogTemplate(string dialogKey, MessageType messageType, UserDialogInfo senderDetails)
+ ///
+ /// Get an empty dialog template
+ ///
+ /// Key to assign
+ /// Type of message
+ /// Sender details
+ /// Empty dialog template
+ protected Models.Eft.Profile.Dialogue GetEmptyDialogTemplate(MongoId dialogKey, MessageType messageType, UserDialogInfo senderDetails)
{
return new Models.Eft.Profile.Dialogue
{
@@ -117,7 +145,7 @@ public class NotificationSendHelper(
Pinned = false,
New = 0,
AttachmentsNew = 0,
- Users = senderDetails.Info.MemberCategory == MemberCategory.Trader ? null : [senderDetails],
+ Users = senderDetails.Info?.MemberCategory == MemberCategory.Trader ? null : [senderDetails],
};
}
}
diff --git a/Libraries/SPTarkov.Server.Core/Helpers/NotifierHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/NotifierHelper.cs
index 75dc8aec..a8b35245 100644
--- a/Libraries/SPTarkov.Server.Core/Helpers/NotifierHelper.cs
+++ b/Libraries/SPTarkov.Server.Core/Helpers/NotifierHelper.cs
@@ -8,11 +8,11 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable(InjectionType.Singleton)]
public class NotifierHelper(HttpServerHelper httpServerHelper)
{
- protected static readonly WsPing ping = new();
+ protected static readonly WsPing Ping = new();
public WsNotificationEvent GetDefaultNotification()
{
- return ping;
+ return Ping;
}
///
diff --git a/Libraries/SPTarkov.Server.Core/Helpers/PaymentHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/PaymentHelper.cs
index 90f33f82..9df39fab 100644
--- a/Libraries/SPTarkov.Server.Core/Helpers/PaymentHelper.cs
+++ b/Libraries/SPTarkov.Server.Core/Helpers/PaymentHelper.cs
@@ -9,9 +9,9 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable(InjectionType.Singleton)]
public class PaymentHelper(ConfigServer configServer)
{
- protected bool _addedCustomMoney;
- protected readonly InventoryConfig _inventoryConfig = configServer.GetConfig();
- protected readonly HashSet _moneyTpls = [Money.DOLLARS, Money.EUROS, Money.ROUBLES, Money.GP];
+ protected bool AddedCustomMoney;
+ protected readonly InventoryConfig InventoryConfig = configServer.GetConfig();
+ protected readonly HashSet MoneyTpls = [Money.DOLLARS, Money.EUROS, Money.ROUBLES, Money.GP];
///
/// Is the passed in tpl money (also checks custom currencies in inventoryConfig.customMoneyTpls)
@@ -21,16 +21,16 @@ public class PaymentHelper(ConfigServer configServer)
public bool IsMoneyTpl(MongoId tpl)
{
// Add custom currency first time this method is accessed
- if (!_addedCustomMoney)
+ if (!AddedCustomMoney)
{
- foreach (var customMoney in _inventoryConfig.CustomMoneyTpls)
+ foreach (var customMoney in InventoryConfig.CustomMoneyTpls)
{
- _moneyTpls.Add(customMoney);
+ MoneyTpls.Add(customMoney);
}
- _addedCustomMoney = true;
+ AddedCustomMoney = true;
}
- return _moneyTpls.Contains(tpl);
+ return MoneyTpls.Contains(tpl);
}
}
diff --git a/Libraries/SPTarkov.Server.Core/Helpers/PresetHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/PresetHelper.cs
index f3734be1..24ed71e1 100644
--- a/Libraries/SPTarkov.Server.Core/Helpers/PresetHelper.cs
+++ b/Libraries/SPTarkov.Server.Core/Helpers/PresetHelper.cs
@@ -10,17 +10,17 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable(InjectionType.Singleton)]
public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper, ICloner cloner)
{
- protected Dictionary? _defaultEquipmentPresets;
- protected Dictionary? _defaultWeaponPresets;
+ protected Dictionary? DefaultEquipmentPresets;
+ protected Dictionary? DefaultWeaponPresets;
///
/// Preset cache - key = item tpl, value = preset ids
///
- protected Dictionary _lookup = new();
+ protected Dictionary PresetCache = new();
public void HydratePresetStore(Dictionary input)
{
- _lookup = input;
+ PresetCache = input;
}
///
@@ -48,7 +48,7 @@ public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper
return weapons
.Concat(equipment)
.Where(preset => preset.Items.Count > 0) // Some safety to prevent nullref
- .ToDictionary(preset => preset.Items.FirstOrDefault().Template);
+ .ToDictionary(preset => preset.Items.FirstOrDefault()!.Template);
}
///
@@ -57,15 +57,15 @@ public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper
///
public Dictionary GetDefaultWeaponPresets()
{
- if (_defaultWeaponPresets is null)
+ if (DefaultWeaponPresets is null)
{
var tempPresets = databaseService.GetGlobals().ItemPresets;
- _defaultWeaponPresets = tempPresets
+ DefaultWeaponPresets = tempPresets
.Where(p => p.Value.Encyclopedia != null && itemHelper.IsOfBaseclass(p.Value.Encyclopedia.Value, BaseClasses.WEAPON))
.ToDictionary();
}
- return _defaultWeaponPresets;
+ return DefaultWeaponPresets;
}
///
@@ -74,15 +74,15 @@ public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper
/// Dictionary
public Dictionary GetDefaultEquipmentPresets()
{
- if (_defaultEquipmentPresets == null)
+ if (DefaultEquipmentPresets == null)
{
var tempPresets = databaseService.GetGlobals().ItemPresets;
- _defaultEquipmentPresets = tempPresets
+ DefaultEquipmentPresets = tempPresets
.Where(p => p.Value.Encyclopedia != null && itemHelper.ArmorItemCanHoldMods(p.Value.Encyclopedia.Value))
.ToDictionary();
}
- return _defaultEquipmentPresets;
+ return DefaultEquipmentPresets;
}
///
@@ -108,7 +108,7 @@ public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper
/// True if the preset is of the given base class, false otherwise
public bool IsPresetBaseClass(MongoId id, MongoId baseClass)
{
- return IsPreset(id) && itemHelper.IsOfBaseclass(GetPreset(id).Encyclopedia.Value, baseClass);
+ return IsPreset(id) && itemHelper.IsOfBaseclass(GetPreset(id)!.Encyclopedia!.Value, baseClass);
}
///
@@ -118,10 +118,10 @@ public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper
/// True if preset exists for tpl
public bool HasPreset(MongoId templateId)
{
- return _lookup.ContainsKey(templateId);
+ return PresetCache.ContainsKey(templateId);
}
- public Preset GetPreset(MongoId id)
+ public Preset? GetPreset(MongoId id)
{
return cloner.Clone(databaseService.GetGlobals().ItemPresets[id]);
}
@@ -130,7 +130,7 @@ public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper
/// Get all presets from globals db
///
/// List
- public List GetAllPresets()
+ public List? GetAllPresets()
{
return cloner.Clone(databaseService.GetGlobals().ItemPresets.Values.ToList());
}
@@ -140,10 +140,10 @@ public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper
///
/// Tpl to get presets for
/// List
- public List GetPresets(MongoId templateId)
+ public List? GetPresets(MongoId templateId)
{
- // Try adn get preset ids from cache if they exist
- if (!_lookup.TryGetValue(templateId, out var presetDetailsForTpl))
+ // Try and get preset ids from cache if they exist
+ if (!PresetCache.TryGetValue(templateId, out var presetDetailsForTpl))
{
// None found, early exit
return [];
@@ -161,7 +161,7 @@ public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper
public Preset? GetDefaultPreset(MongoId templateId)
{
// look in main cache for presets for this tpl
- if (!_lookup.TryGetValue(templateId, out var presetDetails))
+ if (!PresetCache.TryGetValue(templateId, out var presetDetails))
{
return null;
}
@@ -172,9 +172,9 @@ public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper
}
// Use default preset id from above cache to find the weapon/equipment preset
- if (!_defaultWeaponPresets.TryGetValue(presetDetails.DefaultId.Value, out var defaultPreset))
+ if (DefaultWeaponPresets?.TryGetValue(presetDetails.DefaultId.Value, out var defaultPreset) is null or false)
{
- if (!_defaultEquipmentPresets.TryGetValue(presetDetails.DefaultId.Value, out defaultPreset))
+ if (DefaultEquipmentPresets?.TryGetValue(presetDetails.DefaultId.Value, out defaultPreset) is null or false)
{
// Default not found in weapon or equipment, return first preset in list
return cloner.Clone(databaseService.GetGlobals().ItemPresets[presetDetails.PresetIds.First()]);
diff --git a/Libraries/SPTarkov.Server.Core/Helpers/PrestigeHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/PrestigeHelper.cs
index 5cea9010..6bed1752 100644
--- a/Libraries/SPTarkov.Server.Core/Helpers/PrestigeHelper.cs
+++ b/Libraries/SPTarkov.Server.Core/Helpers/PrestigeHelper.cs
@@ -22,9 +22,9 @@ public class PrestigeHelper(
{
public void ProcessPendingPrestige(SptProfile oldProfile, SptProfile newProfile, PendingPrestige prestige)
{
- var prePrestigePmc = oldProfile.CharacterData.PmcData;
- var sessionId = newProfile.ProfileInfo.ProfileId;
- var prestigeLevels = databaseService.GetTemplates().Prestige.Elements;
+ var prePrestigePmc = oldProfile.CharacterData?.PmcData;
+ var sessionId = newProfile.ProfileInfo?.ProfileId;
+ var prestigeLevels = databaseService.GetTemplates().Prestige?.Elements ?? [];
var indexOfPrestigeObtained = Math.Clamp((prestige.PrestigeLevel ?? 1) - 1, 0, prestigeLevels.Count - 1); // Levels are 1 to 4, Index is 0 to 3
// Skill copy
@@ -34,37 +34,39 @@ public class PrestigeHelper(
1 - prestigeLevels[indexOfPrestigeObtained].TransferConfigs.MasteringConfig.TransferMultiplier
);
- if (prePrestigePmc.Skills.Common is not null)
+ if (prePrestigePmc?.Skills?.Common is not null)
{
var commonSKillsToCopy = prePrestigePmc.Skills.Common;
foreach (var skillToCopy in commonSKillsToCopy)
{
// Set progress for 5% of what it was, multiplied by prestige level
skillToCopy.Progress *= skillProgressCopyAmount;
- var existingSkill = newProfile.CharacterData.PmcData.Skills.Common.FirstOrDefault(skill => skill.Id == skillToCopy.Id);
+ var existingSkill = newProfile.CharacterData?.PmcData?.Skills?.Common.FirstOrDefault(skill => skill.Id == skillToCopy.Id);
if (existingSkill is not null)
{
existingSkill.Progress = skillToCopy.Progress;
}
else
{
- newProfile.CharacterData.PmcData.Skills.Common = newProfile.CharacterData.PmcData.Skills.Common.Union([skillToCopy]);
+ newProfile.CharacterData!.PmcData!.Skills!.Common = newProfile.CharacterData.PmcData.Skills.Common.Union([skillToCopy]);
}
}
var masteringSkillsToCopy = prePrestigePmc.Skills.Mastering;
- foreach (var skillToCopy in masteringSkillsToCopy)
+ foreach (var skillToCopy in masteringSkillsToCopy ?? [])
{
// Set progress 5% of what it was, multiplied by prestige level
skillToCopy.Progress *= masteringProgressCopyAmount;
- var existingSkill = newProfile.CharacterData.PmcData.Skills.Mastering.FirstOrDefault(skill => skill.Id == skillToCopy.Id);
+ var existingSkill = newProfile.CharacterData?.PmcData?.Skills?.Mastering?.FirstOrDefault(skill =>
+ skill.Id == skillToCopy.Id
+ );
if (existingSkill is not null)
{
existingSkill.Progress = skillToCopy.Progress;
}
else
{
- newProfile.CharacterData.PmcData.Skills.Mastering = newProfile.CharacterData.PmcData.Skills.Mastering.Union(
+ newProfile.CharacterData!.PmcData!.Skills!.Mastering = newProfile.CharacterData.PmcData.Skills.Mastering?.Union(
[skillToCopy]
);
}
@@ -73,30 +75,35 @@ public class PrestigeHelper(
// Add "Prestigious" achievement
var prestigiousAchievement = new MongoId("676091c0f457869a94017a23");
- if (!newProfile.CharacterData.PmcData.Achievements.ContainsKey(prestigiousAchievement))
+ if (newProfile.CharacterData?.PmcData?.Achievements?.ContainsKey(prestigiousAchievement) is false)
{
rewardHelper.AddAchievementToProfile(newProfile, prestigiousAchievement);
}
// Assumes Prestige data is in descending order
- var currentPrestigeData = databaseService.GetTemplates().Prestige.Elements[indexOfPrestigeObtained];
+ var currentPrestigeData = databaseService.GetTemplates().Prestige?.Elements[indexOfPrestigeObtained];
// Get all prestige rewards from prestige 1 up to desired prestige
var prestigeRewards = prestigeLevels
.Slice(0, indexOfPrestigeObtained + 1) // Index back to PrestigeLevel
- .SelectMany(prestige => prestige.Rewards);
+ .SelectMany(prestigeInner => prestigeInner.Rewards);
- AddPrestigeRewardsToProfile(sessionId.Value, newProfile, prestigeRewards);
+ AddPrestigeRewardsToProfile(sessionId!.Value, newProfile, prestigeRewards);
// Flag profile as having achieved this prestige level
- newProfile.CharacterData.PmcData.Prestige.TryAdd(currentPrestigeData.Id, timeUtil.GetTimeStamp());
+ if (newProfile.CharacterData?.PmcData?.Prestige?.TryAdd(currentPrestigeData!.Id, timeUtil.GetTimeStamp()) is false)
+ {
+ logger.Error(
+ $"Failed to add prestige element with id: {currentPrestigeData.Id} to new profile during processing of pending prestige."
+ );
+ }
var itemsToTransfer = new List- ();
// Copy transferred items
foreach (var transferRequest in prestige.Items ?? [])
{
- var item = prePrestigePmc.Inventory.Items.FirstOrDefault(item => item.Id == transferRequest.Id);
+ var item = prePrestigePmc?.Inventory?.Items?.FirstOrDefault(item => item.Id == transferRequest.Id);
if (item is null)
{
logger.Error($"Unable to find item with id: {transferRequest.Id} in profile: {sessionId}, skipping");
@@ -116,7 +123,7 @@ public class PrestigeHelper(
);
}
- newProfile.CharacterData.PmcData.Info.PrestigeLevel = prestige.PrestigeLevel;
+ newProfile.CharacterData!.PmcData!.Info!.PrestigeLevel = prestige.PrestigeLevel;
}
private void AddPrestigeRewardsToProfile(MongoId sessionId, SptProfile newProfile, IEnumerable rewards)
@@ -135,7 +142,7 @@ public class PrestigeHelper(
case RewardType.Skill:
if (Enum.TryParse(reward.Target, out SkillTypes result))
{
- profileHelper.AddSkillPointsToPlayer(newProfile.CharacterData.PmcData, result, reward.Value.GetValueOrDefault(0));
+ profileHelper.AddSkillPointsToPlayer(newProfile.CharacterData!.PmcData!, result, reward.Value.GetValueOrDefault(0));
}
else
{
@@ -145,12 +152,12 @@ public class PrestigeHelper(
break;
case RewardType.Item:
{
- itemsToSend.AddRange(reward.Items);
+ itemsToSend.AddRange(reward.Items ?? []);
break;
}
case RewardType.ExtraDailyQuest:
{
- newProfile.AddExtraRepeatableQuest(new MongoId(reward.Target), (double)reward.Value);
+ newProfile.AddExtraRepeatableQuest(new MongoId(reward.Target), (double)reward.Value!);
break;
}
default: