diff --git a/Core/Controllers/GameController.cs b/Core/Controllers/GameController.cs
index 01431e45..e0fe9aeb 100644
--- a/Core/Controllers/GameController.cs
+++ b/Core/Controllers/GameController.cs
@@ -11,6 +11,7 @@ using Core.Servers;
using Core.Services;
using Core.Utils;
using Core.Utils.Cloners;
+using Core.Utils.Json;
using Server;
@@ -55,101 +56,115 @@ public class GameController(
///
///
///
- public void GameStart(string url, EmptyRequestData info, string sessionId, long startTimeStampMs)
+ public void GameStart(string url, EmptyRequestData info, string? sessionId, long startTimeStampMs)
{
// Store client start time in app context
_applicationContext.AddValue(ContextVariableType.CLIENT_START_TIMESTAMP, $"{sessionId}_{startTimeStampMs}");
+ if (sessionId is null)
+ {
+ _logger.Error($"{nameof(sessionId)} is null on GameController.GameStart");
+ return;
+ }
+
_profileActivityService.SetActivityTimestamp(sessionId);
// repeatableQuests are stored by in profile.Quests due to the responses of the client (e.g. Quests in
// offraidData). Since we don't want to clutter the Quests list, we need to remove all completed (failed or
// successful) repeatable quests. We also have to remove the Counters from the repeatableQuests
- if (sessionId != null)
+
+ var fullProfile = _profileHelper.GetFullProfile(sessionId);
+
+ if (fullProfile is null)
{
- var fullProfile = _profileHelper.GetFullProfile(sessionId);
- if (fullProfile.ProfileInfo.IsWiped.Value)
- return;
-
- if (fullProfile.SptData.Migrations == null)
- fullProfile.SptData.Migrations = new();
-
- if (fullProfile.FriendProfileIds == null)
- fullProfile.FriendProfileIds = new();
-
- if (fullProfile.SptData.Version.Contains("3.9.") && fullProfile.SptData.Migrations.All(m => m.Key != "39x"))
- {
- _inventoryHelper.ValidateInventoryUsesMongoIds(fullProfile.CharacterData.PmcData.Inventory.Items);
- Migrate39xProfile(fullProfile);
-
- // flag as migrated
- fullProfile.SptData.Migrations.Add("39x", _timeUtil.GetTimeStamp());
- _logger.Info($"Migration of 3.9.x profile: {fullProfile.ProfileInfo.Username} completed successfully");
- }
-
- //3.10 migrations
- if (fullProfile.SptData.Version.Contains("3.10.") && fullProfile.SptData.Migrations.All(m => m.Key != "310x"))
- {
- Migrate310xProfile(fullProfile);
-
- // Flag as migrated
- fullProfile.SptData.Migrations["310x"] = _timeUtil.GetTimeStamp();
-
- _logger.Success($"Migration of 3.10.x profile: ${fullProfile.ProfileInfo.Username} completed successfully");
- }
-
- // with our method of converting type from array for this prop, we *might* not need this?
- // if (Array.isArray(fullProfile.characters.pmc.WishList)) {
- // fullProfile.characters.pmc.WishList = {};
- // }
- //
- // if (Array.isArray(fullProfile.characters.scav.WishList)) {
- // fullProfile.characters.scav.WishList = {};
- // }
-
- if (fullProfile.DialogueRecords != null)
- _profileFixerService.CheckForAndFixDialogueAttachments(fullProfile);
-
- _logger.Debug($"Started game with session {sessionId} {fullProfile.ProfileInfo.Username}");
-
- var pmcProfile = fullProfile.CharacterData.PmcData;
-
- if (_coreConfig.Fixes.FixProfileBreakingInventoryItemIssues)
- _profileFixerService.FixProfileBreakingInventoryItemIssues(pmcProfile);
-
- if (pmcProfile.Health != null)
- UpdateProfileHealthValues(pmcProfile);
-
- if (pmcProfile.Inventory != null)
- {
- SendPraporGiftsToNewProfiles(pmcProfile);
- _profileFixerService.CheckForOrphanedModdedItems(sessionId, fullProfile);
- }
-
- _profileFixerService.CheckForAndRemoveInvalidTraders(fullProfile);
- _profileFixerService.CheckForAndFixPmcProfileIssues(pmcProfile);
-
- if (pmcProfile.Hideout != null)
- {
- _profileFixerService.AddMissingHideoutBonusesToProfile(pmcProfile);
- _hideoutHelper.SetHideoutImprovementsToCompleted(pmcProfile);
- _hideoutHelper.UnlockHideoutWallInProfile(pmcProfile);
- }
-
- LogProfileDetails(fullProfile);
- SaveActiveModsToProfile(fullProfile);
-
- if (pmcProfile.Info != null)
- {
- AddPlayerToPmcNames(pmcProfile);
- CheckForAndRemoveUndefinedDialogues(fullProfile);
- }
-
- if (pmcProfile.Skills.Common != null)
- WarnOnActiveBotReloadSkill(pmcProfile);
-
- _seasonalEventService.GivePlayerSeasonalGifts(sessionId);
+ _logger.Error($"{nameof(fullProfile)} is null on GameController.GameStart");
+ return;
}
+
+ if (fullProfile.SptData is null)
+ {
+ _logger.Error($"{nameof(fullProfile.SptData)} is null on GameController.GameStart");
+ return;
+ }
+
+ if (fullProfile.SptData.Version is null)
+ {
+ _logger.Error($"{nameof(fullProfile.SptData.Version)} is null on GameController.GameStart");
+ return;
+ }
+
+ if (fullProfile.ProfileInfo?.IsWiped is not null && fullProfile.ProfileInfo.IsWiped.Value)
+ return;
+
+ fullProfile.SptData.Migrations ??= new Dictionary();
+ fullProfile.FriendProfileIds ??= [];
+
+ if (fullProfile.SptData.Version.Contains("3.9.") && fullProfile.SptData.Migrations.All(m => m.Key != "39x"))
+ {
+ _inventoryHelper.ValidateInventoryUsesMongoIds(fullProfile.CharacterData?.PmcData?.Inventory?.Items ?? []);
+ Migrate39xProfile(fullProfile);
+
+ // flag as migrated
+ fullProfile.SptData.Migrations.Add("39x", _timeUtil.GetTimeStamp());
+ _logger.Info($"Migration of 3.9.x profile: {fullProfile.ProfileInfo?.Username} completed successfully");
+ }
+
+ //3.10 migrations
+ if (fullProfile.SptData.Version.Contains("3.10.") && fullProfile.SptData.Migrations.All(m => m.Key != "310x"))
+ {
+ Migrate310xProfile(fullProfile);
+
+ // Flag as migrated
+ fullProfile.SptData.Migrations["310x"] = _timeUtil.GetTimeStamp();
+
+ _logger.Success($"Migration of 3.10.x profile: ${fullProfile.ProfileInfo?.Username} completed successfully");
+ }
+
+ fullProfile.CharacterData!.PmcData!.WishList ??= new DictionaryOrList(new Dictionary(), []);
+ fullProfile.CharacterData.ScavData!.WishList ??= new DictionaryOrList(new Dictionary(), []);
+
+ if (fullProfile.DialogueRecords is not null)
+ _profileFixerService.CheckForAndFixDialogueAttachments(fullProfile);
+
+ _logger.Debug($"Started game with session {sessionId} {fullProfile.ProfileInfo?.Username}");
+
+ var pmcProfile = fullProfile.CharacterData.PmcData;
+
+ if (_coreConfig.Fixes.FixProfileBreakingInventoryItemIssues)
+ _profileFixerService.FixProfileBreakingInventoryItemIssues(pmcProfile);
+
+ if (pmcProfile.Health is not null)
+ UpdateProfileHealthValues(pmcProfile);
+
+ if (pmcProfile.Inventory is not null)
+ {
+ SendPraporGiftsToNewProfiles(pmcProfile);
+ _profileFixerService.CheckForOrphanedModdedItems(sessionId, fullProfile);
+ }
+
+ _profileFixerService.CheckForAndRemoveInvalidTraders(fullProfile);
+ _profileFixerService.CheckForAndFixPmcProfileIssues(pmcProfile);
+
+ if (pmcProfile.Hideout is not null)
+ {
+ _profileFixerService.AddMissingHideoutBonusesToProfile(pmcProfile);
+ _hideoutHelper.SetHideoutImprovementsToCompleted(pmcProfile);
+ _hideoutHelper.UnlockHideoutWallInProfile(pmcProfile);
+ }
+
+ LogProfileDetails(fullProfile);
+ SaveActiveModsToProfile(fullProfile);
+
+ if (pmcProfile.Info is not null)
+ {
+ AddPlayerToPmcNames(pmcProfile);
+ CheckForAndRemoveUndefinedDialogues(fullProfile);
+ }
+
+ if (pmcProfile.Skills?.Common is not null)
+ WarnOnActiveBotReloadSkill(pmcProfile);
+
+ _seasonalEventService.GivePlayerSeasonalGifts(sessionId);
}
private void Migrate39xProfile(SptProfile fullProfile)
@@ -180,13 +195,9 @@ public class GameController(
public GameConfigResponse GetGameConfig(string sessionId)
{
var profile = _profileHelper.GetPmcProfile(sessionId);
- var gameTime = profile?.Stats?.Eft?.OverallCounters?.Items?.FirstOrDefault(
- c =>
- c.Key.Contains("LifeTime") &&
- c.Key.Contains("Pmc")
- )
- ?.Value ??
- 0D;
+ var gameTime = profile?.Stats?.Eft?.OverallCounters?.Items?
+ .FirstOrDefault(c => c.Key!.Contains("LifeTime")
+ && c.Key.Contains("Pmc"))?.Value ?? 0D;
var config = new GameConfigResponse
{
@@ -195,7 +206,7 @@ public class GameController(
IsReportAvailable = false,
IsTwitchEventMember = false,
Language = "en",
- Aid = profile.Aid,
+ Aid = profile?.Aid,
Taxonomy = 6,
ActiveProfileId = sessionId,
Backend = new()
@@ -338,7 +349,7 @@ public class GameController(
/// Profile to adjust values for
private void UpdateProfileHealthValues(PmcData pmcProfile)
{
- var healthLastUpdated = pmcProfile.Health.UpdateTime;
+ var healthLastUpdated = pmcProfile.Health?.UpdateTime;
var currentTimeStamp = _timeUtil.GetTimeStamp();
var diffSeconds = currentTimeStamp - healthLastUpdated;
@@ -351,21 +362,21 @@ public class GameController(
double hpRegenPerHour = 456.6;
// Set new values, whatever is smallest
- energyRegenPerHour += pmcProfile.Bonuses
+ energyRegenPerHour += pmcProfile.Bonuses!
.Where((bonus) => bonus.Type == BonusType.EnergyRegeneration)
- .Aggregate(0d, (sum, bonus) => sum + (bonus.Value.Value));
- hydrationRegenPerHour += pmcProfile.Bonuses
+ .Aggregate(0d, (sum, bonus) => sum + (bonus.Value!.Value));
+ hydrationRegenPerHour += pmcProfile.Bonuses!
.Where((bonus) => bonus.Type == BonusType.HydrationRegeneration)
- .Aggregate(0d, (sum, bonus) => sum + (bonus.Value.Value));
- hpRegenPerHour += pmcProfile.Bonuses
+ .Aggregate(0d, (sum, bonus) => sum + (bonus.Value!.Value));
+ hpRegenPerHour += pmcProfile.Bonuses!
.Where((bonus) => bonus.Type == BonusType.HealthRegeneration)
- .Aggregate(0d, (sum, bonus) => sum + (bonus.Value.Value));
+ .Aggregate(0d, (sum, bonus) => sum + (bonus.Value!.Value));
// Player has energy deficit
- if (pmcProfile.Health.Energy.Current != pmcProfile.Health.Energy.Maximum)
+ if (pmcProfile.Health?.Energy?.Current != pmcProfile.Health?.Energy?.Maximum)
{
// Set new value, whatever is smallest
- pmcProfile.Health.Energy.Current += Math.Round(energyRegenPerHour * (diffSeconds.Value / 3600));
+ pmcProfile.Health!.Energy!.Current += Math.Round(energyRegenPerHour * (diffSeconds!.Value / 3600));
if (pmcProfile.Health.Energy.Current > pmcProfile.Health.Energy.Maximum)
{
pmcProfile.Health.Energy.Current = pmcProfile.Health.Energy.Maximum;
@@ -373,9 +384,9 @@ public class GameController(
}
// Player has hydration deficit
- if (pmcProfile.Health.Hydration.Current != pmcProfile.Health.Hydration.Maximum)
+ if (pmcProfile.Health?.Hydration?.Current != pmcProfile.Health?.Hydration?.Maximum)
{
- pmcProfile.Health.Hydration.Current += Math.Round(hydrationRegenPerHour * (diffSeconds.Value / 3600));
+ pmcProfile.Health!.Hydration!.Current += Math.Round(hydrationRegenPerHour * (diffSeconds!.Value / 3600));
if (pmcProfile.Health.Hydration.Current > pmcProfile.Health.Hydration.Maximum)
{
pmcProfile.Health.Hydration.Current = pmcProfile.Health.Hydration.Maximum;
@@ -383,13 +394,13 @@ public class GameController(
}
// Check all body parts
- foreach (var bodyPart in pmcProfile.Health.BodyParts
+ foreach (var bodyPart in pmcProfile.Health!.BodyParts!
.Select(bodyPartKvP => bodyPartKvP.Value))
{
// Check part hp
- if (bodyPart.Health.Current < bodyPart.Health.Maximum)
+ if (bodyPart.Health!.Current < bodyPart.Health.Maximum)
{
- bodyPart.Health.Current += Math.Round(hpRegenPerHour * (diffSeconds.Value / 3600));
+ bodyPart.Health.Current += Math.Round(hpRegenPerHour * (diffSeconds!.Value / 3600));
}
if (bodyPart.Health.Current > bodyPart.Health.Maximum)
@@ -439,20 +450,20 @@ public class GameController(
/// Profile to add gifts to
private void SendPraporGiftsToNewProfiles(PmcData pmcProfile)
{
- var timeStampProfileCreated = pmcProfile.Info.RegistrationDate;
+ var timeStampProfileCreated = pmcProfile.Info?.RegistrationDate;
var oneDaySeconds = _timeUtil.GetHoursAsSeconds(24);
var currentTimeStamp = _timeUtil.GetTimeStamp();
// One day post-profile creation
if (currentTimeStamp > timeStampProfileCreated + oneDaySeconds)
{
- _giftService.SendPraporStartingGift(pmcProfile.SessionId, 1);
+ _giftService.SendPraporStartingGift(pmcProfile.SessionId!, 1);
}
// Two day post-profile creation
if (currentTimeStamp > timeStampProfileCreated + oneDaySeconds * 2)
{
- _giftService.SendPraporStartingGift(pmcProfile.SessionId, 2);
+ _giftService.SendPraporStartingGift(pmcProfile.SessionId!, 2);
}
}
@@ -463,41 +474,38 @@ public class GameController(
private void SaveActiveModsToProfile(SptProfile fullProfile)
{
// Add empty mod array if undefined
- if (fullProfile.SptData.Mods is null)
- {
- fullProfile.SptData.Mods = [];
- }
+ fullProfile.SptData!.Mods ??= [];
// Get active mods
_logger.Error("NOT IMPLEMENTED - _preSptModLoader SaveActiveModsToProfile()");
- //var activeMods = _preSptModLoader.GetImportedModDetails(); //TODO IMPLEMENT _preSptModLoader
- var activeMods = new Dictionary();
- foreach (var modKvP in activeMods)
- {
- var modDetails = modKvP.Value;
- if (
- fullProfile.SptData.Mods.Any(
- (mod) =>
- mod.Author == modDetails.Author &&
- mod.Name == modDetails.Name &&
- mod.Version == modDetails.Version
- ))
- {
- // Exists already, skip
- continue;
- }
-
- fullProfile.SptData.Mods.Add(
- new ModDetails
- {
- Author = modDetails.Author,
- DateAdded = _timeUtil.GetTimeStamp(),
- Name = modDetails.Name,
- Version = modDetails.Version,
- Url = modDetails.Url,
- }
- );
- }
+ //var activeMods = _preSptModLoader.GetImportedModDetails(); // TODO IMPLEMENT _preSptModLoader
+ // var activeMods = new Dictionary();
+ // foreach (var modKvP in activeMods)
+ // {
+ // var modDetails = modKvP.Value;
+ // if (
+ // fullProfile.SptData.Mods.Any(
+ // (mod) =>
+ // mod.Author == modDetails.Author &&
+ // mod.Name == modDetails.Name &&
+ // mod.Version == modDetails.Version
+ // ))
+ // {
+ // // Exists already, skip
+ // continue;
+ // }
+ //
+ // fullProfile.SptData.Mods.Add(
+ // new ModDetails
+ // {
+ // Author = modDetails.Author,
+ // DateAdded = _timeUtil.GetTimeStamp(),
+ // Name = modDetails.Name,
+ // Version = modDetails.Version,
+ // Url = modDetails.Url,
+ // }
+ // );
+ // }
}
///
@@ -506,7 +514,7 @@ public class GameController(
/// Profile of player to get name from
private void AddPlayerToPmcNames(PmcData pmcProfile)
{
- var playerName = pmcProfile.Info.Nickname;
+ var playerName = pmcProfile.Info?.Nickname;
if (playerName is not null)
{
var bots = _databaseService.GetBots().Types;
@@ -518,19 +526,19 @@ public class GameController(
}
// Skip if player name exists already
- if (bots.TryGetValue("bear", out var bearBot))
+ if (bots!.TryGetValue("bear", out var bearBot))
{
- if (bearBot is not null && bearBot.FirstNames.Any(x => x == playerName))
+ if (bearBot is not null && bearBot.FirstNames!.Any(x => x == playerName))
{
- bearBot.FirstNames.Add(playerName);
+ bearBot.FirstNames!.Add(playerName);
}
}
if (bots.TryGetValue("bear", out var usecBot))
{
- if (usecBot is not null && usecBot.FirstNames.Any(x => x == playerName))
+ if (usecBot is not null && usecBot.FirstNames!.Any(x => x == playerName))
{
- usecBot.FirstNames.Add(playerName);
+ usecBot.FirstNames!.Add(playerName);
}
}
}
@@ -542,7 +550,7 @@ public class GameController(
/// Profile to check for dialog in
private void CheckForAndRemoveUndefinedDialogues(SptProfile fullProfile)
{
- if (fullProfile.DialogueRecords.TryGetValue("undefined", out var undefinedDialog))
+ if (fullProfile.DialogueRecords!.TryGetValue("undefined", out var _))
{
fullProfile.DialogueRecords.Remove("undefined");
}
@@ -554,10 +562,10 @@ public class GameController(
///
private void LogProfileDetails(SptProfile fullProfile)
{
- _logger.Debug($"Profile made with: {fullProfile.SptData.Version}");
- _logger.Debug($"Server version: {(ProgramStatics.SPT_VERSION()) ?? _coreConfig.SptVersion} {ProgramStatics.COMMIT}");
- _logger.Debug($"Debug enabled: {ProgramStatics.DEBUG}");
- _logger.Debug($"Mods enabled: {ProgramStatics.MODS}");
+ _logger.Debug($"Profile made with: {fullProfile.SptData?.Version}");
+ _logger.Debug($"Server version: {(ProgramStatics.SPT_VERSION()) ?? _coreConfig.SptVersion} {ProgramStatics.COMMIT()}");
+ _logger.Debug($"Debug enabled: {ProgramStatics.DEBUG()}");
+ _logger.Debug($"Mods enabled: {ProgramStatics.MODS()}");
}
public void Load()
diff --git a/Core/Models/Spt/Bots/Bots.cs b/Core/Models/Spt/Bots/Bots.cs
index 1fe654b1..e782d1fb 100644
--- a/Core/Models/Spt/Bots/Bots.cs
+++ b/Core/Models/Spt/Bots/Bots.cs
@@ -6,7 +6,7 @@ namespace Core.Models.Spt.Bots;
public record Bots
{
[JsonPropertyName("types")]
- public Dictionary? Types { get; set; }
+ public Dictionary? Types { get; set; }
[JsonPropertyName("base")]
public BotBase? Base { get; set; }
diff --git a/Core/Utils/ProgramStatics.cs b/Core/Utils/ProgramStatics.cs
index 720fffd7..028ea586 100644
--- a/Core/Utils/ProgramStatics.cs
+++ b/Core/Utils/ProgramStatics.cs
@@ -8,9 +8,9 @@ namespace Server
private static bool _compiled;
private static bool _mods;
- private static string _sptVersion;
- private static string _commit;
- private static double _buildTime;
+ private static string? _sptVersion;
+ private static string? _commit;
+ private static double? _buildTime;
private static BuildInfo buildInfo; // TODO get from buildinfo.json
@@ -63,15 +63,15 @@ namespace Server
{
return ProgramStatics._mods;
}
- public static string SPT_VERSION()
+ public static string? SPT_VERSION()
{
return ProgramStatics._sptVersion;
}
- public static string COMMIT()
+ public static string? COMMIT()
{
return ProgramStatics._commit;
}
- public static double BUILD_TIME()
+ public static double? BUILD_TIME()
{
return ProgramStatics._buildTime;
}