Helpers Mongoid conversion + cleanup (#458)

* Start converting helper method ids to mongoids and remove underscore from injections...

* Finish helper mongoIds
This commit is contained in:
Cj
2025-07-06 12:31:59 -04:00
committed by GitHub
parent 0f917a103f
commit 3817d6cca4
37 changed files with 981 additions and 994 deletions
@@ -392,8 +392,8 @@ public class RagfairController
/// <returns>Array of offers</returns>
protected List<RagfairOffer> GetOffersForSearchType(
SearchRequestData searchRequest,
List<string> itemsToAdd,
Dictionary<string, TraderAssort> traderAssorts,
List<MongoId> itemsToAdd,
Dictionary<MongoId, TraderAssort> traderAssorts,
PmcData pmcProfile
)
{
@@ -1,5 +1,6 @@
using SPTarkov.DI.Annotations;
using SPTarkov.Server.Core.Extensions;
using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Eft.Common;
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
using SPTarkov.Server.Core.Models.Enums;
@@ -10,22 +11,22 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class AssortHelper(
ISptLogger<AssortHelper> _logger,
ServerLocalisationService _serverLocalisationService
ISptLogger<AssortHelper> logger,
ServerLocalisationService serverLocalisationService
)
{
/// <summary>
/// Remove assorts from a trader that have not been unlocked yet (via player completing corresponding quest)
/// </summary>
/// <param name="pmcProfile"></param>
/// <param name="traderId">Traders id the assort belongs to</param>
/// <param name="traderId">Traders id assort belongs to</param>
/// <param name="traderAssorts">All assort items from same trader</param>
/// <param name="mergedQuestAssorts">Dict of quest assort to quest id unlocks for all traders (key = started/failed/complete)</param>
/// <param name="isFlea">Is the trader assort being modified the flea market</param>
/// <returns>items minus locked quest assorts</returns>
public TraderAssort StripLockedQuestAssort(
PmcData pmcProfile,
string traderId,
MongoId traderId,
TraderAssort traderAssorts,
Dictionary<string, Dictionary<string, string>> mergedQuestAssorts,
bool isFlea = false
@@ -36,8 +37,8 @@ public class AssortHelper(
// Trader assort does not always contain loyal_level_items
if (traderAssorts.LoyalLevelItems is null)
{
_logger.Warning(
_serverLocalisationService.GetText("assort-missing_loyalty_level_object", traderId)
logger.Warning(
serverLocalisationService.GetText("assort-missing_loyalty_level_object", traderId)
);
return traderAssorts;
@@ -116,7 +117,7 @@ public class AssortHelper(
/// <returns>Trader assorts minus locked loyalty assorts</returns>
public TraderAssort StripLockedLoyaltyAssort(
PmcData pmcProfile,
string traderId,
MongoId traderId,
TraderAssort assort
)
{
@@ -125,8 +126,8 @@ public class AssortHelper(
// Trader assort does not always contain loyal_level_items
if (assort.LoyalLevelItems is null)
{
_logger.Warning(
_serverLocalisationService.GetText("assort-missing_loyalty_level_object", traderId)
logger.Warning(
serverLocalisationService.GetText("assort-missing_loyalty_level_object", traderId)
);
return strippedAssort;
@@ -12,16 +12,16 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class BotDifficultyHelper(
ISptLogger<BotDifficultyHelper> _logger,
DatabaseService _databaseService,
RandomUtil _randomUtil,
ServerLocalisationService _serverLocalisationService,
BotHelper _botHelper,
ConfigServer _configServer,
ICloner _cloner
ISptLogger<BotDifficultyHelper> logger,
DatabaseService databaseService,
RandomUtil randomUtil,
ServerLocalisationService serverLocalisationService,
BotHelper botHelper,
ConfigServer configServer,
ICloner cloner
)
{
protected readonly PmcConfig _pmcConfig = _configServer.GetConfig<PmcConfig>();
protected readonly PmcConfig _pmcConfig = configServer.GetConfig<PmcConfig>();
/// <summary>
/// Get difficulty settings for desired bot type, if not found use assault bot types
@@ -36,39 +36,36 @@ public class BotDifficultyHelper(
Bots botDb
)
{
var desiredType = _botHelper.IsBotPmc(type)
? _botHelper.GetPmcSideByRole(type).ToLowerInvariant()
var desiredType = botHelper.IsBotPmc(type)
? botHelper.GetPmcSideByRole(type).ToLowerInvariant()
: type.ToLowerInvariant();
if (!botDb.Types.ContainsKey(desiredType))
{
// No bot found, get fallback difficulty values
_logger.Warning(
_serverLocalisationService.GetText(
"bot-unable_to_get_bot_fallback_to_assault",
type
)
logger.Warning(
serverLocalisationService.GetText("bot-unable_to_get_bot_fallback_to_assault", type)
);
botDb.Types[desiredType] = _cloner.Clone(botDb.Types["assault"]);
botDb.Types[desiredType] = cloner.Clone(botDb.Types["assault"]);
}
// Get settings from raw bot json template file
var botTemplate = _botHelper.GetBotTemplate(desiredType);
var botTemplate = botHelper.GetBotTemplate(desiredType);
botTemplate.BotDifficulty.TryGetValue(desiredDifficulty, out var difficultySettings);
if (difficultySettings is null)
{
// No bot settings found, use 'assault' bot difficulty instead
_logger.Warning(
_serverLocalisationService.GetText(
logger.Warning(
serverLocalisationService.GetText(
"bot-unable_to_get_bot_difficulty_fallback_to_assault",
new { botType = desiredType, difficulty = desiredDifficulty }
)
);
botDb.Types[desiredType].BotDifficulty[desiredDifficulty] = _cloner.Clone(
botDb.Types[desiredType].BotDifficulty[desiredDifficulty] = cloner.Clone(
botDb.Types["assault"].BotDifficulty[desiredDifficulty]
);
}
return _cloner.Clone(difficultySettings);
return cloner.Clone(difficultySettings);
}
/// <summary>
@@ -89,9 +86,7 @@ public class BotDifficultyHelper(
difficultySetting = ConvertBotDifficultyDropdownToBotDifficulty(difficultySetting);
return _cloner.Clone(
_databaseService.GetBots().Types[type].BotDifficulty[difficultySetting]
);
return cloner.Clone(databaseService.GetBots().Types[type].BotDifficulty[difficultySetting]);
}
/// <summary>
@@ -118,6 +113,6 @@ public class BotDifficultyHelper(
/// <returns>random difficulty</returns>
public string ChooseRandomDifficulty()
{
return _randomUtil.GetArrayValue(["easy", "normal", "hard", "impossible"]);
return randomUtil.GetArrayValue(["easy", "normal", "hard", "impossible"]);
}
}
@@ -17,14 +17,14 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class BotGeneratorHelper(
ISptLogger<BotGeneratorHelper> _logger,
RandomUtil _randomUtil,
DurabilityLimitsHelper _durabilityLimitsHelper,
ItemHelper _itemHelper,
InventoryHelper _inventoryHelper,
ProfileActivityService _profileActivityService,
ServerLocalisationService _serverLocalisationService,
ConfigServer _configServer
ISptLogger<BotGeneratorHelper> logger,
RandomUtil randomUtil,
DurabilityLimitsHelper durabilityLimitsHelper,
ItemHelper itemHelper,
InventoryHelper inventoryHelper,
ProfileActivityService profileActivityService,
ServerLocalisationService serverLocalisationService,
ConfigServer configServer
)
{
// Equipment slot ids that do not conflict with other slots
@@ -43,7 +43,7 @@ public class BotGeneratorHelper(
Sides.PmcUsec.ToLowerInvariant(),
];
private readonly BotConfig _botConfig = _configServer.GetConfig<BotConfig>();
private readonly BotConfig _botConfig = configServer.GetConfig<BotConfig>();
/// <summary>
/// Adds properties to an item
@@ -55,7 +55,7 @@ public class BotGeneratorHelper(
public Upd GenerateExtraPropertiesForItem(TemplateItem? itemTemplate, string? botRole = null)
{
// Get raid settings, if no raid, default to day
var raidSettings = _profileActivityService
var raidSettings = profileActivityService
.GetFirstProfileActivityRaidData()
?.RaidConfiguration;
@@ -114,7 +114,7 @@ public class BotGeneratorHelper(
? new UpdFireMode { FireMode = "fullauto" }
: new UpdFireMode
{
FireMode = _randomUtil.GetArrayValue(itemTemplate.Properties.WeapFireType),
FireMode = randomUtil.GetArrayValue(itemTemplate.Properties.WeapFireType),
};
hasProperties = true;
}
@@ -163,7 +163,7 @@ public class BotGeneratorHelper(
);
itemProperties.Light = new UpdLight
{
IsActive = _randomUtil.GetChance100(lightLaserActiveChance),
IsActive = randomUtil.GetChance100(lightLaserActiveChance),
SelectedMode = 0,
};
hasProperties = true;
@@ -178,7 +178,7 @@ public class BotGeneratorHelper(
);
itemProperties.Light = new UpdLight
{
IsActive = _randomUtil.GetChance100(lightLaserActiveChance),
IsActive = randomUtil.GetChance100(lightLaserActiveChance),
SelectedMode = 0,
};
hasProperties = true;
@@ -193,7 +193,7 @@ public class BotGeneratorHelper(
: GetBotEquipmentSettingFromConfig(botRole, "nvgIsActiveChanceDayPercent", 15);
itemProperties.Togglable = new UpdTogglable
{
On = _randomUtil.GetChance100(nvgActiveChance),
On = randomUtil.GetChance100(nvgActiveChance),
};
hasProperties = true;
}
@@ -211,7 +211,7 @@ public class BotGeneratorHelper(
);
itemProperties.Togglable = new UpdTogglable
{
On = _randomUtil.GetChance100(faceShieldActiveChance),
On = randomUtil.GetChance100(faceShieldActiveChance),
};
hasProperties = true;
}
@@ -236,13 +236,13 @@ public class BotGeneratorHelper(
return maxResource;
}
if (_randomUtil.GetChance100(randomizationValues.ChanceMaxResourcePercent))
if (randomUtil.GetChance100(randomizationValues.ChanceMaxResourcePercent))
{
return maxResource;
}
return _randomUtil.GetDouble(
_randomUtil.GetPercentOfValue(randomizationValues.ResourcePercent, maxResource, 0),
return randomUtil.GetDouble(
randomUtil.GetPercentOfValue(randomizationValues.ResourcePercent, maxResource, 0),
maxResource
);
}
@@ -268,8 +268,8 @@ public class BotGeneratorHelper(
var botEquipmentSettings = _botConfig.Equipment[GetBotEquipmentRole(botRole)];
if (botEquipmentSettings is null)
{
_logger.Warning(
_serverLocalisationService.GetText(
logger.Warning(
serverLocalisationService.GetText(
"bot-missing_equipment_settings",
new
{
@@ -296,8 +296,8 @@ public class BotGeneratorHelper(
return propValue;
}
_logger.Warning(
_serverLocalisationService.GetText(
logger.Warning(
serverLocalisationService.GetText(
"bot-missing_equipment_settings_property",
new
{
@@ -322,11 +322,11 @@ public class BotGeneratorHelper(
string? botRole = null
)
{
var maxDurability = _durabilityLimitsHelper.GetRandomizedMaxWeaponDurability(
var maxDurability = durabilityLimitsHelper.GetRandomizedMaxWeaponDurability(
itemTemplate,
botRole
);
var currentDurability = _durabilityLimitsHelper.GetRandomizedWeaponDurability(
var currentDurability = durabilityLimitsHelper.GetRandomizedWeaponDurability(
itemTemplate,
botRole,
maxDurability
@@ -359,11 +359,11 @@ public class BotGeneratorHelper(
}
else
{
maxDurability = _durabilityLimitsHelper.GetRandomizedMaxArmorDurability(
maxDurability = durabilityLimitsHelper.GetRandomizedMaxArmorDurability(
itemTemplate,
botRole
);
currentDurability = _durabilityLimitsHelper.GetRandomizedArmorDurability(
currentDurability = durabilityLimitsHelper.GetRandomizedArmorDurability(
itemTemplate,
botRole,
maxDurability
@@ -403,14 +403,14 @@ public class BotGeneratorHelper(
// TODO: Can probably be optimized to cache itemTemplates as items are added to inventory
var equippedItemsDb = itemsEquipped
.Select(equippedItem => _itemHelper.GetItem(equippedItem.Template).Value)
.Select(equippedItem => itemHelper.GetItem(equippedItem.Template).Value)
.ToList();
var (itemIsValid, itemToEquip) = _itemHelper.GetItem(tplToCheck);
var (itemIsValid, itemToEquip) = itemHelper.GetItem(tplToCheck);
if (!itemIsValid)
{
_logger.Warning(
_serverLocalisationService.GetText(
logger.Warning(
serverLocalisationService.GetText(
"bot-invalid_item_compatibility_check",
new { itemTpl = tplToCheck, slot = equipmentSlot }
)
@@ -426,8 +426,8 @@ public class BotGeneratorHelper(
if (itemToEquip?.Properties is null)
{
_logger.Warning(
_serverLocalisationService.GetText(
logger.Warning(
serverLocalisationService.GetText(
"bot-compatibility_check_missing_props",
new
{
@@ -633,9 +633,9 @@ public class BotGeneratorHelper(
if (missingContainerCount == equipmentSlots.Count)
{
// Bot doesn't have any containers we want to add item to
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
logger.Debug(
$"Unable to add item: {itemWithChildren.FirstOrDefault()?.Template} to bot as it lacks the following containers: {string.Join(",", equipmentSlots)}"
);
}
@@ -648,11 +648,11 @@ public class BotGeneratorHelper(
}
// Get container details from db
var (key, value) = _itemHelper.GetItem(container.Template);
var (key, value) = itemHelper.GetItem(container.Template);
if (!key)
{
_logger.Warning(
_serverLocalisationService.GetText(
logger.Warning(
serverLocalisationService.GetText(
"bot-missing_container_with_tpl",
container.Template
)
@@ -669,7 +669,7 @@ public class BotGeneratorHelper(
}
// Get x/y grid size of item
var (itemWidth, itemHeight) = _inventoryHelper.GetItemSize(
var (itemWidth, itemHeight) = inventoryHelper.GetItemSize(
rootItemTplId,
rootItemId,
itemWithChildren
@@ -714,7 +714,7 @@ public class BotGeneratorHelper(
if (slotGrid.Props is not null)
{
// Get rid of an items free/used spots in current grid
var slotGridMap = _inventoryHelper.GetContainerMap(
var slotGridMap = inventoryHelper.GetContainerMap(
slotGrid.Props.CellsH.GetValueOrDefault(),
slotGrid.Props.CellsV.GetValueOrDefault(),
containerItemsWithChildren,
@@ -830,7 +830,7 @@ public class BotGeneratorHelper(
}
// Check if item base type is excluded
var itemDetails = _itemHelper.GetItem(itemTpl).Value;
var itemDetails = itemHelper.GetItem(itemTpl).Value;
// if item to add is found in exclude filter, not allowed
if (excludedFilter.Contains(itemDetails?.Parent ?? string.Empty))
@@ -14,10 +14,10 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class BotHelper(
ISptLogger<BotHelper> _logger,
DatabaseService _databaseService,
RandomUtil _randomUtil,
ConfigServer _configServer
ISptLogger<BotHelper> logger,
DatabaseService databaseService,
RandomUtil randomUtil,
ConfigServer configServer
)
{
private static readonly FrozenSet<string> _pmcTypeIds =
@@ -28,8 +28,8 @@ public class BotHelper(
Sides.PmcUsec.ToLowerInvariant(),
];
private readonly BotConfig _botConfig = _configServer.GetConfig<BotConfig>();
private readonly PmcConfig _pmcConfig = _configServer.GetConfig<PmcConfig>();
private readonly BotConfig _botConfig = configServer.GetConfig<BotConfig>();
private readonly PmcConfig _pmcConfig = configServer.GetConfig<PmcConfig>();
private readonly ConcurrentDictionary<string, List<string>> _pmcNameCache = new();
/// <summary>
@@ -39,9 +39,9 @@ public class BotHelper(
/// <returns>BotType object</returns>
public BotType? GetBotTemplate(string role)
{
if (!_databaseService.GetBots().Types.TryGetValue(role?.ToLowerInvariant(), out var bot))
if (!databaseService.GetBots().Types.TryGetValue(role?.ToLowerInvariant(), out var bot))
{
_logger.Error($"Unable to get bot of type: {role} from DB");
logger.Error($"Unable to get bot of type: {role} from DB");
return null;
}
@@ -203,7 +203,7 @@ public class BotHelper(
/// <returns>pmc side as string</returns>
protected string GetRandomizedPmcSide()
{
return _randomUtil.GetChance100(_pmcConfig.IsUsec) ? Sides.Usec : Sides.Bear;
return randomUtil.GetChance100(_pmcConfig.IsUsec) ? Sides.Usec : Sides.Bear;
}
/// <summary>
@@ -215,20 +215,20 @@ public class BotHelper(
public string GetPmcNicknameOfMaxLength(int maxLength, string? side = null)
{
var chosenFaction = (
side ?? (_randomUtil.GetInt(0, 1) == 0 ? Sides.Usec : Sides.Bear)
side ?? (randomUtil.GetInt(0, 1) == 0 ? Sides.Usec : Sides.Bear)
).ToLowerInvariant();
var cacheKey = $"{chosenFaction}{maxLength}";
if (!_pmcNameCache.TryGetValue(cacheKey, out var eligibleNames))
{
if (
!_databaseService
!databaseService
.GetBots()
.Types.TryGetValue(chosenFaction, out var chosenFactionDetails)
)
{
_logger.Error($"Unknown faction: {chosenFaction} Defaulting to: {Sides.Usec}");
logger.Error($"Unknown faction: {chosenFaction} Defaulting to: {Sides.Usec}");
chosenFaction = Sides.Usec.ToLowerInvariant();
chosenFactionDetails = _databaseService.GetBots().Types[chosenFaction];
chosenFactionDetails = databaseService.GetBots().Types[chosenFaction];
}
var matchingNames = chosenFactionDetails
@@ -236,12 +236,12 @@ public class BotHelper(
.ToList();
if (!matchingNames.Any())
{
_logger.Warning(
logger.Warning(
$"Unable to filter: {chosenFaction} PMC names to only those under: {maxLength}, none found that match that criteria, selecting from entire name pool instead"
);
// Return a random string from names
return _randomUtil.GetCollectionValue(chosenFactionDetails.FirstNames);
return randomUtil.GetCollectionValue(chosenFactionDetails.FirstNames);
}
_pmcNameCache.TryAdd(cacheKey, matchingNames);
@@ -249,6 +249,6 @@ public class BotHelper(
eligibleNames = matchingNames;
}
return _randomUtil.GetCollectionValue(eligibleNames);
return randomUtil.GetCollectionValue(eligibleNames);
}
}
@@ -9,10 +9,10 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class BotWeaponGeneratorHelper(
ISptLogger<BotWeaponGeneratorHelper> _logger,
ItemHelper _itemHelper,
WeightedRandomHelper _weightedRandomHelper,
BotGeneratorHelper _botGeneratorHelper
ISptLogger<BotWeaponGeneratorHelper> logger,
ItemHelper itemHelper,
WeightedRandomHelper weightedRandomHelper,
BotGeneratorHelper botGeneratorHelper
)
{
private static readonly FrozenSet<string> _magCheck =
@@ -30,7 +30,7 @@ public class BotWeaponGeneratorHelper(
public double? GetRandomizedBulletCount(GenerationData magCounts, TemplateItem magTemplate)
{
var randomizedMagazineCount = GetRandomizedMagazineCount(magCounts);
var parentItem = _itemHelper.GetItem(magTemplate.Parent).Value;
var parentItem = itemHelper.GetItem(magTemplate.Parent).Value;
double? chamberBulletCount = 0;
if (MagazineIsCylinderRelated(parentItem.Name))
{
@@ -40,7 +40,7 @@ public class BotWeaponGeneratorHelper(
?.Props.Filters[0]
.Filter.FirstOrDefault() ?? new MongoId(null);
var ammoMaxStackSize =
_itemHelper.GetItem(firstSlotAmmoTpl).Value?.Properties?.StackMaxSize ?? 1;
itemHelper.GetItem(firstSlotAmmoTpl).Value?.Properties?.StackMaxSize ?? 1;
chamberBulletCount =
ammoMaxStackSize == 1
? 1 // Rotating grenade launcher
@@ -68,7 +68,7 @@ public class BotWeaponGeneratorHelper(
/// <returns>Numerical value of magazine count</returns>
public int GetRandomizedMagazineCount(GenerationData magCounts)
{
return (int)_weightedRandomHelper.GetWeightedValue(magCounts.Weights);
return (int)weightedRandomHelper.GetWeightedValue(magCounts.Weights);
}
/// <summary>
@@ -89,14 +89,14 @@ public class BotWeaponGeneratorHelper(
/// <param name="magTemplate">Template object of magazine</param>
/// <returns>Item array</returns>
public List<Item> CreateMagazineWithAmmo(
string magazineTpl,
string ammoTpl,
MongoId magazineTpl,
MongoId ammoTpl,
TemplateItem magTemplate
)
{
List<Item> magazine = [new() { Id = new MongoId(), Template = magazineTpl }];
_itemHelper.FillMagazineWithCartridge(magazine, magTemplate, ammoTpl, 1);
itemHelper.FillMagazineWithCartridge(magazine, magTemplate, ammoTpl, 1);
return magazine;
}
@@ -109,7 +109,7 @@ public class BotWeaponGeneratorHelper(
/// <param name="inventory">Bot inventory to add cartridges to</param>
/// <param name="equipmentSlotsToAddTo">What equipment slots should bullets be added into</param>
public void AddAmmoIntoEquipmentSlots(
string ammoTpl,
MongoId ammoTpl,
int cartridgeCount,
BotBaseInventory inventory,
HashSet<EquipmentSlots>? equipmentSlotsToAddTo = null
@@ -120,7 +120,7 @@ public class BotWeaponGeneratorHelper(
equipmentSlotsToAddTo = [EquipmentSlots.TacticalVest, EquipmentSlots.Pockets];
}
var ammoItems = _itemHelper.SplitStack(
var ammoItems = itemHelper.SplitStack(
new Item
{
Id = new MongoId(),
@@ -131,7 +131,7 @@ public class BotWeaponGeneratorHelper(
foreach (var ammoItem in ammoItems)
{
var result = _botGeneratorHelper.AddItemWithChildrenToEquipmentSlot(
var result = botGeneratorHelper.AddItemWithChildrenToEquipmentSlot(
equipmentSlotsToAddTo,
ammoItem.Id,
ammoItem.Template,
@@ -141,7 +141,7 @@ public class BotWeaponGeneratorHelper(
if (result != ItemAddedResult.SUCCESS)
{
_logger.Debug(
logger.Debug(
$"Unable to add ammo: {ammoItem.Template} to bot inventory, {result.ToString()}"
);
@@ -8,7 +8,7 @@ using SPTarkov.Server.Core.Utils;
namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class CertificateHelper(ISptLogger<CertificateHelper> _logger, FileUtil _fileUtil)
public class CertificateHelper(ISptLogger<CertificateHelper> logger, FileUtil fileUtil)
{
private const string certificatePath = "./user/certs/server.crt";
private const string certificateKeyPath = "./user/certs/server.key";
@@ -41,7 +41,7 @@ public class CertificateHelper(ISptLogger<CertificateHelper> _logger, FileUtil _
throw new Exception("Certificate could not be loaded for the second time.");
}
_logger.Success($"Generated and stored self-signed certificate ({certificatePath})");
logger.Success($"Generated and stored self-signed certificate ({certificatePath})");
}
return certificate;
@@ -57,12 +57,12 @@ public class CertificateHelper(ISptLogger<CertificateHelper> _logger, FileUtil _
if (TryLoadCertificatePfx(out var cert))
{
_logger.Success($"Loaded self-signed certificate ({certificatePath})");
logger.Success($"Loaded self-signed certificate ({certificatePath})");
return cert;
}
// shit went wrong, throw a wobbly and close app
_logger.Critical("Certificate pfx could not be loaded. Stopping server...");
logger.Critical("Certificate pfx could not be loaded. Stopping server...");
Environment.Exit(1);
return null;
}
@@ -91,7 +91,7 @@ public class CertificateHelper(ISptLogger<CertificateHelper> _logger, FileUtil _
// file doesnt exist so create straight away
cert = GenerateSelfSignedCertificate("localhost");
SaveCertificatePfx(cert);
_logger.Success($"Generated and stored self-signed certificate ({certificatePath})");
logger.Success($"Generated and stored self-signed certificate ({certificatePath})");
}
try
@@ -182,11 +182,11 @@ public class CertificateHelper(ISptLogger<CertificateHelper> _logger, FileUtil _
Base64FormattingOptions.InsertLineBreaks
)
+ "\n-----END CERTIFICATE-----";
_fileUtil.WriteFile(certificatePath, certPem);
fileUtil.WriteFile(certificatePath, certPem);
}
catch (Exception ex)
{
_logger.Error($"Error saving certificate: {ex.Message}");
logger.Error($"Error saving certificate: {ex.Message}");
}
}
@@ -198,11 +198,11 @@ public class CertificateHelper(ISptLogger<CertificateHelper> _logger, FileUtil _
{
try
{
_fileUtil.WriteFile(certificatePfxPath, certificate.Export(X509ContentType.Pfx));
fileUtil.WriteFile(certificatePfxPath, certificate.Export(X509ContentType.Pfx));
}
catch (Exception ex)
{
_logger.Error($"Error saving certificate: {ex.Message}");
logger.Error($"Error saving certificate: {ex.Message}");
}
}
@@ -218,11 +218,11 @@ public class CertificateHelper(ISptLogger<CertificateHelper> _logger, FileUtil _
+ Convert.ToBase64String(privateKeyBytes, Base64FormattingOptions.InsertLineBreaks)
+ "\n-----END PRIVATE KEY-----";
_fileUtil.WriteFile(certificateKeyPath, privateKeyString);
fileUtil.WriteFile(certificateKeyPath, privateKeyString);
}
catch (Exception ex)
{
_logger.Error($"Error saving certificate key: {ex.Message}");
logger.Error($"Error saving certificate key: {ex.Message}");
}
}
}
@@ -1,47 +1,46 @@
using SPTarkov.DI.Annotations;
using SPTarkov.Server.Core.Models.Common;
namespace SPTarkov.Server.Core.Helpers
namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class CounterTrackerHelper
{
[Injectable]
public class CounterTrackerHelper
private Dictionary<MongoId, int> _maxCounts = new();
private readonly Dictionary<MongoId, int> _trackedCounts = new();
/// <summary>
/// Add dictionary of keys and their matching limits to track
/// </summary>
/// <param name="maxCounts">Values to store</param>
public void AddDataToTrack(Dictionary<MongoId, int> maxCounts)
{
private Dictionary<MongoId, int> _maxCounts = new();
private readonly Dictionary<MongoId, int> _trackedCounts = new();
_maxCounts = maxCounts;
}
/// <summary>
/// Add dictionary of keys and their matching limits to track
/// </summary>
/// <param name="maxCounts">Values to store</param>
public void AddDataToTrack(Dictionary<MongoId, int> maxCounts)
/// <summary>
/// Increment the counter for passed in key, get back value determining if max value passed
/// </summary>
/// <param name="key"></param>
/// <param name="countToIncrementBy"></param>
/// <returns>True = above max count</returns>
public bool IncrementCount(MongoId key, int countToIncrementBy = 1)
{
// Not tracked, skip
if (!_maxCounts.Any() || !_maxCounts.ContainsKey(key))
{
_maxCounts = maxCounts;
return false;
}
/// <summary>
/// Increment the counter for passed in key, get back value determining if max value passed
/// </summary>
/// <param name="key"></param>
/// <param name="countToIncrementBy"></param>
/// <returns>True = above max count</returns>
public bool IncrementCount(MongoId key, int countToIncrementBy = 1)
{
// Not tracked, skip
if (!_maxCounts.Any() || !_maxCounts.ContainsKey(key))
{
return false;
}
_trackedCounts.TryAdd(key, 0);
_trackedCounts[key] += countToIncrementBy;
_trackedCounts.TryAdd(key, 0);
_trackedCounts[key] += countToIncrementBy;
return _trackedCounts[key] > _maxCounts[key];
}
return _trackedCounts[key] > _maxCounts[key];
}
public void Clear()
{
_trackedCounts.Clear();
_maxCounts.Clear();
}
public void Clear()
{
_trackedCounts.Clear();
_maxCounts.Clear();
}
}
@@ -47,7 +47,7 @@ public class DialogueHelper(ISptLogger<DialogueHelper> logger, ProfileHelper pro
/// <param name="sessionID">Session/player id</param>
/// <param name="itemId">Item being moved to inventory</param>
/// <returns>Collection of items from message</returns>
public List<Item> GetMessageItemContents(string messageID, string sessionID, MongoId itemId)
public List<Item> GetMessageItemContents(string messageID, MongoId sessionID, MongoId itemId)
{
var fullProfile = profileHelper.GetFullProfile(sessionID);
var dialogueData = fullProfile.DialogueRecords;
@@ -95,7 +95,7 @@ public class DialogueHelper(ISptLogger<DialogueHelper> logger, ProfileHelper pro
/// </summary>
/// <param name="sessionId">Session/player id</param>
/// <returns>Dialog dictionary</returns>
public Dictionary<string, Models.Eft.Profile.Dialogue> GetDialogsForProfile(string sessionId)
public Dictionary<string, Models.Eft.Profile.Dialogue> GetDialogsForProfile(MongoId sessionId)
{
var profile = profileHelper.GetFullProfile(sessionId);
return profile.DialogueRecords
@@ -108,7 +108,7 @@ public class DialogueHelper(ISptLogger<DialogueHelper> logger, ProfileHelper pro
/// <param name="profileId">Profile to look in</param>
/// <param name="dialogueId">Dialog to return</param>
/// <returns>Dialogue</returns>
public Models.Eft.Profile.Dialogue? GetDialogueFromProfile(string profileId, string dialogueId)
public Models.Eft.Profile.Dialogue? GetDialogueFromProfile(MongoId profileId, string dialogueId)
{
var dialogues = GetDialogsForProfile(profileId);
if (dialogues.TryGetValue(dialogueId, out var dialogue))
@@ -11,9 +11,9 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable(InjectionType.Singleton)]
public class HandbookHelper(
DatabaseService _databaseService,
ConfigServer _configServer,
ICloner _cloner
DatabaseService databaseService,
ConfigServer configServer,
ICloner cloner
)
{
private LookupCollection? _handbookPriceCache;
@@ -22,7 +22,7 @@ public class HandbookHelper(
get { return _handbookPriceCache ??= HydrateHandbookCache(); }
}
protected readonly ItemConfig _itemConfig = _configServer.GetConfig<ItemConfig>();
protected readonly ItemConfig _itemConfig = configServer.GetConfig<ItemConfig>();
/// <summary>
/// Create an in-memory cache of all items with associated handbook price in handbookPriceCache class
@@ -30,7 +30,7 @@ public class HandbookHelper(
protected LookupCollection HydrateHandbookCache()
{
var result = new LookupCollection();
var handbook = _databaseService.GetHandbook();
var handbook = databaseService.GetHandbook();
// Add handbook overrides found in items.json config into db
foreach (var (key, priceOverride) in _itemConfig.HandbookPriceOverride)
{
@@ -52,7 +52,7 @@ public class HandbookHelper(
itemToUpdate.ParentId = priceOverride.ParentId;
}
var handbookDbClone = _cloner.Clone(handbook);
var handbookDbClone = cloner.Clone(handbook);
foreach (var handbookItem in handbookDbClone.Items)
{
result.Items.ById.TryAdd(handbookItem.Id, handbookItem.Price ?? 0);
@@ -70,12 +70,16 @@ public class HandbookHelper(
result.Categories.ById.TryAdd(handbookCategory.Id, handbookCategory.ParentId);
if (handbookCategory.ParentId is not null)
{
if (!result.Categories.ByParent.TryGetValue(handbookCategory.ParentId, out _))
if (!result.Categories.ByParent.TryGetValue(handbookCategory.ParentId.Value, out _))
{
result.Categories.ByParent.TryAdd(handbookCategory.ParentId, []);
result.Categories.ByParent.TryAdd(handbookCategory.ParentId.Value, []);
}
result.Categories.ByParent.TryGetValue(handbookCategory.ParentId, out var itemIds);
result.Categories.ByParent.TryGetValue(
handbookCategory.ParentId.Value,
out var itemIds
);
itemIds.Add(handbookCategory.Id);
}
}
@@ -96,7 +100,7 @@ public class HandbookHelper(
return itemPrice;
}
var handbookItem = _databaseService
var handbookItem = databaseService
.GetHandbook()
.Items?.FirstOrDefault(item => item.Id == tpl);
if (handbookItem is null)
@@ -142,7 +146,7 @@ public class HandbookHelper(
/// </summary>
/// <param name="parentId"></param>
/// <returns>string array</returns>
public List<string> TemplatesWithParent(string parentId)
public List<MongoId> TemplatesWithParent(MongoId parentId)
{
HandbookPriceCache.Items.ByParent.TryGetValue(parentId, out var template);
@@ -154,7 +158,7 @@ public class HandbookHelper(
/// </summary>
/// <param name="category"></param>
/// <returns>true if exists in cache</returns>
public bool IsCategory(string category)
public bool IsCategory(MongoId category)
{
return HandbookPriceCache.Categories.ById.TryGetValue(category, out _);
}
@@ -176,7 +180,7 @@ public class HandbookHelper(
/// <param name="nonRoubleCurrencyCount">Currency count to convert</param>
/// <param name="currencyTypeFrom">What current currency is</param>
/// <returns>Count in roubles</returns>
public double InRUB(double nonRoubleCurrencyCount, string currencyTypeFrom)
public double InRUB(double nonRoubleCurrencyCount, MongoId currencyTypeFrom)
{
return currencyTypeFrom == Money.ROUBLES
? nonRoubleCurrencyCount
@@ -189,7 +193,7 @@ public class HandbookHelper(
/// <param name="roubleCurrencyCount">roubles to convert</param>
/// <param name="currencyTypeTo">Currency to convert roubles into</param>
/// <returns>currency count in desired type</returns>
public double FromRUB(double roubleCurrencyCount, string currencyTypeTo)
public double FromRUB(double roubleCurrencyCount, MongoId currencyTypeTo)
{
if (currencyTypeTo == Money.ROUBLES)
{
@@ -201,9 +205,9 @@ public class HandbookHelper(
return price > 0 ? Math.Max(1, Math.Round(roubleCurrencyCount / price)) : 0;
}
public HandbookCategory GetCategoryById(string handbookId)
public HandbookCategory GetCategoryById(MongoId handbookId)
{
return _databaseService
return databaseService
.GetHandbook()
.Categories.FirstOrDefault(category => category.Id == handbookId);
}
@@ -213,23 +217,23 @@ public class HandbookHelper(
public LookupItem()
{
ById = new Dictionary<MongoId, T>();
ByParent = new Dictionary<string, List<I>>();
ByParent = new Dictionary<MongoId, List<I>>();
}
public Dictionary<MongoId, T> ById { get; set; }
public Dictionary<string, List<I>> ByParent { get; set; }
public Dictionary<MongoId, List<I>> ByParent { get; set; }
}
protected record LookupCollection
{
public LookupCollection()
{
Items = new LookupItem<double, string>();
Items = new LookupItem<double, MongoId>();
Categories = new LookupItem<string, string>();
}
public LookupItem<double, string> Items { get; set; }
public LookupItem<double, MongoId> Items { get; set; }
public LookupItem<string, string> Categories { get; set; }
}
@@ -1,4 +1,5 @@
using SPTarkov.DI.Annotations;
using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Eft.Common;
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
using SPTarkov.Server.Core.Models.Spt.Config;
@@ -10,13 +11,13 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class HealthHelper(
TimeUtil _timeUtil,
SaveServer _saveServer,
ProfileHelper _profileHelper,
ConfigServer _configServer
TimeUtil timeUtil,
SaveServer saveServer,
ProfileHelper profileHelper,
ConfigServer configServer
)
{
protected readonly HealthConfig _healthConfig = _configServer.GetConfig<HealthConfig>();
protected readonly HealthConfig _healthConfig = configServer.GetConfig<HealthConfig>();
/// <summary>
/// Update player profile vitality values with changes from client request object
@@ -26,18 +27,18 @@ public class HealthHelper(
/// <param name="healthChanges">Changes to apply </param>
/// <param name="isDead">OPTIONAL - Is player dead</param>
public void ApplyHealthChangesToProfile(
string sessionID,
MongoId sessionID,
PmcData pmcProfileToUpdate,
BotBaseHealth healthChanges,
bool isDead = false
)
{
var fullProfile = _saveServer.GetProfile(sessionID);
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 matchingSide = profileHelper.GetProfileTemplateForSide(profileEdition, profileSide);
var defaultTemperature =
matchingSide?.Character?.Health?.Temperature ?? new CurrentMinMax { Current = 36.6 };
@@ -53,7 +54,7 @@ public class HealthHelper(
AdjustProfileHydrationEnergyTemperature(pmcProfileToUpdate, healthChanges);
// Update last edited timestamp
pmcProfileToUpdate.Health.UpdateTime = _timeUtil.GetTimeStamp();
pmcProfileToUpdate.Health.UpdateTime = timeUtil.GetTimeStamp();
}
/// <summary>
@@ -18,16 +18,16 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class HideoutHelper(
ISptLogger<HideoutHelper> _logger,
TimeUtil _timeUtil,
ServerLocalisationService _serverLocalisationService,
DatabaseService _databaseService,
EventOutputHolder _eventOutputHolder,
HttpResponseUtil _httpResponseUtil,
ProfileHelper _profileHelper,
InventoryHelper _inventoryHelper,
ItemHelper _itemHelper,
ICloner _cloner
ISptLogger<HideoutHelper> logger,
TimeUtil timeUtil,
ServerLocalisationService serverLocalisationService,
DatabaseService databaseService,
EventOutputHolder eventOutputHolder,
HttpResponseUtil httpResponseUtil,
ProfileHelper profileHelper,
InventoryHelper inventoryHelper,
ItemHelper itemHelper,
ICloner cloner
)
{
public static readonly MongoId BitcoinProductionId = new("5d5c205bd582a50d042a3c0e");
@@ -44,24 +44,24 @@ public class HideoutHelper(
public void RegisterProduction(
PmcData pmcData,
HideoutSingleProductionStartRequestData productionRequest,
string sessionID
MongoId sessionID
)
{
var recipe = _databaseService
var recipe = databaseService
.GetHideout()
.Production.Recipes.FirstOrDefault(production =>
production.Id == productionRequest.RecipeId
);
if (recipe is null)
{
_logger.Error(
_serverLocalisationService.GetText(
logger.Error(
serverLocalisationService.GetText(
"hideout-missing_recipe_in_db",
productionRequest.RecipeId
)
);
_httpResponseUtil.AppendErrorToOutput(_eventOutputHolder.GetOutput(sessionID));
httpResponseUtil.AppendErrorToOutput(eventOutputHolder.GetOutput(sessionID));
}
// @Important: Here we need to be very exact:
@@ -90,12 +90,12 @@ public class HideoutHelper(
foreach (var tool in productionRequest.Tools)
{
var toolItem = _cloner.Clone(
var toolItem = cloner.Clone(
pmcData.Inventory.Items.FirstOrDefault(x => x.Id == tool.Id)
);
// Make sure we only return as many as we took
_itemHelper.AddUpdObjectToItem(toolItem);
itemHelper.AddUpdObjectToItem(toolItem);
toolItem.Upd.StackObjectsCount = tool.Count;
@@ -123,24 +123,24 @@ public class HideoutHelper(
public void RegisterProduction(
PmcData pmcData,
HideoutContinuousProductionStartRequestData productionRequest,
string sessionID
MongoId sessionID
)
{
var recipe = _databaseService
var recipe = databaseService
.GetHideout()
.Production.Recipes.FirstOrDefault(production =>
production.Id == productionRequest.RecipeId
);
if (recipe is null)
{
_logger.Error(
_serverLocalisationService.GetText(
logger.Error(
serverLocalisationService.GetText(
"hideout-missing_recipe_in_db",
productionRequest.RecipeId
)
);
_httpResponseUtil.AppendErrorToOutput(_eventOutputHolder.GetOutput(sessionID));
httpResponseUtil.AppendErrorToOutput(eventOutputHolder.GetOutput(sessionID));
}
// @Important: Here we need to be very exact:
@@ -153,11 +153,11 @@ public class HideoutHelper(
var modifiedProductionTime = GetAdjustedCraftTimeWithSkills(
pmcData,
productionRequest.RecipeId
productionRequest.RecipeId.Value
);
var production = InitProduction(
productionRequest.RecipeId,
productionRequest.RecipeId.Value,
modifiedProductionTime ?? 0,
recipe.NeedFuelForAllProductionTime
);
@@ -170,7 +170,7 @@ public class HideoutHelper(
/// with all the constants.
/// </summary>
public Production InitProduction(
string recipeId,
MongoId recipeId,
double productionTime,
bool? needFuelForAllProductionTime
)
@@ -180,7 +180,7 @@ public class HideoutHelper(
Progress = 0,
InProgress = true,
RecipeId = recipeId,
StartTimestamp = _timeUtil.GetTimeStamp(),
StartTimestamp = timeUtil.GetTimeStamp(),
ProductionTime = productionTime,
Products = [],
GivenItemsInStart = [],
@@ -209,8 +209,8 @@ public class HideoutHelper(
);
if (stashItem is null)
{
_logger.Warning(
_serverLocalisationService.GetText(
logger.Warning(
serverLocalisationService.GetText(
"hideout-unable_to_apply_stashsize_bonus_no_stash_found",
profileData.Inventory.Stash
)
@@ -235,9 +235,9 @@ public class HideoutHelper(
// Add bonus to player bonuses array in profile
// EnergyRegeneration, HealthRegeneration, RagfairCommission, ScavCooldownTimer, SkillGroupLevelingBoost, ExperienceRate, QuestMoneyReward etc
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"Adding bonus: {bonus.Type} to profile, value: {bonus.Value}");
logger.Debug($"Adding bonus: {bonus.Type} to profile, value: {bonus.Value}");
}
profileData.Bonuses.Add(bonus);
@@ -247,16 +247,16 @@ public class HideoutHelper(
/// Process a players hideout, update areas that use resources + increment production timers
/// </summary>
/// <param name="sessionID">Session id</param>
public void UpdatePlayerHideout(string sessionID)
public void UpdatePlayerHideout(MongoId sessionID)
{
var pmcData = _profileHelper.GetPmcProfile(sessionID);
var pmcData = profileHelper.GetPmcProfile(sessionID);
var hideoutProperties = GetHideoutProperties(pmcData);
pmcData.Hideout.SptUpdateLastRunTimestamp ??= _timeUtil.GetTimeStamp();
pmcData.Hideout.SptUpdateLastRunTimestamp ??= timeUtil.GetTimeStamp();
UpdateAreasWithResources(sessionID, pmcData, hideoutProperties);
UpdateProductionTimers(pmcData, hideoutProperties);
pmcData.Hideout.SptUpdateLastRunTimestamp = _timeUtil.GetTimeStamp();
pmcData.Hideout.SptUpdateLastRunTimestamp = timeUtil.GetTimeStamp();
}
/// <summary>
@@ -313,7 +313,7 @@ public class HideoutHelper(
/// <param name="hideoutProperties">Hideout properties</param>
protected void UpdateProductionTimers(PmcData pmcData, HideoutProperties hideoutProperties)
{
var recipes = _databaseService.GetHideout().Production;
var recipes = databaseService.GetHideout().Production;
// Check each production and handle edge cases if necessary
foreach (var prodId in pmcData.Hideout?.Production)
@@ -328,8 +328,8 @@ public class HideoutHelper(
if (craft.Progress == null)
{
_logger.Warning(
_serverLocalisationService.GetText(
logger.Warning(
serverLocalisationService.GetText(
"hideout-craft_has_undefined_progress_value_defaulting",
prodId
)
@@ -383,8 +383,8 @@ public class HideoutHelper(
var recipe = recipes?.Recipes?.FirstOrDefault(r => r.Id == prodId.Key);
if (recipe is null)
{
_logger.Error(
_serverLocalisationService.GetText("hideout-missing_recipe_for_area", prodId)
logger.Error(
serverLocalisationService.GetText("hideout-missing_recipe_for_area", prodId)
);
continue;
@@ -486,7 +486,7 @@ public class HideoutHelper(
// Get seconds since last hideout update
var timeElapsedSeconds =
_timeUtil.GetTimeStamp() - pmcData.Hideout.SptUpdateLastRunTimestamp;
timeUtil.GetTimeStamp() - pmcData.Hideout.SptUpdateLastRunTimestamp;
// Increment progress by time passed if progress is less than time needed
if (production.Progress < production.ProductionTime)
@@ -536,7 +536,7 @@ public class HideoutHelper(
protected void UpdateScavCaseProductionTimer(PmcData pmcData, string productionId)
{
var timeElapsed =
_timeUtil.GetTimeStamp()
timeUtil.GetTimeStamp()
- pmcData.Hideout.Production[productionId].StartTimestamp
- pmcData.Hideout.Production[productionId].Progress;
@@ -550,7 +550,7 @@ public class HideoutHelper(
/// <param name="pmcData">Profile to update areas of</param>
/// <param name="hideoutProperties">hideout properties</param>
protected void UpdateAreasWithResources(
string sessionID,
MongoId sessionID,
PmcData pmcData,
HideoutProperties hideoutProperties
)
@@ -592,7 +592,7 @@ public class HideoutHelper(
// 1 resource last 14 min 27 sec, 1/14.45/60 = 0.00115
// 10-10-2021 From wiki, 1 resource last 12 minutes 38 seconds, 1/12.63333/60 = 0.00131
var fuelUsedSinceLastTick =
_databaseService.GetHideout().Settings.GeneratorFuelFlowRate
databaseService.GetHideout().Settings.GeneratorFuelFlowRate
* GetTimeElapsedSinceLastServerTick(pmcData, isGeneratorOn);
// Get all fuel consumption bonuses, returns an empty array if none found
@@ -645,7 +645,7 @@ public class HideoutHelper(
// Undefined fuel, fresh fuel item and needs its max fuel amount looked up
if (fuelRemaining is null)
{
var fuelItemTemplate = _itemHelper.GetItem(fuelItemInSlot.Template).Value;
var fuelItemTemplate = itemHelper.GetItem(fuelItemInSlot.Template).Value;
pointsConsumed = fuelUsedSinceLastTick ?? 0;
fuelRemaining = fuelItemTemplate.Properties.MaxResource - fuelUsedSinceLastTick;
}
@@ -665,7 +665,7 @@ public class HideoutHelper(
// Fuel consumed / 10 is over 1, add hideout management skill point
if (pmcData is not null && Math.Floor(pointsConsumed / 10) >= 1)
{
_profileHelper.AddSkillPointsToPlayer(pmcData, SkillTypes.HideoutManagement, 1);
profileHelper.AddSkillPointsToPlayer(pmcData, SkillTypes.HideoutManagement, 1);
pointsConsumed -= 10;
}
@@ -680,9 +680,9 @@ public class HideoutHelper(
isFuelItemFoundInRaid
);
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
logger.Debug(
$"Profile: {pmcData.Id} Generator has: {fuelRemaining} fuel left in slot {i + 1}"
);
}
@@ -696,9 +696,9 @@ public class HideoutHelper(
// Ran out of fuel items to deduct fuel from
fuelUsedSinceLastTick = Math.Abs(fuelRemaining ?? 0);
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"Profile: {pmcData.Id} Generator ran out of fuel");
logger.Debug($"Profile: {pmcData.Id} Generator ran out of fuel");
}
}
@@ -710,7 +710,7 @@ public class HideoutHelper(
}
protected void UpdateWaterCollector(
string sessionId,
MongoId sessionId,
PmcData pmcData,
BotHideoutArea area,
HideoutProperties hideoutProperties
@@ -752,7 +752,7 @@ public class HideoutHelper(
Action = "HideoutSingleProductionStart",
Items = [],
Tools = [],
Timestamp = _timeUtil.GetTimeStamp(),
Timestamp = timeUtil.GetTimeStamp(),
};
RegisterProduction(pmcData, recipe, sessionId);
@@ -768,19 +768,19 @@ public class HideoutHelper(
/// <returns>Items craft time with bonuses subtracted</returns>
public double? GetAdjustedCraftTimeWithSkills(
PmcData pmcData,
string recipeId,
MongoId recipeId,
bool applyHideoutManagementBonus = false
)
{
var globalSkillsDb = _databaseService.GetGlobals().Configuration.SkillsSettings;
var globalSkillsDb = databaseService.GetGlobals().Configuration.SkillsSettings;
var recipe = _databaseService
var recipe = databaseService
.GetHideout()
.Production.Recipes.FirstOrDefault(production => production.Id == recipeId);
if (recipe is null)
{
_logger.Error(
_serverLocalisationService.GetText("hideout-missing_recipe_in_db", recipeId)
logger.Error(
serverLocalisationService.GetText("hideout-missing_recipe_in_db", recipeId)
);
return null;
@@ -812,7 +812,7 @@ public class HideoutHelper(
}
var modifiedProductionTime = recipe.ProductionTime - timeReductionSeconds;
if (modifiedProductionTime > 0 && _profileHelper.IsDeveloperAccount(pmcData.Id.Value))
if (modifiedProductionTime > 0 && profileHelper.IsDeveloperAccount(pmcData.Id.Value))
{
modifiedProductionTime = 40;
}
@@ -896,7 +896,7 @@ public class HideoutHelper(
// Check units consumed for possible increment of hideout mgmt skill point
if (pmcData is not null && Math.Floor(pointsConsumed / 10) >= 1)
{
_profileHelper.AddSkillPointsToPlayer(pmcData, SkillTypes.HideoutManagement, 1);
profileHelper.AddSkillPointsToPlayer(pmcData, SkillTypes.HideoutManagement, 1);
pointsConsumed -= 10;
}
@@ -912,9 +912,9 @@ public class HideoutHelper(
pointsConsumed,
isWaterFilterFoundInRaid
);
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"Water filter has: {resourceValue} units left in slot {i + 1}");
logger.Debug($"Water filter has: {resourceValue} units left in slot {i + 1}");
}
break; // Break here to avoid iterating other filters now w're done
@@ -959,7 +959,7 @@ public class HideoutHelper(
/// <returns>Drain rate</returns>
protected double GetWaterFilterDrainRate(PmcData pmcData)
{
var globalSkillsDb = _databaseService.GetGlobals().Configuration.SkillsSettings;
var globalSkillsDb = databaseService.GetGlobals().Configuration.SkillsSettings;
// 100 resources last 8 hrs 20 min, 100/8.33/60/60 = 0.00333
const double filterDrainRate = 0.00333d;
@@ -989,9 +989,9 @@ public class HideoutHelper(
/// </summary>
/// <param name="prodId">Id, e.g. Water collector id</param>
/// <returns>Seconds to produce item</returns>
protected double GetTotalProductionTimeSeconds(string prodId)
protected double GetTotalProductionTimeSeconds(MongoId prodId)
{
return _databaseService
return databaseService
.GetHideout()
.Production.Recipes.FirstOrDefault(prod => prod.Id == prodId)
?.ProductionTime ?? 0;
@@ -1036,7 +1036,7 @@ public class HideoutHelper(
300/17.64694/60/60 = 0.004722
*/
var filterDrainRate =
_databaseService.GetHideout().Settings.AirFilterUnitFlowRate
databaseService.GetHideout().Settings.AirFilterUnitFlowRate
* GetTimeElapsedSinceLastServerTick(pmcData, isGeneratorOn);
// Hideout management resource consumption bonus:
@@ -1072,7 +1072,7 @@ public class HideoutHelper(
// check unit consumed for increment skill point
if (pmcData is not null && Math.Floor(pointsConsumed / 10) >= 1)
{
_profileHelper.AddSkillPointsToPlayer(pmcData, SkillTypes.HideoutManagement, 1);
profileHelper.AddSkillPointsToPlayer(pmcData, SkillTypes.HideoutManagement, 1);
pointsConsumed -= 10;
}
@@ -1087,9 +1087,9 @@ public class HideoutHelper(
UnitsConsumed = pointsConsumed,
},
};
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"Air filter: {resourceValue} filter left on slot {i + 1}");
logger.Debug($"Air filter: {resourceValue} filter left on slot {i + 1}");
}
break; // Break here to avoid updating all filters
@@ -1118,7 +1118,7 @@ public class HideoutHelper(
{
if (btcProduction is null)
{
_logger.Error(_serverLocalisationService.GetText("hideout-bitcoin_craft_missing"));
logger.Error(serverLocalisationService.GetText("hideout-bitcoin_craft_missing"));
return;
}
@@ -1181,17 +1181,17 @@ public class HideoutHelper(
return;
}
var bitcoinProdData = _databaseService
var bitcoinProdData = databaseService
.GetHideout()
.Production.Recipes.FirstOrDefault(production => production.Id == BitcoinProductionId);
// BSG finally fixed their settings, they now get loaded from the settings and used in the client
var adjustedCraftTime =
(
_profileHelper.IsDeveloperAccount(pmcData.SessionId)
profileHelper.IsDeveloperAccount(pmcData.SessionId)
? 40
: bitcoinProdData.ProductionTime
) / (1 + (btcFarmCGs - 1) * _databaseService.GetHideout().Settings.GpuBoostRate);
) / (1 + (btcFarmCGs - 1) * databaseService.GetHideout().Settings.GpuBoostRate);
// The progress should be adjusted based on the GPU boost rate, but the target is still the base productionTime
var timeMultiplier = bitcoinProdData.ProductionTime / adjustedCraftTime;
@@ -1212,7 +1212,7 @@ public class HideoutHelper(
}
}
btcProduction.StartTimestamp = _timeUtil.GetTimeStamp();
btcProduction.StartTimestamp = timeUtil.GetTimeStamp();
}
/// <summary>
@@ -1249,11 +1249,11 @@ public class HideoutHelper(
)
{
// Reduce time elapsed (and progress) when generator is off
var timeElapsed = _timeUtil.GetTimeStamp() - pmcData.Hideout.SptUpdateLastRunTimestamp;
var timeElapsed = timeUtil.GetTimeStamp() - pmcData.Hideout.SptUpdateLastRunTimestamp;
if (recipe is not null)
{
var hideoutArea = _databaseService
var hideoutArea = databaseService
.GetHideout()
.Areas.FirstOrDefault(area => area.Type == recipe.AreaType);
if (!(hideoutArea.NeedsFuel ?? false))
@@ -1266,7 +1266,7 @@ public class HideoutHelper(
if (!isGeneratorOn)
{
timeElapsed = (long)(
timeElapsed * _databaseService.GetHideout().Settings.GeneratorSpeedWithoutFuel
timeElapsed * databaseService.GetHideout().Settings.GeneratorSpeedWithoutFuel
);
}
@@ -1280,11 +1280,11 @@ public class HideoutHelper(
/// <returns>Coin slot count</returns>
protected double GetBTCSlots(PmcData pmcData)
{
var bitcoinProductions = _databaseService
var bitcoinProductions = databaseService
.GetHideout()
.Production.Recipes.FirstOrDefault(production => production.Id == BitcoinProductionId);
var productionSlots = bitcoinProductions?.ProductionLimitCount ?? 3; // Default to 3 if none found
var hasManagementSkillSlots = _profileHelper.HasEliteSkillLevel(
var hasManagementSkillSlots = profileHelper.HasEliteSkillLevel(
SkillTypes.HideoutManagement,
pmcData
);
@@ -1298,7 +1298,7 @@ public class HideoutHelper(
/// </summary>
protected double? GetEliteSkillAdditionalBitcoinSlotCount()
{
return _databaseService
return databaseService
.GetGlobals()
.Configuration.SkillsSettings.HideoutManagement.EliteSlots.BitcoinFarm.Container;
}
@@ -1324,7 +1324,7 @@ public class HideoutHelper(
roundedLevel = roundedLevel == 51 ? roundedLevel - 1 : roundedLevel;
return roundedLevel
* _databaseService
* databaseService
.GetGlobals()
.Configuration.SkillsSettings.HideoutManagement.ConsumptionReductionPerLevel
/ 100;
@@ -1392,7 +1392,7 @@ public class HideoutHelper(
public void GetBTC(
PmcData pmcData,
HideoutTakeProductionRequestData request,
string sessionId,
MongoId sessionId,
ItemEventRouterResponse output
)
{
@@ -1401,10 +1401,10 @@ public class HideoutHelper(
var craftedCoinCount = bitcoinCraft?.Products?.Count;
if (bitcoinCraft is null || craftedCoinCount is null)
{
var errorMsg = _serverLocalisationService.GetText("hideout-no_bitcoins_to_collect");
_logger.Error(errorMsg);
var errorMsg = serverLocalisationService.GetText("hideout-no_bitcoins_to_collect");
logger.Error(errorMsg);
_httpResponseUtil.AppendErrorToOutput(output, errorMsg);
httpResponseUtil.AppendErrorToOutput(output, errorMsg);
return;
}
@@ -1434,7 +1434,7 @@ public class HideoutHelper(
};
// Add FiR coins to player inventory
_inventoryHelper.AddItemsToStash(sessionId, addItemsRequest, pmcData, output);
inventoryHelper.AddItemsToStash(sessionId, addItemsRequest, pmcData, output);
if (output.Warnings?.Count > 0)
{
return;
@@ -1446,7 +1446,7 @@ public class HideoutHelper(
// Set start to now
{
pmcData.Hideout.Production[BitcoinProductionId].StartTimestamp =
_timeUtil.GetTimeStamp();
timeUtil.GetTimeStamp();
}
// Remove crafted coins from production in profile now they've been collected
@@ -1484,7 +1484,7 @@ public class HideoutHelper(
if (
improvementDetails.Completed == false
&& improvementDetails.ImproveCompleteTimestamp < _timeUtil.GetTimeStamp()
&& improvementDetails.ImproveCompleteTimestamp < timeUtil.GetTimeStamp()
)
{
improvementDetails.Completed = true;
@@ -1503,7 +1503,7 @@ public class HideoutHelper(
);
// Get hideout area 16 bonus array
var fameAreaDb = _databaseService
var fameAreaDb = databaseService
.GetHideout()
.Areas.FirstOrDefault(area => area.Type == HideoutAreas.PlaceOfFame);
@@ -1584,9 +1584,9 @@ public class HideoutHelper(
bonusIdsToRemove.Add(bonus.Id);
}
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"Removing: {bonusIdsToRemove.Count} bonuses from profile");
logger.Debug($"Removing: {bonusIdsToRemove.Count} bonuses from profile");
}
// Remove the wall bonuses from profile by id
@@ -13,10 +13,10 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class InRaidHelper(
InventoryHelper _inventoryHelper,
ConfigServer _configServer,
ICloner _cloner,
DatabaseService _databaseService
InventoryHelper inventoryHelper,
ConfigServer configServer,
ICloner cloner,
DatabaseService databaseService
)
{
protected static readonly List<string> _pocketSlots =
@@ -26,9 +26,9 @@ public class InRaidHelper(
"pocket3",
"pocket4",
];
protected readonly InRaidConfig _inRaidConfig = _configServer.GetConfig<InRaidConfig>();
protected readonly InRaidConfig _inRaidConfig = configServer.GetConfig<InRaidConfig>();
protected readonly LostOnDeathConfig _lostOnDeathConfig =
_configServer.GetConfig<LostOnDeathConfig>();
configServer.GetConfig<LostOnDeathConfig>();
/// <summary>
/// Deprecated. Reset the skill points earned in a raid to 0, ready for next raid.
@@ -54,7 +54,7 @@ public class InRaidHelper(
/// <param name="isSurvived">Indicates if the player survived the raid</param>
/// <param name="isTransfer">Indicates if it is a transfer operation</param>
public void SetInventory(
string sessionID,
MongoId sessionID,
PmcData serverProfile,
PmcData postRaidProfile,
bool isSurvived,
@@ -62,17 +62,17 @@ public class InRaidHelper(
)
{
// Store insurance (as removeItem() removes insured items)
var insured = _cloner.Clone(serverProfile.InsuredItems);
var insured = cloner.Clone(serverProfile.InsuredItems);
// Remove equipment and loot items stored on player from server profile in preparation for data from client being added
_inventoryHelper.RemoveItem(
inventoryHelper.RemoveItem(
serverProfile,
serverProfile.Inventory.Equipment.Value,
sessionID
);
// Remove quest items stored on player from server profile in preparation for data from client being added
_inventoryHelper.RemoveItem(
inventoryHelper.RemoveItem(
serverProfile,
serverProfile.Inventory.QuestRaidItems.Value,
sessionID
@@ -111,7 +111,7 @@ public class InRaidHelper(
/// <param name="items">Items to process</param>
protected void RemoveFiRStatusFromItems(List<Item> items)
{
var dbItems = _databaseService.GetItems();
var dbItems = databaseService.GetItems();
var itemsToRemovePropertyFrom = items.Where(item =>
{
@@ -166,7 +166,7 @@ public class InRaidHelper(
/// </summary>
/// <param name="pmcData">Player profile</param>
/// <param name="sessionId">Session id</param>
public void DeleteInventory(PmcData pmcData, string sessionId)
public void DeleteInventory(PmcData pmcData, MongoId sessionId)
{
// Get inventory item ids to remove from players profile
var itemIdsToDeleteFromProfile = GetInventoryItemsLostOnDeath(pmcData)
@@ -174,7 +174,7 @@ public class InRaidHelper(
foreach (var itemIdToDelete in itemIdsToDeleteFromProfile)
// Items inside containers are handled as part of function
{
_inventoryHelper.RemoveItem(pmcData, itemIdToDelete, sessionId);
inventoryHelper.RemoveItem(pmcData, itemIdToDelete, sessionId);
}
// Remove contents of fast panel
@@ -188,7 +188,7 @@ public class InRaidHelper(
/// <param name="pmcData">Player profile</param>
/// <param name="secureContainerSlotId">Container slot id to find items for and remove FiR from</param>
public void RemoveFiRStatusFromItemsInContainer(
string sessionId,
MongoId sessionId,
PmcData pmcData,
string secureContainerSlotId
)
@@ -22,15 +22,15 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class InventoryHelper(
ISptLogger<InventoryHelper> _logger,
HttpResponseUtil _httpResponseUtil,
DialogueHelper _dialogueHelper,
EventOutputHolder _eventOutputHolder,
ProfileHelper _profileHelper,
ItemHelper _itemHelper,
ServerLocalisationService _serverLocalisationService,
ConfigServer _configServer,
ICloner _cloner
ISptLogger<InventoryHelper> logger,
HttpResponseUtil httpResponseUtil,
DialogueHelper dialogueHelper,
EventOutputHolder eventOutputHolder,
ProfileHelper profileHelper,
ItemHelper itemHelper,
ServerLocalisationService serverLocalisationService,
ConfigServer configServer,
ICloner cloner
)
{
private static readonly FrozenSet<MongoId> _variableSizeItemTypes =
@@ -39,8 +39,7 @@ public class InventoryHelper(
BaseClasses.FUNCTIONAL_MOD,
BaseClasses.MOD,
];
protected readonly InventoryConfig _inventoryConfig =
_configServer.GetConfig<InventoryConfig>();
protected readonly InventoryConfig _inventoryConfig = configServer.GetConfig<InventoryConfig>();
/// <summary>
/// Add multiple items to player stash (assuming they all fit)
@@ -50,7 +49,7 @@ public class InventoryHelper(
/// <param name="pmcData">Player profile</param>
/// <param name="output">Client response object</param>
public void AddItemsToStash(
string sessionId,
MongoId sessionId,
AddItemsDirectRequest request,
PmcData pmcData,
ItemEventRouterResponse output
@@ -60,9 +59,9 @@ public class InventoryHelper(
if (!CanPlaceItemsInInventory(sessionId, request.ItemsWithModsToAdd))
{
// No space, exit
_httpResponseUtil.AppendErrorToOutput(
httpResponseUtil.AppendErrorToOutput(
output,
_serverLocalisationService.GetText("inventory-no_stash_space"),
serverLocalisationService.GetText("inventory-no_stash_space"),
BackendErrorCodes.NotEnoughSpace
);
@@ -96,19 +95,19 @@ public class InventoryHelper(
/// <param name="pmcData">Player profile</param>
/// <param name="output">Client response object</param>
public void AddItemToStash(
string sessionId,
MongoId sessionId,
AddItemDirectRequest request,
PmcData pmcData,
ItemEventRouterResponse output
)
{
var itemWithModsToAddClone = _cloner.Clone(request.ItemWithModsToAdd);
var itemWithModsToAddClone = cloner.Clone(request.ItemWithModsToAdd);
// Get stash layouts ready for use
var stashFS2D = GetStashSlotMap(pmcData);
if (stashFS2D is null)
{
_logger.Error($"Unable to get stash map for players: {sessionId} stash");
logger.Error($"Unable to get stash map for players: {sessionId} stash");
return;
}
@@ -148,8 +147,8 @@ public class InventoryHelper(
{
// Callback failed
var message = ex.Message;
_httpResponseUtil.AppendErrorToOutput(output, message);
_logger.Error($"[InventoryHelper]: {ex.Message}");
httpResponseUtil.AppendErrorToOutput(output, message);
logger.Error($"[InventoryHelper]: {ex.Message}");
return;
}
@@ -159,9 +158,9 @@ public class InventoryHelper(
output.ProfileChanges[sessionId].Items.NewItems.AddRange(itemWithModsToAddClone);
pmcData.Inventory.Items.AddRange(itemWithModsToAddClone);
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
logger.Debug(
$"Added: {itemWithModsToAddClone[0].Upd?.StackObjectsCount ?? 1} item: {itemWithModsToAddClone[0].Template} with: {itemWithModsToAddClone.Count - 1} mods to inventory"
);
}
@@ -177,10 +176,10 @@ public class InventoryHelper(
foreach (var item in itemWithChildren)
{
// Ensure item has upd object
_itemHelper.AddUpdObjectToItem(item);
itemHelper.AddUpdObjectToItem(item);
// Ammo / currency can NEVER be FiR or have a 'SpawnedInSession' property
item.Upd.SpawnedInSession = _itemHelper.IsOfBaseclass(item.Template, BaseClasses.AMMO)
item.Upd.SpawnedInSession = itemHelper.IsOfBaseclass(item.Template, BaseClasses.AMMO)
? null
: foundInRaid;
}
@@ -216,12 +215,12 @@ public class InventoryHelper(
/// <returns>True all items fit</returns>
public bool CanPlaceItemsInInventory(string sessionId, List<List<Item>> itemsWithChildren)
{
var pmcData = _profileHelper.GetPmcProfile(sessionId);
var pmcData = profileHelper.GetPmcProfile(sessionId);
var stashFS2D = _cloner.Clone(GetStashSlotMap(pmcData));
var stashFS2D = cloner.Clone(GetStashSlotMap(pmcData));
if (stashFS2D is null)
{
_logger.Error($"Unable to get stash map for players: {sessionId} stash");
logger.Error($"Unable to get stash map for players: {sessionId} stash");
return false;
}
@@ -273,8 +272,8 @@ public class InventoryHelper(
}
catch (Exception ex)
{
_logger.Error(
_serverLocalisationService.GetText(
logger.Error(
serverLocalisationService.GetText(
"inventory-unable_to_fit_item_into_inventory",
ex.Message
)
@@ -328,11 +327,8 @@ public class InventoryHelper(
}
catch (Exception ex)
{
_logger.Error(
_serverLocalisationService.GetText(
"inventory-fill_container_failed",
ex.Message
)
logger.Error(
serverLocalisationService.GetText("inventory-fill_container_failed", ex.Message)
);
return;
@@ -449,9 +445,9 @@ public class InventoryHelper(
}
else
{
_httpResponseUtil.AppendErrorToOutput(
httpResponseUtil.AppendErrorToOutput(
output,
_serverLocalisationService.GetText("inventory-no_stash_space"),
serverLocalisationService.GetText("inventory-no_stash_space"),
BackendErrorCodes.NotEnoughSpace
);
}
@@ -459,13 +455,13 @@ public class InventoryHelper(
protected void HandleContainerPlacementError(string errorText, ItemEventRouterResponse output)
{
_logger.Error(
_serverLocalisationService.GetText("inventory-fill_container_failed", errorText)
logger.Error(
serverLocalisationService.GetText("inventory-fill_container_failed", errorText)
);
_httpResponseUtil.AppendErrorToOutput(
httpResponseUtil.AppendErrorToOutput(
output,
_serverLocalisationService.GetText("inventory-no_stash_space")
serverLocalisationService.GetText("inventory-no_stash_space")
);
}
@@ -481,14 +477,14 @@ public class InventoryHelper(
public void RemoveItem(
PmcData profile,
MongoId itemId,
string sessionId,
MongoId sessionId,
ItemEventRouterResponse? output = null
)
{
if (itemId.IsEmpty())
{
_logger.Warning(
_serverLocalisationService.GetText("inventory-unable_to_remove_item_no_id_given")
logger.Warning(
serverLocalisationService.GetText("inventory-unable_to_remove_item_no_id_given")
);
return;
@@ -498,10 +494,10 @@ public class InventoryHelper(
var itemAndChildrenToRemove = profile.Inventory.Items.FindAndReturnChildrenAsItems(itemId);
if (!itemAndChildrenToRemove.Any())
{
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
_serverLocalisationService.GetText(
logger.Debug(
serverLocalisationService.GetText(
"inventory-unable_to_remove_item_id_not_found",
new { ChildId = itemId, ProfileId = profile.Id }
)
@@ -530,8 +526,8 @@ public class InventoryHelper(
}
else
{
_logger.Warning(
_serverLocalisationService.GetText(
logger.Warning(
serverLocalisationService.GetText(
"inventory-unable_to_remove_item_id_not_found",
new { childId = item.Id, ProfileId = profile.Id }
)
@@ -555,12 +551,12 @@ public class InventoryHelper(
/// <param name="removeRequest">Remove request</param>
/// <param name="output">OPTIONAL - ItemEventRouterResponse</param>
public void RemoveItemAndChildrenFromMailRewards(
string sessionId,
MongoId sessionId,
InventoryRemoveRequestData removeRequest,
ItemEventRouterResponse? output
)
{
var fullProfile = _profileHelper.GetFullProfile(sessionId);
var fullProfile = profileHelper.GetFullProfile(sessionId);
// Iterate over all dialogs and look for mesasage with key from request, that has item (and maybe its children) we want to remove
var dialogs = fullProfile.DialogueRecords;
@@ -581,8 +577,8 @@ public class InventoryHelper(
var indexOfItemToRemove = messageWithReward.Items.Data.IndexOf(itemToDelete);
if (indexOfItemToRemove == -1)
{
_logger.Error(
_serverLocalisationService.GetText(
logger.Error(
serverLocalisationService.GetText(
"inventory-unable_to_remove_item_restart_immediately",
new
{
@@ -619,7 +615,7 @@ public class InventoryHelper(
PmcData pmcData,
MongoId itemId,
int countToRemove,
string sessionId,
MongoId sessionId,
ItemEventRouterResponse? output
)
{
@@ -658,7 +654,7 @@ public class InventoryHelper(
}
}
return output ?? _eventOutputHolder.GetOutput(sessionId);
return output ?? eventOutputHolder.GetOutput(sessionId);
}
/// <summary>
@@ -689,21 +685,18 @@ public class InventoryHelper(
)
{
// Invalid item
var (isValidItem, itemTemplate) = _itemHelper.GetItem(itemTpl);
var (isValidItem, itemTemplate) = itemHelper.GetItem(itemTpl);
if (!isValidItem)
{
_logger.Error(
_serverLocalisationService.GetText(
"inventory-invalid_item_missing_from_db",
itemTpl
)
logger.Error(
serverLocalisationService.GetText("inventory-invalid_item_missing_from_db", itemTpl)
);
}
// Item found but no _props property
if (isValidItem && itemTemplate.Properties is null)
{
_serverLocalisationService.GetText(
serverLocalisationService.GetText(
"inventory-item_missing_props_property",
new { itemTpl, itemName = itemTemplate?.Name }
);
@@ -713,8 +706,8 @@ public class InventoryHelper(
if (!isValidItem && itemTemplate is null)
{
// return default size of 1x1
_logger.Error(
_serverLocalisationService.GetText("inventory-return_default_size", itemTpl)
logger.Error(
serverLocalisationService.GetText("inventory-return_default_size", itemTpl)
);
return (1, 1); // Invalid input data, return defaults
@@ -722,7 +715,7 @@ public class InventoryHelper(
if (!inventoryItemHash.ByItemId.TryGetValue(itemId, out var rootItem))
{
_logger.Error(
logger.Error(
$"Unable to get root item with Id: {itemId} from player inventory. Defaulting to 1x1"
);
@@ -757,7 +750,7 @@ public class InventoryHelper(
}
// Item can have child items that adjust its size
if (_itemHelper.IsOfBaseclasses(itemTpl, _variableSizeItemTypes))
if (itemHelper.IsOfBaseclasses(itemTpl, _variableSizeItemTypes))
{
// Storage for root item and its children, store root item id for now
// Will store child items that may have sub-children to process
@@ -781,11 +774,11 @@ public class InventoryHelper(
toDo.Enqueue(childItem.Id);
// Get child item from db
var (isValid, template) = _itemHelper.GetItem(childItem.Template);
var (isValid, template) = itemHelper.GetItem(childItem.Template);
if (!isValid)
{
_logger.Error(
_serverLocalisationService.GetText(
logger.Error(
serverLocalisationService.GetText(
"inventory-get_item_size_item_not_found_by_tpl",
childItem.Template
)
@@ -866,11 +859,11 @@ public class InventoryHelper(
int containerSizeHorizontalX,
int containerSizeVerticalY,
List<Item> itemList,
string containerId
MongoId containerId
)
{
// Create blank 2d map of container
var container = _itemHelper.GetBlankContainerMap(
var container = itemHelper.GetBlankContainerMap(
containerSizeHorizontalX, // Column count
containerSizeVerticalY // Row count
);
@@ -892,7 +885,7 @@ public class InventoryHelper(
if (itemLocation is null)
{
// Item has no location property
_logger.Error(
logger.Error(
$"Unable to find 'location' property on item with id: {rootItem.Id}, skipping"
);
@@ -937,8 +930,8 @@ public class InventoryHelper(
var message =
$"Item: {rootItem.Id} at: {itemLocation.X}, {itemLocation.Y} size: {itemHeight}x{itemWidth} extends outside the containers bounds";
_logger.Error(
_serverLocalisationService.GetText(
logger.Error(
serverLocalisationService.GetText(
"inventory-unable_to_fill_container",
new { id = rootItem.Id, error = $"{message}" }
)
@@ -998,11 +991,11 @@ public class InventoryHelper(
public OwnerInventoryItems GetOwnerInventoryItems(
InventoryBaseActionRequestData request,
MongoId itemId,
string sessionId
MongoId sessionId
)
{
var pmcItems = _profileHelper.GetPmcProfile(sessionId).Inventory.Items;
var scavProfile = _profileHelper.GetScavProfile(sessionId);
var pmcItems = profileHelper.GetPmcProfile(sessionId).Inventory.Items;
var scavProfile = profileHelper.GetScavProfile(sessionId);
var fromInventoryItems = pmcItems;
var fromType = "pmc";
@@ -1018,7 +1011,7 @@ public class InventoryHelper(
)
{
// Split requests don't use 'use' but 'splitItem' property
fromInventoryItems = _dialogueHelper.GetMessageItemContents(
fromInventoryItems = dialogueHelper.GetMessageItemContents(
request.FromOwner.Id,
sessionId,
itemId
@@ -1064,7 +1057,7 @@ public class InventoryHelper(
horizontal,
vertical,
pmcData.Inventory.Items,
pmcData.Inventory.Stash
pmcData.Inventory.Stash.Value
);
}
@@ -1075,16 +1068,13 @@ public class InventoryHelper(
/// <returns>blank two-dimensional array</returns>
public int[,] GetContainerSlotMap(string containerTpl)
{
var containerTemplate = _itemHelper.GetItem(containerTpl).Value;
var containerTemplate = itemHelper.GetItem(containerTpl).Value;
var firstContainerGrid = containerTemplate.Properties.Grids.FirstOrDefault();
var containerRowCount = firstContainerGrid.Props.CellsH;
var containerColumnCount = firstContainerGrid.Props.CellsV;
return _itemHelper.GetBlankContainerMap(
containerColumnCount.Value,
containerRowCount.Value
);
return itemHelper.GetBlankContainerMap(containerColumnCount.Value, containerRowCount.Value);
}
/// <summary>
@@ -1094,7 +1084,12 @@ public class InventoryHelper(
/// <returns>two-dimensional array</returns>
protected int[,] GetSortingTableSlotMap(PmcData pmcData)
{
return GetContainerMap(10, 45, pmcData.Inventory.Items, pmcData.Inventory.SortingTable);
return GetContainerMap(
10,
45,
pmcData.Inventory.Items,
pmcData.Inventory.SortingTable.Value
);
}
/// <summary>
@@ -1109,18 +1104,16 @@ public class InventoryHelper(
var stashTpl = GetProfileStashTpl(pmcData);
if (stashTpl is null)
{
_logger.Error(_serverLocalisationService.GetText("inventory-missing_stash_size"));
logger.Error(serverLocalisationService.GetText("inventory-missing_stash_size"));
return (0, 0);
}
// Look up details of stash in db
var (isValidItem, stashItemDbItem) = _itemHelper.GetItem(stashTpl);
var (isValidItem, stashItemDbItem) = itemHelper.GetItem(stashTpl);
if (!isValidItem)
{
_logger.Error(
_serverLocalisationService.GetText("inventory-stash_not_found", stashTpl)
);
logger.Error(serverLocalisationService.GetText("inventory-stash_not_found", stashTpl));
return (0, 0);
}
@@ -1156,7 +1149,7 @@ public class InventoryHelper(
);
if (stashObj is null)
{
_logger.Error(_serverLocalisationService.GetText("inventory-unable_to_find_stash"));
logger.Error(serverLocalisationService.GetText("inventory-unable_to_find_stash"));
}
return stashObj?.Template;
@@ -1183,8 +1176,8 @@ public class InventoryHelper(
var itemToMove = sourceItems.FirstOrDefault(item => item.Id == itemId);
if (itemToMove is null)
{
_logger.Error(
_serverLocalisationService.GetText(
logger.Error(
serverLocalisationService.GetText(
"inventory-unable_to_find_item_to_move",
itemId
)
@@ -1241,15 +1234,15 @@ public class InventoryHelper(
{
var noMatchingItemMesage =
$"Unable to move item: {moveRequest.Item}, cannot find in inventory";
_logger.Error(noMatchingItemMesage);
logger.Error(noMatchingItemMesage);
errorMessage = noMatchingItemMesage;
return false;
}
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
logger.Debug(
$"{moveRequest.Action} item: {moveRequest.Item} from slotid: {matchingInventoryItem.SlotId} to container: {moveRequest.To.Container}"
);
}
@@ -1260,8 +1253,8 @@ public class InventoryHelper(
&& moveRequest.To.Container == "cartridges"
)
{
_logger.Warning(
_serverLocalisationService.GetText(
logger.Warning(
serverLocalisationService.GetText(
"inventory-invalid_move_to_container",
new
{
@@ -1380,7 +1373,7 @@ public class InventoryHelper(
.ToList();
foreach (var message in errors)
{
_logger.Error(message);
logger.Error(message);
}
throw new Exception(
@@ -1439,7 +1439,7 @@ public class ItemHelper(
0
].Filter?.FirstOrDefault();
ammoBox.Add(
CreateCartridges(ammoBox[0].Id, cartridgeTpl, (int)ammoBoxMaxCartridgeCount, 0)
CreateCartridges(ammoBox[0].Id, cartridgeTpl.Value, (int)ammoBoxMaxCartridgeCount, 0)
);
}
@@ -1459,7 +1459,7 @@ public class ItemHelper(
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist,
string? caliber = null,
double minSizePercent = 0.25,
string? defaultCartridgeTpl = null,
MongoId? defaultCartridgeTpl = null,
TemplateItem? weapon = null
)
{
@@ -1504,7 +1504,7 @@ public class ItemHelper(
public void FillMagazineWithCartridge(
List<Item> magazineWithChildCartridges,
TemplateItem magTemplate,
string cartridgeTpl,
MongoId cartridgeTpl,
double minSizeMultiplier = 0.25
)
{
@@ -1624,7 +1624,7 @@ public class ItemHelper(
protected string? DrawAmmoTpl(
string caliber,
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist,
string? fallbackCartridgeTpl = null,
MongoId? fallbackCartridgeTpl = null,
ICollection<MongoId>? cartridgeWhitelist = null
)
{
@@ -1677,7 +1677,7 @@ public class ItemHelper(
/// <param name="stackCount">Count of cartridges inside parent</param>
/// <param name="location">Location inside parent (e.g. 0, 1)</param>
/// <returns>Item</returns>
public Item CreateCartridges(string parentId, string ammoTpl, int stackCount, double location)
public Item CreateCartridges(MongoId parentId, MongoId ammoTpl, int stackCount, double location)
{
return new Item
{
@@ -1957,7 +1957,7 @@ public class ItemHelper(
);
}
public string? GetItemBaseType(MongoId tpl, bool rootOnly = true)
public MongoId? GetItemBaseType(MongoId tpl, bool rootOnly = true)
{
var result = GetItem(tpl);
if (!result.Key)
@@ -1992,7 +1992,7 @@ public class ItemHelper(
/// Get a 2D grid of a container's item slots
/// </summary>
/// <param name="containerTpl">Tpl id of the container</param>
public int[,] GetContainerMapping(string containerTpl)
public int[,] GetContainerMapping(MongoId containerTpl)
{
// Get template from db
var containerTemplate = GetItem(containerTpl).Value;
@@ -14,12 +14,12 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class NotificationSendHelper(
ISptLogger<NotificationSendHelper> _logger,
SptWebSocketConnectionHandler _sptWebSocketConnectionHandler,
SaveServer _saveServer,
NotificationService _notificationService,
TimeUtil _timeUtil,
JsonUtil _jsonUtil
ISptLogger<NotificationSendHelper> logger,
SptWebSocketConnectionHandler sptWebSocketConnectionHandler,
SaveServer saveServer,
NotificationService notificationService,
TimeUtil timeUtil,
JsonUtil jsonUtil
)
{
/// <summary>
@@ -27,33 +27,33 @@ public class NotificationSendHelper(
/// </summary>
/// <param name="sessionID">Session/player id</param>
/// <param name="notificationMessage"></param>
public void SendMessage(string sessionID, WsNotificationEvent notificationMessage)
public void SendMessage(MongoId sessionID, WsNotificationEvent notificationMessage)
{
if (_logger.IsLogEnabled(LogLevel.Debug))
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))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
logger.Debug(
$"Send message for {sessionID} websocket available, message being sent"
);
}
_sptWebSocketConnectionHandler.SendMessage(sessionID, notificationMessage);
sptWebSocketConnectionHandler.SendMessage(sessionID, notificationMessage);
}
else
{
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
logger.Debug(
$"Send message for {sessionID} websocket not available, queuing into profile"
);
}
_notificationService.Add(sessionID, notificationMessage);
notificationService.Add(sessionID, notificationMessage);
}
}
@@ -65,7 +65,7 @@ public class NotificationSendHelper(
/// <param name="messageText">Text to send player</param>
/// <param name="messageType">Underlying type of message being sent</param>
public void SendMessageToPlayer(
string sessionId,
MongoId sessionId,
UserDialogInfo senderDetails,
string messageText,
MessageType messageType
@@ -79,7 +79,7 @@ public class NotificationSendHelper(
Id = new MongoId(),
UserId = dialog.Id,
MessageType = messageType,
DateTime = _timeUtil.GetTimeStamp(),
DateTime = timeUtil.GetTimeStamp(),
Text = messageText,
HasRewards = null,
RewardCollected = null,
@@ -105,7 +105,7 @@ public class NotificationSendHelper(
/// <param name="senderDetails">Who is sending the message</param>
/// <returns>Dialogue</returns>
protected Models.Eft.Profile.Dialogue GetDialog(
string sessionId,
MongoId sessionId,
MessageType messageType,
UserDialogInfo senderDetails
)
@@ -114,7 +114,7 @@ public class NotificationSendHelper(
var dialogKey = senderDetails.Id;
// Get all dialogs with pmcs/traders player has
var dialogueData = _saveServer.GetProfile(sessionId).DialogueRecords;
var dialogueData = saveServer.GetProfile(sessionId).DialogueRecords;
// Ensure empty dialog exists based on sender details passed in
dialogueData.TryAdd(
@@ -9,10 +9,10 @@ using SPTarkov.Server.Core.Utils.Cloners;
namespace SPTarkov.Server.Core.Helpers;
[Injectable(InjectionType.Singleton)]
public class PresetHelper(DatabaseService _databaseService, ItemHelper _itemHelper, ICloner _cloner)
public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper, ICloner cloner)
{
protected Dictionary<string, Preset> _defaultEquipmentPresets;
protected Dictionary<string, Preset> _defaultWeaponPresets;
protected Dictionary<string, Preset>? _defaultEquipmentPresets;
protected Dictionary<string, Preset>? _defaultWeaponPresets;
/// <summary>
/// Preset cache - key = item tpl, value = preset ids
@@ -60,11 +60,11 @@ public class PresetHelper(DatabaseService _databaseService, ItemHelper _itemHelp
{
if (_defaultWeaponPresets is null)
{
var tempPresets = _databaseService.GetGlobals().ItemPresets;
var tempPresets = databaseService.GetGlobals().ItemPresets;
_defaultWeaponPresets = tempPresets
.Where(p =>
p.Value.Encyclopedia != null
&& _itemHelper.IsOfBaseclass(p.Value.Encyclopedia, BaseClasses.WEAPON)
&& itemHelper.IsOfBaseclass(p.Value.Encyclopedia, BaseClasses.WEAPON)
)
.ToDictionary();
}
@@ -80,11 +80,11 @@ public class PresetHelper(DatabaseService _databaseService, ItemHelper _itemHelp
{
if (_defaultEquipmentPresets == null)
{
var tempPresets = _databaseService.GetGlobals().ItemPresets;
var tempPresets = databaseService.GetGlobals().ItemPresets;
_defaultEquipmentPresets = tempPresets
.Where(p =>
p.Value.Encyclopedia != null
&& _itemHelper.ArmorItemCanHoldMods(p.Value.Encyclopedia)
&& itemHelper.ArmorItemCanHoldMods(p.Value.Encyclopedia)
)
.ToDictionary();
}
@@ -97,14 +97,14 @@ public class PresetHelper(DatabaseService _databaseService, ItemHelper _itemHelp
/// </summary>
/// <param name="id">Value to check</param>
/// <returns>True = preset exists for this id</returns>
public bool IsPreset(string id)
public bool IsPreset(MongoId id)
{
if (string.IsNullOrEmpty(id))
if (id.IsEmpty())
{
return false;
}
return _databaseService.GetGlobals().ItemPresets.ContainsKey(id);
return databaseService.GetGlobals().ItemPresets.ContainsKey(id);
}
/**
@@ -113,9 +113,9 @@ public class PresetHelper(DatabaseService _databaseService, ItemHelper _itemHelp
* @param baseClass The BaseClasses enum to check against
* @returns True if the preset is of the given base class, false otherwise
*/
public bool IsPresetBaseClass(string id, MongoId baseClass)
public bool IsPresetBaseClass(MongoId id, MongoId baseClass)
{
return IsPreset(id) && _itemHelper.IsOfBaseclass(GetPreset(id).Encyclopedia, baseClass);
return IsPreset(id) && itemHelper.IsOfBaseclass(GetPreset(id).Encyclopedia, baseClass);
}
/// <summary>
@@ -128,9 +128,9 @@ public class PresetHelper(DatabaseService _databaseService, ItemHelper _itemHelp
return _lookup.ContainsKey(templateId);
}
public Preset GetPreset(string id)
public Preset GetPreset(MongoId id)
{
return _cloner.Clone(_databaseService.GetGlobals().ItemPresets[id]);
return cloner.Clone(databaseService.GetGlobals().ItemPresets[id]);
}
/// <summary>
@@ -139,7 +139,7 @@ public class PresetHelper(DatabaseService _databaseService, ItemHelper _itemHelp
/// <returns>List</returns>
public List<Preset> GetAllPresets()
{
return _cloner.Clone(_databaseService.GetGlobals().ItemPresets.Values.ToList());
return cloner.Clone(databaseService.GetGlobals().ItemPresets.Values.ToList());
}
/// <summary>
@@ -147,7 +147,7 @@ public class PresetHelper(DatabaseService _databaseService, ItemHelper _itemHelp
/// </summary>
/// <param name="templateId">Tpl to get presets for</param>
/// <returns>List</returns>
public List<Preset> GetPresets(string templateId)
public List<Preset> GetPresets(MongoId templateId)
{
// Try adn get preset ids from cache if they exist
if (!_lookup.TryGetValue(templateId, out var presetDetailsForTpl))
@@ -157,9 +157,9 @@ public class PresetHelper(DatabaseService _databaseService, ItemHelper _itemHelp
}
// Use gathered preset ids to get full preset objects, clone and return
return _cloner.Clone(
return cloner.Clone(
presetDetailsForTpl
.PresetIds.Select(x => _databaseService.GetGlobals().ItemPresets[x])
.PresetIds.Select(x => databaseService.GetGlobals().ItemPresets[x])
.ToList()
);
}
@@ -188,13 +188,13 @@ public class PresetHelper(DatabaseService _databaseService, ItemHelper _itemHelp
if (!_defaultEquipmentPresets.TryGetValue(presetDetails.DefaultId, out defaultPreset))
{
// Default not found in weapon or equipment, return first preset in list
return _cloner.Clone(
_databaseService.GetGlobals().ItemPresets[presetDetails.PresetIds.First()]
return cloner.Clone(
databaseService.GetGlobals().ItemPresets[presetDetails.PresetIds.First()]
);
}
}
return _cloner.Clone(defaultPreset);
return cloner.Clone(defaultPreset);
}
/// <summary>
@@ -204,7 +204,7 @@ public class PresetHelper(DatabaseService _databaseService, ItemHelper _itemHelp
/// <returns>tpl mongoid</returns>
public MongoId GetBaseItemTpl(MongoId presetId)
{
if (!_databaseService.GetGlobals().ItemPresets.TryGetValue(presetId, out var preset))
if (!databaseService.GetGlobals().ItemPresets.TryGetValue(presetId, out var preset))
{
// No preset exists
return "";
@@ -236,6 +236,6 @@ public class PresetHelper(DatabaseService _databaseService, ItemHelper _itemHelp
: [tpl];
// Get price of tpls
return _itemHelper.GetItemAndChildrenPrice(tpls);
return itemHelper.GetItemAndChildrenPrice(tpls);
}
}
@@ -1,5 +1,6 @@
using SPTarkov.DI.Annotations;
using SPTarkov.Server.Core.Extensions;
using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
using SPTarkov.Server.Core.Models.Eft.Profile;
using SPTarkov.Server.Core.Models.Enums;
@@ -10,32 +11,15 @@ using SPTarkov.Server.Core.Utils;
namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class PrestigeHelper
public class PrestigeHelper(
ISptLogger<PrestigeHelper> logger,
TimeUtil timeUtil,
DatabaseService databaseService,
MailSendService mailSendService,
ProfileHelper profileHelper,
RewardHelper rewardHelper
)
{
protected DatabaseService _databaseService;
protected ISptLogger<PrestigeHelper> _logger;
protected MailSendService _mailSendService;
protected ProfileHelper _profileHelper;
protected RewardHelper _rewardHelper;
protected TimeUtil _timeUtil;
public PrestigeHelper(
ISptLogger<PrestigeHelper> logger,
TimeUtil timeUtil,
DatabaseService databaseService,
MailSendService mailSendService,
ProfileHelper profileHelper,
RewardHelper rewardHelper
)
{
_logger = logger;
_timeUtil = timeUtil;
_databaseService = databaseService;
_mailSendService = mailSendService;
_profileHelper = profileHelper;
_rewardHelper = rewardHelper;
}
public void ProcessPendingPrestige(
SptProfile oldProfile,
SptProfile newProfile,
@@ -92,23 +76,22 @@ public class PrestigeHelper
// Add "Prestigious" achievement
if (!newProfile.CharacterData.PmcData.Achievements.ContainsKey("676091c0f457869a94017a23"))
{
_rewardHelper.AddAchievementToProfile(newProfile, "676091c0f457869a94017a23");
rewardHelper.AddAchievementToProfile(newProfile, "676091c0f457869a94017a23");
}
// Assumes Prestige data is in descending order
var currentPrestigeData = _databaseService.GetTemplates().Prestige.Elements[
var currentPrestigeData = databaseService.GetTemplates().Prestige.Elements[
indexOfPrestigeObtained
];
var prestigeRewards = _databaseService
var prestigeRewards = databaseService
.GetTemplates()
.Prestige.Elements.Slice(0, indexOfPrestigeObtained + 1)
.SelectMany(prestige => prestige.Rewards);
AddPrestigeRewardsToProfile(sessionId, newProfile, prestigeRewards);
AddPrestigeRewardsToProfile(sessionId.Value, newProfile, prestigeRewards);
// Flag profile as having achieved this prestige level
newProfile.CharacterData.PmcData.Prestige[currentPrestigeData.Id] =
_timeUtil.GetTimeStamp();
newProfile.CharacterData.PmcData.Prestige[currentPrestigeData.Id] = timeUtil.GetTimeStamp();
var itemsToTransfer = new List<Item>();
@@ -120,7 +103,7 @@ public class PrestigeHelper
);
if (item is null)
{
_logger.Error(
logger.Error(
$"Unable to find item with id: {transferRequest.Id} in profile: {sessionId}, skipping"
);
continue;
@@ -129,13 +112,13 @@ public class PrestigeHelper
itemsToTransfer.Add(item);
}
_mailSendService.SendSystemMessageToPlayer(sessionId.Value, "", itemsToTransfer, 31536000);
mailSendService.SendSystemMessageToPlayer(sessionId.Value, "", itemsToTransfer, 31536000);
newProfile.CharacterData.PmcData.Info.PrestigeLevel = prestige.PrestigeLevel;
}
private void AddPrestigeRewardsToProfile(
string sessionId,
MongoId sessionId,
SptProfile newProfile,
IEnumerable<Reward> rewards
)
@@ -148,7 +131,7 @@ public class PrestigeHelper
{
case RewardType.CustomizationDirect:
{
_profileHelper.AddHideoutCustomisationUnlock(
profileHelper.AddHideoutCustomisationUnlock(
newProfile,
reward,
CustomisationSource.PRESTIGE
@@ -158,7 +141,7 @@ public class PrestigeHelper
case RewardType.Skill:
if (Enum.TryParse(reward.Target, out SkillTypes result))
{
_profileHelper.AddSkillPointsToPlayer(
profileHelper.AddSkillPointsToPlayer(
newProfile.CharacterData.PmcData,
result,
reward.Value
@@ -166,7 +149,7 @@ public class PrestigeHelper
}
else
{
_logger.Error($"Unable to parse reward Target to Enum: {reward.Target}");
logger.Error($"Unable to parse reward Target to Enum: {reward.Target}");
}
break;
@@ -181,14 +164,14 @@ public class PrestigeHelper
break;
}
default:
_logger.Error($"Unhandled prestige reward type: {reward.Type}");
logger.Error($"Unhandled prestige reward type: {reward.Type}");
break;
}
}
if (itemsToSend.Count > 0)
{
_mailSendService.SendSystemMessageToPlayer(sessionId, "", itemsToSend, 31536000);
mailSendService.SendSystemMessageToPlayer(sessionId, "", itemsToSend, 31536000);
}
}
}
@@ -18,14 +18,14 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class ProfileHelper(
ISptLogger<ProfileHelper> _logger,
ICloner _cloner,
SaveServer _saveServer,
DatabaseService _databaseService,
Watermark _watermark,
TimeUtil _timeUtil,
ServerLocalisationService _serverLocalisationService,
ConfigServer _configServer
ISptLogger<ProfileHelper> logger,
ICloner cloner,
SaveServer saveServer,
DatabaseService databaseService,
Watermark watermark,
TimeUtil timeUtil,
ServerLocalisationService serverLocalisationService,
ConfigServer configServer
)
{
protected static readonly FrozenSet<string> _gameEditionsWithFreeRefresh =
@@ -33,8 +33,7 @@ public class ProfileHelper(
"edge_of_darkness",
"unheard_edition",
];
protected readonly InventoryConfig _inventoryConfig =
_configServer.GetConfig<InventoryConfig>();
protected readonly InventoryConfig _inventoryConfig = configServer.GetConfig<InventoryConfig>();
/// <summary>
/// Remove/reset a completed quest condition from players profile quest data
@@ -64,7 +63,7 @@ public class ProfileHelper(
/// <returns>Dictionary of profiles</returns>
public Dictionary<MongoId, SptProfile> GetProfiles()
{
return _saveServer.GetProfiles();
return saveServer.GetProfiles();
}
/// <summary>
@@ -81,7 +80,7 @@ public class ProfileHelper(
return output;
}
var FullProfileClone = _cloner.Clone(GetFullProfile(sessionId));
var FullProfileClone = cloner.Clone(GetFullProfile(sessionId));
// Sanitize any data the client can not receive
SanitizeProfileForClient(FullProfileClone);
@@ -115,7 +114,7 @@ public class ProfileHelper(
/// <returns>True if already in use</returns>
public bool IsNicknameTaken(ValidateNicknameRequestData nicknameRequest, MongoId sessionID)
{
var allProfiles = _saveServer.GetProfiles().Values;
var allProfiles = saveServer.GetProfiles().Values;
// Find a profile that doesn't have same session id but has same name
return allProfiles.Any(p =>
@@ -153,7 +152,7 @@ public class ProfileHelper(
}
else
{
_logger.Error($"Profile {sessionID} does not exist");
logger.Error($"Profile {sessionID} does not exist");
}
}
@@ -162,12 +161,12 @@ public class ProfileHelper(
/// </summary>
/// <param name="pmcId">Profile id to find</param>
/// <returns>PmcData</returns>
public PmcData? GetProfileByPmcId(string pmcId)
public PmcData? GetProfileByPmcId(MongoId pmcId)
{
return _saveServer
return saveServer
.GetProfiles()
.Values.First(p => p.CharacterData?.PmcData?.Id == pmcId)
.CharacterData.PmcData;
.CharacterData?.PmcData;
}
/// <summary>
@@ -178,7 +177,7 @@ public class ProfileHelper(
public int? GetExperience(int level)
{
var playerLevel = level;
var expTable = _databaseService.GetGlobals().Configuration.Exp.Level.ExperienceTable;
var expTable = databaseService.GetGlobals().Configuration.Exp.Level.ExperienceTable;
int? exp = 0;
if (playerLevel >= expTable.Length) // make sure to not go out of bounds
@@ -200,7 +199,7 @@ public class ProfileHelper(
/// <returns>Max level</returns>
public int GetMaxLevel()
{
return _databaseService.GetGlobals().Configuration.Exp.Level.ExperienceTable.Length - 1;
return databaseService.GetGlobals().Configuration.Exp.Level.ExperienceTable.Length - 1;
}
/// <summary>
@@ -211,7 +210,7 @@ public class ProfileHelper(
{
return new Spt
{
Version = _watermark.GetVersionTag(true),
Version = watermark.GetVersionTag(true),
Mods = [],
ReceivedGifts = [],
BlacklistedItemTemplates = [],
@@ -230,7 +229,7 @@ public class ProfileHelper(
/// <returns>SptProfile object</returns>
public SptProfile? GetFullProfile(MongoId sessionID)
{
return _saveServer.ProfileExists(sessionID) ? _saveServer.GetProfile(sessionID) : null;
return saveServer.ProfileExists(sessionID) ? saveServer.GetProfile(sessionID) : null;
}
/// <summary>
@@ -243,13 +242,10 @@ public class ProfileHelper(
var check = int.TryParse(accountId, out var aid);
if (!check)
{
_logger.Error($"Account {accountId} does not exist");
logger.Error($"Account {accountId} does not exist");
}
return _saveServer
.GetProfiles()
.FirstOrDefault(p => p.Value?.ProfileInfo?.Aid == aid)
.Value;
return saveServer.GetProfiles().FirstOrDefault(p => p.Value?.ProfileInfo?.Aid == aid).Value;
}
/// <summary>
@@ -308,7 +304,7 @@ public class ProfileHelper(
/// UNUSED?
public bool IsPlayer(MongoId userId)
{
return _saveServer.ProfileExists(userId);
return saveServer.ProfileExists(userId);
}
/// <summary>
@@ -318,7 +314,7 @@ public class ProfileHelper(
/// <returns>IPmcData object</returns>
public PmcData? GetScavProfile(MongoId sessionID)
{
return _saveServer.GetProfile(sessionID).CharacterData?.ScavData;
return saveServer.GetProfile(sessionID).CharacterData?.ScavData;
}
/// <summary>
@@ -362,7 +358,7 @@ public class ProfileHelper(
/// TODO: logic doesn't feel right to have IsWiped being nullable
protected bool IsWiped(MongoId sessionID)
{
return _saveServer.GetProfile(sessionID)?.ProfileInfo?.IsWiped ?? false;
return saveServer.GetProfile(sessionID)?.ProfileInfo?.IsWiped ?? false;
}
/// <summary>
@@ -417,7 +413,7 @@ public class ProfileHelper(
new ReceivedGift
{
GiftId = giftId,
TimestampLastAccepted = _timeUtil.GetTimeStamp(),
TimestampLastAccepted = timeUtil.GetTimeStamp(),
Current = 1,
}
);
@@ -435,9 +431,9 @@ public class ProfileHelper(
var profile = GetFullProfile(playerId);
if (profile == null)
{
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"Unable to gift {giftId}, Profile: {playerId} does not exist");
logger.Debug($"Unable to gift {giftId}, Profile: {playerId} does not exist");
}
return false;
@@ -486,7 +482,7 @@ public class ProfileHelper(
var profileSkill = profileSkills.FirstOrDefault(s => s.Id == skill);
if (profileSkill == null)
{
_logger.Error(_serverLocalisationService.GetText("quest-no_skill_found", skill));
logger.Error(serverLocalisationService.GetText("quest-no_skill_found", skill));
return false;
}
@@ -509,8 +505,8 @@ public class ProfileHelper(
{
if (pointsToAddToSkill < 0D)
{
_logger.Warning(
_serverLocalisationService.GetText(
logger.Warning(
serverLocalisationService.GetText(
"player-attempt_to_increment_skill_with_negative_value",
skill
)
@@ -521,7 +517,7 @@ public class ProfileHelper(
var profileSkills = pmcProfile?.Skills?.Common;
if (profileSkills == null)
{
_logger.Warning(
logger.Warning(
$"Unable to add: {pointsToAddToSkill} points to {skill}, Profile has no skills"
);
return;
@@ -530,13 +526,13 @@ public class ProfileHelper(
var profileSkill = profileSkills.FirstOrDefault(s => s.Id == skill);
if (profileSkill == null)
{
_logger.Error(_serverLocalisationService.GetText("quest-no_skill_found", skill));
logger.Error(serverLocalisationService.GetText("quest-no_skill_found", skill));
return;
}
if (useSkillProgressRateMultiplier)
{
var skillProgressRate = _databaseService
var skillProgressRate = databaseService
.GetGlobals()
.Configuration.SkillsSettings.SkillProgressRate;
pointsToAddToSkill *= skillProgressRate;
@@ -553,7 +549,7 @@ public class ProfileHelper(
profileSkill.PointsEarnedDuringSession ??= 0;
profileSkill.PointsEarnedDuringSession += pointsToAddToSkill;
profileSkill.LastAccess = _timeUtil.GetTimeStamp();
profileSkill.LastAccess = timeUtil.GetTimeStamp();
}
/// <summary>
@@ -619,7 +615,7 @@ public class ProfileHelper(
var pockets = pmcProfile.Inventory.Items.Where(i => i.SlotId == "Pockets");
if (!pockets.Any())
{
_logger.Error(
logger.Error(
$"Unable to replace profile: {pmcProfile.Id} pocket tpl with: {newPocketTpl} as Pocket item could not be found."
);
return;
@@ -647,7 +643,7 @@ public class ProfileHelper(
if (itemAndChildren?.Count > 0)
{
// To get the client to actually see the items, we set the main item's parent to null, so it's treated as a root item
var clonedItems = _cloner.Clone(itemAndChildren);
var clonedItems = cloner.Clone(itemAndChildren);
clonedItems.First().ParentId = null;
fullFavorites.AddRange(clonedItems);
@@ -666,13 +662,13 @@ public class ProfileHelper(
if (fullProfile?.CustomisationUnlocks?.Any(u => u.Id == reward.Target) ?? false)
{
_logger.Warning(
logger.Warning(
$"Profile: {fullProfile.ProfileInfo.ProfileId} already has hideout customisation reward: {reward.Target}, skipping"
);
return;
}
var customisationTemplateDb = _databaseService.GetTemplates().Customization;
var customisationTemplateDb = databaseService.GetTemplates().Customization;
var matchingCustomisation = customisationTemplateDb.GetValueOrDefault(reward.Target, null);
if (matchingCustomisation is not null)
@@ -711,7 +707,7 @@ public class ProfileHelper(
rewardToStore.Type = CustomisationType.SHOOTING_RANGE_MARK;
break;
default:
_logger.Error(
logger.Error(
$"Unhandled customisation unlock type: {matchingCustomisation.Parent} not added to profile"
);
return;
@@ -729,7 +725,7 @@ public class ProfileHelper(
/// <returns></returns>
public TemplateSide GetProfileTemplateForSide(string accountEdition, string side)
{
var profileTemplates = _databaseService.GetProfileTemplates();
var profileTemplates = databaseService.GetProfileTemplates();
// Get matching profile 'type' e.g. 'standard'
profileTemplates.TryGetValue(accountEdition, out var matchingProfileTemplate);
@@ -22,20 +22,20 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable(InjectionType.Singleton)]
public class QuestHelper(
ISptLogger<QuestHelper> _logger,
TimeUtil _timeUtil,
ItemHelper _itemHelper,
DatabaseService _databaseService,
EventOutputHolder _eventOutputHolder,
LocaleService _localeService,
ProfileHelper _profileHelper,
QuestRewardHelper _questRewardHelper,
RewardHelper _rewardHelper,
ServerLocalisationService _serverLocalisationService,
SeasonalEventService _seasonalEventService,
MailSendService _mailSendService,
ConfigServer _configServer,
ICloner _cloner
ISptLogger<QuestHelper> logger,
TimeUtil timeUtil,
ItemHelper itemHelper,
DatabaseService databaseService,
EventOutputHolder eventOutputHolder,
LocaleService localeService,
ProfileHelper profileHelper,
QuestRewardHelper questRewardHelper,
RewardHelper rewardHelper,
ServerLocalisationService serverLocalisationService,
SeasonalEventService seasonalEventService,
MailSendService mailSendService,
ConfigServer configServer,
ICloner cloner
)
{
protected readonly HashSet<QuestStatusEnum> _startedOrAvailToFinish =
@@ -43,7 +43,7 @@ public class QuestHelper(
QuestStatusEnum.Started,
QuestStatusEnum.AvailableForFinish,
];
protected readonly QuestConfig _questConfig = _configServer.GetConfig<QuestConfig>();
protected readonly QuestConfig _questConfig = configServer.GetConfig<QuestConfig>();
private Dictionary<string, List<QuestCondition>>? _sellToTraderQuestConditionCache;
/// <summary>
@@ -85,8 +85,8 @@ public class QuestHelper(
case "=":
return playerLevel == conditionValue;
default:
_logger.Error(
_serverLocalisationService.GetText(
logger.Error(
serverLocalisationService.GetText(
"quest-unable_to_find_compare_condition",
condition.CompareMethod
)
@@ -147,16 +147,16 @@ public class QuestHelper(
{
// Calculate how much progress to add, limiting it to the current level max progress
var currentLevelRemainingProgress = (currentLevel + 1) * 10 - startingLevelProgress;
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"currentLevelRemainingProgress: {currentLevelRemainingProgress}");
logger.Debug($"currentLevelRemainingProgress: {currentLevelRemainingProgress}");
}
var progressToAdd = Math.Min(remainingProgress, currentLevelRemainingProgress ?? 0);
var adjustedProgressToAdd = 10 / (currentLevel + 1) * progressToAdd;
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
logger.Debug(
$"Progress To Add: {progressToAdd} Adjusted for level: {adjustedProgressToAdd}"
);
}
@@ -185,7 +185,7 @@ public class QuestHelper(
public string GetQuestNameFromLocale(string questId)
{
var questNameKey = $"{questId} name";
return _localeService.GetLocaleDb().GetValueOrDefault(questNameKey, "UNKNOWN");
return localeService.GetLocaleDb().GetValueOrDefault(questNameKey, "UNKNOWN");
}
/// <summary>
@@ -205,8 +205,8 @@ public class QuestHelper(
)
)
{
_logger.Error(
_serverLocalisationService.GetText(
logger.Error(
serverLocalisationService.GetText(
"quest-unable_to_find_trader_in_profile",
questProperties.Target
)
@@ -238,8 +238,8 @@ public class QuestHelper(
)
)
{
_logger.Error(
_serverLocalisationService.GetText(
logger.Error(
serverLocalisationService.GetText(
"quest-unable_to_find_trader_in_profile",
questProperties.Target
)
@@ -278,8 +278,8 @@ public class QuestHelper(
return current == required;
default:
_logger.Error(
_serverLocalisationService.GetText(
logger.Error(
serverLocalisationService.GetText(
"quest-compare_operator_unhandled",
compareMethod
)
@@ -309,7 +309,7 @@ public class QuestHelper(
AcceptQuestRequestData acceptedQuest
)
{
var currentTimestamp = _timeUtil.GetTimeStamp();
var currentTimestamp = timeUtil.GetTimeStamp();
var existingQuest = pmcData.Quests.FirstOrDefault(q => q.QId == acceptedQuest.QuestId);
if (existingQuest is not null)
{
@@ -340,8 +340,8 @@ public class QuestHelper(
var questDbData = GetQuestFromDb(acceptedQuest.QuestId, pmcData);
if (questDbData is null)
{
_logger.Error(
_serverLocalisationService.GetText(
logger.Error(
serverLocalisationService.GetText(
"quest-unable_to_find_quest_in_db",
new { questId = acceptedQuest.QuestId, questType = acceptedQuest.Type }
)
@@ -374,12 +374,12 @@ public class QuestHelper(
/// <param name="sessionID">Session/Player id</param>
/// <returns>Quests accessible to player including newly unlocked quests now quest (startedQuestId) was started</returns>
public List<Quest> GetNewlyAccessibleQuestsWhenStartingQuest(
string startedQuestId,
string sessionID
MongoId startedQuestId,
MongoId sessionID
)
{
// Get quest acceptance data from profile
var profile = _profileHelper.GetPmcProfile(sessionID);
var profile = profileHelper.GetPmcProfile(sessionID);
var startedQuestInProfile = profile.Quests.FirstOrDefault(profileQuest =>
profileQuest.QId == startedQuestId
);
@@ -479,15 +479,15 @@ public class QuestHelper(
/// </summary>
/// <param name="questId">Quest to check</param>
/// <returns>true = show to player</returns>
public bool ShowEventQuestToPlayer(string questId)
public bool ShowEventQuestToPlayer(MongoId questId)
{
var isChristmasEventActive = _seasonalEventService.ChristmasEventEnabled();
var isHalloweenEventActive = _seasonalEventService.HalloweenEventEnabled();
var isChristmasEventActive = seasonalEventService.ChristmasEventEnabled();
var isHalloweenEventActive = seasonalEventService.HalloweenEventEnabled();
// Not christmas + quest is for christmas
if (
!isChristmasEventActive
&& _seasonalEventService.IsQuestRelatedToEvent(questId, SeasonalEventType.Christmas)
&& seasonalEventService.IsQuestRelatedToEvent(questId, SeasonalEventType.Christmas)
)
{
return false;
@@ -496,7 +496,7 @@ public class QuestHelper(
// Not halloween + quest is for halloween
if (
!isHalloweenEventActive
&& _seasonalEventService.IsQuestRelatedToEvent(questId, SeasonalEventType.Halloween)
&& seasonalEventService.IsQuestRelatedToEvent(questId, SeasonalEventType.Halloween)
)
{
return false;
@@ -505,7 +505,7 @@ public class QuestHelper(
// Should non-season event quests be shown to player
if (
!_questConfig.ShowNonSeasonalEventQuests
&& _seasonalEventService.IsQuestRelatedToEvent(questId, SeasonalEventType.None)
&& seasonalEventService.IsQuestRelatedToEvent(questId, SeasonalEventType.None)
)
{
return false;
@@ -520,7 +520,7 @@ public class QuestHelper(
/// <param name="playerSide">Player side (usec/bear)</param>
/// <param name="questId">QuestId to check</param>
/// <returns>true = quest isn't for player</returns>
public bool QuestIsForOtherSide(string playerSide, string questId)
public bool QuestIsForOtherSide(string playerSide, MongoId questId)
{
var isUsec = string.Equals(playerSide, "usec", StringComparison.OrdinalIgnoreCase);
if (isUsec && _questConfig.BearOnlyQuests.Contains(questId))
@@ -546,9 +546,9 @@ public class QuestHelper(
/// <param name="gameVersion">Game version to check against</param>
/// <param name="questId">Quest id to check</param>
/// <returns>True = Quest should not be visible to game version</returns>
protected bool QuestIsProfileBlacklisted(string gameVersion, string questId)
protected bool QuestIsProfileBlacklisted(string gameVersion, MongoId questId)
{
var questBlacklist = _questConfig.ProfileBlacklist?.GetValueOrDefault(gameVersion);
var questBlacklist = _questConfig.ProfileBlacklist.GetValueOrDefault(gameVersion);
if (questBlacklist is null)
{
// Not blacklisted
@@ -565,7 +565,7 @@ public class QuestHelper(
/// <param name="gameVersion">Game version to check against</param>
/// <param name="questId">Quest id to check</param>
/// <returns>True = Quest should be visible to game version</returns>
protected bool QuestIsProfileWhitelisted(string gameVersion, string questId)
protected bool QuestIsProfileWhitelisted(string gameVersion, MongoId questId)
{
var questBlacklist = _questConfig.ProfileBlacklist.GetValueOrDefault(gameVersion);
if (questBlacklist is null)
@@ -583,9 +583,9 @@ public class QuestHelper(
/// <param name="failedQuestId">Id of the quest failed by player</param>
/// <param name="sessionId">Session/Player id</param>
/// <returns>List of Quest</returns>
public List<Quest> FailedUnlocked(string failedQuestId, string sessionId)
public List<Quest> FailedUnlocked(MongoId failedQuestId, MongoId sessionId)
{
var profile = _profileHelper.GetPmcProfile(sessionId);
var profile = profileHelper.GetPmcProfile(sessionId);
var profileQuest = profile.Quests.FirstOrDefault(x => x.QId == failedQuestId);
var quests = GetQuestsFromDb()
@@ -626,7 +626,7 @@ public class QuestHelper(
PmcData pmcData,
MongoId itemId,
int newStackSize,
string sessionID,
MongoId sessionID,
ItemEventRouterResponse output
)
{
@@ -634,8 +634,8 @@ public class QuestHelper(
var inventoryItemIndex = pmcData.Inventory.Items.FindIndex(item => item.Id == itemId);
if (inventoryItemIndex < 0)
{
_logger.Error(
_serverLocalisationService.GetText("quest-item_not_found_in_inventory", itemId)
logger.Error(
serverLocalisationService.GetText("quest-item_not_found_in_inventory", itemId)
);
return;
@@ -644,7 +644,7 @@ public class QuestHelper(
if (newStackSize > 0)
{
var item = pmcData.Inventory.Items[inventoryItemIndex];
_itemHelper.AddUpdObjectToItem(item);
itemHelper.AddUpdObjectToItem(item);
item.Upd.StackObjectsCount = newStackSize;
@@ -680,7 +680,7 @@ public class QuestHelper(
/// <returns>Quest</returns>
public Quest RemoveQuestConditionsExceptLevel(Quest quest)
{
var updatedQuest = _cloner.Clone(quest);
var updatedQuest = cloner.Clone(quest);
updatedQuest.Conditions.AvailableForStart = updatedQuest
.Conditions.AvailableForStart.Where(q => q.ConditionType == "Level")
.ToList();
@@ -720,9 +720,9 @@ public class QuestHelper(
}
}
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"GetSellToTraderQuests found: {result.Count} quests");
logger.Debug($"GetSellToTraderQuests found: {result.Count} quests");
}
return result;
@@ -768,8 +768,8 @@ public class QuestHelper(
// Condition is in profile, but quest doesn't exist in database
if (!SellToTraderQuestConditionCache.TryGetValue(counter.SourceId, out var conditions))
{
_logger.Error(
_serverLocalisationService.GetText(
logger.Error(
serverLocalisationService.GetText(
"quest_unable_to_find_quest_in_db_no_type",
counter.SourceId
)
@@ -812,8 +812,8 @@ public class QuestHelper(
);
if (itemDetails is null)
{
_logger.Error(
_serverLocalisationService.GetText(
logger.Error(
serverLocalisationService.GetText(
"trader-unable_to_find_inventory_item_for_selltotrader_counter",
taskCounter.SourceId
)
@@ -840,15 +840,15 @@ public class QuestHelper(
public void FailQuest(
PmcData pmcData,
FailQuestRequestData failRequest,
string sessionID,
MongoId sessionID,
ItemEventRouterResponse? output = null
)
{
// Prepare response to send back to client
var updatedOutput = output ?? _eventOutputHolder.GetOutput(sessionID);
var updatedOutput = output ?? eventOutputHolder.GetOutput(sessionID);
UpdateQuestState(pmcData, QuestStatusEnum.Fail, failRequest.QuestId);
var questRewards = _questRewardHelper.ApplyQuestReward(
var questRewards = questRewardHelper.ApplyQuestReward(
pmcData,
failRequest.QuestId,
QuestStatusEnum.Fail,
@@ -869,13 +869,13 @@ public class QuestHelper(
{
if (quest.FailMessageText.Trim().Any())
{
_mailSendService.SendLocalisedNpcMessageToPlayer(
mailSendService.SendLocalisedNpcMessageToPlayer(
sessionID,
quest?.TraderId ?? matchingRepeatableQuest?.TraderId,
MessageType.QuestFail,
quest.FailMessageText,
questRewards.ToList(),
_timeUtil.GetHoursAsSeconds((int)GetMailItemRedeemTimeHoursForProfile(pmcData))
timeUtil.GetHoursAsSeconds((int)GetMailItemRedeemTimeHoursForProfile(pmcData))
);
}
}
@@ -892,7 +892,7 @@ public class QuestHelper(
/// <returns>List of Quest objects</returns>
public List<Quest> GetQuestsFromDb()
{
return _databaseService.GetQuests().Values.ToList();
return databaseService.GetQuests().Values.ToList();
}
/// <summary>
@@ -901,10 +901,10 @@ public class QuestHelper(
/// <param name="questId">Id of quest to find</param>
/// <param name="pmcData">Player profile</param>
/// <returns>Found quest</returns>
public Quest? GetQuestFromDb(string questId, PmcData pmcData)
public Quest? GetQuestFromDb(MongoId questId, PmcData pmcData)
{
// Maybe a repeatable quest?
if (_databaseService.GetQuests().TryGetValue(questId, out var quest))
if (databaseService.GetQuests().TryGetValue(questId, out var quest))
{
return quest;
}
@@ -945,7 +945,7 @@ public class QuestHelper(
/// <returns>Locale Id from locale db</returns>
public string GetQuestLocaleIdFromDb(string questMessageId)
{
var locale = _localeService.GetLocaleDb();
var locale = localeService.GetLocaleDb();
return locale.GetValueOrDefault(questMessageId, null);
}
@@ -955,14 +955,14 @@ public class QuestHelper(
/// <param name="pmcData">Profile to update</param>
/// <param name="newQuestState">New state the quest should be in</param>
/// <param name="questId">Id of the quest to alter the status of</param>
protected void UpdateQuestState(PmcData pmcData, QuestStatusEnum newQuestState, string questId)
protected void UpdateQuestState(PmcData pmcData, QuestStatusEnum newQuestState, MongoId questId)
{
// Find quest in profile, update status to desired status
var questToUpdate = pmcData.Quests.FirstOrDefault(quest => quest.QId == questId);
if (questToUpdate is not null)
{
questToUpdate.Status = newQuestState;
questToUpdate.StatusTimers[newQuestState] = _timeUtil.GetTimeStamp();
questToUpdate.StatusTimers[newQuestState] = timeUtil.GetTimeStamp();
}
}
@@ -972,12 +972,12 @@ public class QuestHelper(
/// <param name="pmcData">Profile to update</param>
/// <param name="newQuestState">New state the quest should be in</param>
/// <param name="questId">Id of the quest to alter the status of</param>
public void ResetQuestState(PmcData pmcData, QuestStatusEnum newQuestState, string questId)
public void ResetQuestState(PmcData pmcData, QuestStatusEnum newQuestState, MongoId questId)
{
var questToUpdate = pmcData.Quests?.FirstOrDefault(quest => quest.QId == questId);
if (questToUpdate is not null)
{
var currentTimestamp = _timeUtil.GetTimeStamp();
var currentTimestamp = timeUtil.GetTimeStamp();
questToUpdate.Status = newQuestState;
@@ -1022,9 +1022,9 @@ public class QuestHelper(
var questInDb = allQuests.FirstOrDefault(x => x.Id == questId);
if (questInDb is null)
{
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
logger.Debug(
$"Unable to find quest: {questId} in db, cannot get 'FindItem' condition, skipping"
);
}
@@ -1055,7 +1055,7 @@ public class QuestHelper(
public void AddAllQuestsToProfile(PmcData pmcProfile, List<QuestStatusEnum> statuses)
{
// Iterate over all quests in db
var quests = _databaseService.GetQuests();
var quests = databaseService.GetQuests();
foreach (var (key, questData) in quests)
{
// Quest from db matches quests in profile, skip
@@ -1068,13 +1068,13 @@ public class QuestHelper(
var statusesDict = new Dictionary<QuestStatusEnum, double>();
foreach (var status in statuses)
{
statusesDict.Add(status, _timeUtil.GetTimeStamp());
statusesDict.Add(status, timeUtil.GetTimeStamp());
}
var questRecordToAdd = new QuestStatus
{
QId = key,
StartTime = _timeUtil.GetTimeStamp(),
StartTime = timeUtil.GetTimeStamp(),
Status = statuses[^1], // Get last status in list as currently active status
StatusTimers = statusesDict,
CompletedConditions = [],
@@ -1102,7 +1102,7 @@ public class QuestHelper(
/// </summary>
/// <param name="questId">Id of quest to remove</param>
/// <param name="quests">Collection of quests to remove id from</param>
public void FindAndRemoveQuestFromArrayIfExists(string questId, List<QuestStatus> quests)
public void FindAndRemoveQuestFromArrayIfExists(MongoId questId, List<QuestStatus> quests)
{
quests.RemoveAll(quest => quest.QId == questId);
}
@@ -1112,7 +1112,7 @@ public class QuestHelper(
/// </summary>
/// <param name="completedQuestId">quest completed id</param>
/// <returns>Collection of Quest objects</returns>
public List<Quest> GetQuestsFailedByCompletingQuest(string completedQuestId)
public List<Quest> GetQuestsFailedByCompletingQuest(MongoId completedQuestId)
{
var questsInDb = GetQuestsFromDb();
return questsInDb
@@ -1163,29 +1163,29 @@ public class QuestHelper(
public ItemEventRouterResponse CompleteQuest(
PmcData pmcData,
CompleteQuestRequestData request,
string sessionID
MongoId sessionID
)
{
var completeQuestResponse = _eventOutputHolder.GetOutput(sessionID);
var completeQuestResponse = eventOutputHolder.GetOutput(sessionID);
if (!completeQuestResponse.ProfileChanges.TryGetValue(sessionID, out var profileChanges))
{
_logger.Error($"Unable to get profile changes for {sessionID}");
logger.Error($"Unable to get profile changes for {sessionID}");
return completeQuestResponse;
}
// Clone of players quest status prior to any changes
var preCompleteProfileQuestsClone = _cloner.Clone(pmcData.Quests);
var preCompleteProfileQuestsClone = cloner.Clone(pmcData.Quests);
// Id of quest player just completed
var completedQuestId = request.QuestId;
// Keep a copy of player quest statuses from their profile (Must be gathered prior to applyQuestReward() & failQuests())
var clientQuestsClone = _cloner.Clone(GetClientQuests(sessionID));
var clientQuestsClone = cloner.Clone(GetClientQuests(sessionID));
const QuestStatusEnum newQuestState = QuestStatusEnum.Success;
UpdateQuestState(pmcData, newQuestState, completedQuestId);
var questRewards = _questRewardHelper.ApplyQuestReward(
var questRewards = questRewardHelper.ApplyQuestReward(
pmcData,
request.QuestId,
newQuestState,
@@ -1250,13 +1250,13 @@ public class QuestHelper(
/// </summary>
/// <param name="sessionID">session/player id</param>
/// <returns>Collection of quests</returns>
public List<Quest> GetClientQuests(string sessionID)
public List<Quest> GetClientQuests(MongoId sessionID)
{
List<Quest> questsToShowPlayer = [];
var profile = _profileHelper.GetPmcProfile(sessionID);
var profile = profileHelper.GetPmcProfile(sessionID);
if (profile is null)
{
_logger.Error($"Profile {sessionID} not found, unable to return quests");
logger.Error($"Profile {sessionID} not found, unable to return quests");
return [];
}
@@ -1293,9 +1293,9 @@ public class QuestHelper(
// Player can use trader mods then remove them, leaving quests behind
if (!profile.TradersInfo.ContainsKey(quest.TraderId))
{
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
logger.Debug(
$"Unable to show quest: {quest.QuestName} as its for a trader: {quest.TraderId} that no longer exists."
);
}
@@ -1358,10 +1358,10 @@ public class QuestHelper(
out var previousQuestCompleteTime
);
var unlockTime = previousQuestCompleteTime + conditionToFulfil.AvailableAfter;
if (unlockTime > _timeUtil.GetTimeStamp())
if (unlockTime > timeUtil.GetTimeStamp())
{
_logger.Debug(
$"Quest {quest.QuestName} is locked for another: {unlockTime - _timeUtil.GetTimeStamp()} seconds"
logger.Debug(
$"Quest {quest.QuestName} is locked for another: {unlockTime - timeUtil.GetTimeStamp()} seconds"
);
}
}
@@ -1415,7 +1415,7 @@ public class QuestHelper(
/// <returns>Collection of Quest objects with the rewards filtered correctly for the game version</returns>
protected List<Quest> UpdateQuestsForGameEdition(List<Quest> quests, string gameVersion)
{
var modifiedQuests = _cloner.Clone(quests);
var modifiedQuests = cloner.Clone(quests);
foreach (var quest in modifiedQuests)
{
// Remove any reward that doesn't pass the game edition check
@@ -1428,7 +1428,7 @@ public class QuestHelper(
}
propsAsDict[rewardType.Key] = ((List<Reward>)propsAsDict[rewardType.Key])
.Where(reward => _rewardHelper.RewardIsForGameEdition(reward, gameVersion))
.Where(reward => rewardHelper.RewardIsForGameEdition(reward, gameVersion))
.ToList();
}
}
@@ -1443,7 +1443,7 @@ public class QuestHelper(
/// <param name="pmcProfile"></param>
/// <returns>Collection of Quest objects</returns>
protected List<Quest> GetQuestsFromProfileFailedByCompletingQuest(
string completedQuestId,
MongoId completedQuestId,
PmcData pmcProfile
)
{
@@ -1511,7 +1511,7 @@ public class QuestHelper(
* @param output Client output
*/
protected void FailQuests(
string sessionID,
MongoId sessionID,
PmcData pmcData,
List<Quest> questsToFail,
ItemEventRouterResponse output
@@ -1555,11 +1555,11 @@ public class QuestHelper(
statusTimers.Add(QuestStatusEnum.Fail, 0);
}
statusTimers[QuestStatusEnum.Fail] = _timeUtil.GetTimeStamp();
statusTimers[QuestStatusEnum.Fail] = timeUtil.GetTimeStamp();
var questData = new QuestStatus
{
QId = questToFail.Id,
StartTime = _timeUtil.GetTimeStamp(),
StartTime = timeUtil.GetTimeStamp(),
StatusTimers = statusTimers,
Status = QuestStatusEnum.Fail,
};
@@ -1576,21 +1576,21 @@ public class QuestHelper(
* @param questRewards Rewards given to player
*/
protected void SendSuccessDialogMessageOnQuestComplete(
string sessionID,
MongoId sessionID,
PmcData pmcData,
string completedQuestId,
MongoId completedQuestId,
List<Item> questRewards
)
{
var quest = GetQuestFromDb(completedQuestId, pmcData);
_mailSendService.SendLocalisedNpcMessageToPlayer(
mailSendService.SendLocalisedNpcMessageToPlayer(
sessionID,
quest.TraderId,
MessageType.QuestSuccess,
quest.SuccessMessageText,
questRewards,
_timeUtil.GetHoursAsSeconds((int)GetMailItemRedeemTimeHoursForProfile(pmcData))
timeUtil.GetHoursAsSeconds((int)GetMailItemRedeemTimeHoursForProfile(pmcData))
);
}
@@ -1603,7 +1603,7 @@ public class QuestHelper(
protected void AddTimeLockedQuestsToProfile(
PmcData pmcData,
List<Quest> quests,
string completedQuestId
MongoId completedQuestId
)
{
// Iterate over quests, look for quests with right criteria
@@ -1622,7 +1622,7 @@ public class QuestHelper(
{
// Now + wait time
var availableAfterTimestamp =
_timeUtil.GetTimeStamp() + nextQuestWaitCondition.AvailableAfter;
timeUtil.GetTimeStamp() + nextQuestWaitCondition.AvailableAfter;
// Update quest in profile with status of AvailableAfter
var existingQuestInProfile = pmcData.Quests.FirstOrDefault(x => x.QId == quest.Id);
@@ -1644,7 +1644,7 @@ public class QuestHelper(
Status = QuestStatusEnum.AvailableAfter,
StatusTimers = new Dictionary<QuestStatusEnum, double>
{
{ QuestStatusEnum.AvailableAfter, _timeUtil.GetTimeStamp() },
{ QuestStatusEnum.AvailableAfter, timeUtil.GetTimeStamp() },
},
AvailableAfter = availableAfterTimestamp,
}
@@ -1658,16 +1658,16 @@ public class QuestHelper(
* @param sessionId Player id
* @param questIdToRemove Qid of quest to remove
*/
protected void RemoveQuestFromScavProfile(string sessionId, string questIdToRemove)
protected void RemoveQuestFromScavProfile(MongoId sessionId, MongoId questIdToRemove)
{
var fullProfile = _profileHelper.GetFullProfile(sessionId);
var fullProfile = profileHelper.GetFullProfile(sessionId);
var repeatableInScavProfile = fullProfile.CharacterData.ScavData.Quests?.FirstOrDefault(x =>
x.QId == questIdToRemove
);
if (repeatableInScavProfile is null)
{
_logger.Warning(
_serverLocalisationService.GetText(
logger.Warning(
serverLocalisationService.GetText(
"quest-unable_to_remove_scav_quest_from_profile",
new { scavQuestId = questIdToRemove, profileId = sessionId }
)
@@ -1,6 +1,7 @@
using SPTarkov.Common.Extensions;
using SPTarkov.DI.Annotations;
using SPTarkov.Server.Core.Extensions;
using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Eft.Common;
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
using SPTarkov.Server.Core.Models.Eft.ItemEvent;
@@ -13,13 +14,13 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class QuestRewardHelper(
ISptLogger<QuestRewardHelper> _logger,
PaymentHelper _paymentHelper,
DatabaseService _databaseService,
ProfileHelper _profileHelper,
RewardHelper _rewardHelper,
ServerLocalisationService _serverLocalisationService,
ICloner _cloner
ISptLogger<QuestRewardHelper> logger,
PaymentHelper paymentHelper,
DatabaseService databaseService,
ProfileHelper profileHelper,
RewardHelper rewardHelper,
ServerLocalisationService serverLocalisationService,
ICloner cloner
)
{
/// <summary>
@@ -27,7 +28,7 @@ public class QuestRewardHelper(
/// Value can be modified by modders by overriding this value with new traders.
/// Ensure to add Lightkeeper's ID (638f541a29ffd1183d187f57) and BTR Driver's ID (656f0f98d80a697f855d34b1)
/// </summary>
protected readonly string[] InGameTraders = [Traders.LIGHTHOUSEKEEPER, Traders.BTR];
protected readonly MongoId[] InGameTraders = [Traders.LIGHTHOUSEKEEPER, Traders.BTR];
/// <summary>
/// Give player quest rewards - Skills/exp/trader standing/items/assort unlocks - Returns reward items player earned
@@ -41,19 +42,19 @@ public class QuestRewardHelper(
/// <returns>Array of reward items player was given</returns>
public IEnumerable<Item> ApplyQuestReward(
PmcData profileData,
string questId,
MongoId questId,
QuestStatusEnum state,
string sessionId,
MongoId sessionId,
ItemEventRouterResponse questResponse
)
{
// Repeatable quest base data is always in PMCProfile, `profileData` may be scav profile
// TODO: Move repeatable quest data to profile-agnostic location
var fullProfile = _profileHelper.GetFullProfile(sessionId);
var fullProfile = profileHelper.GetFullProfile(sessionId);
var pmcProfile = fullProfile.CharacterData.PmcData;
if (pmcProfile is null)
{
_logger.Error($"Unable to get pmc profile for: {sessionId}, no rewards given");
logger.Error($"Unable to get pmc profile for: {sessionId}, no rewards given");
return [];
}
@@ -61,8 +62,8 @@ public class QuestRewardHelper(
var questDetails = GetQuestFromDb(questId, pmcProfile);
if (questDetails is null)
{
_logger.Warning(
_serverLocalisationService.GetText(
logger.Warning(
serverLocalisationService.GetText(
"quest-unable_to_find_quest_in_db_no_quest_rewards",
questId
)
@@ -74,7 +75,7 @@ public class QuestRewardHelper(
if (IsInGameTrader(questDetails))
{
// Assuming in-game traders give ALL rewards
_logger.Debug(
logger.Debug(
$"Skipping quest rewards for quest: {questDetails.Id}, trader: {questDetails.TraderId} in InGameRewardTrader list"
);
@@ -89,7 +90,7 @@ public class QuestRewardHelper(
// e.g. 'Success' or 'AvailableForFinish'
var rewards = questDetails.Rewards.GetByJsonProp<List<Reward>>(state.ToString());
return _rewardHelper.ApplyRewards(
return rewardHelper.ApplyRewards(
rewards,
CustomisationSource.UNLOCKED_IN_GAME,
fullProfile,
@@ -115,10 +116,10 @@ public class QuestRewardHelper(
/// <param name="questId">Id of quest to find</param>
/// <param name="pmcData">Player profile</param>
/// <returns>IQuest object</returns>
protected Quest? GetQuestFromDb(string questId, PmcData pmcData)
protected Quest? GetQuestFromDb(MongoId questId, PmcData pmcData)
{
// Look for quest in db
if (_databaseService.GetQuests().TryGetValue(questId, out var quest))
if (databaseService.GetQuests().TryGetValue(questId, out var quest))
{
return quest;
}
@@ -170,7 +171,7 @@ public class QuestRewardHelper(
/// <returns>Updated quest</returns>
public Quest ApplyMoneyBoost(Quest quest, double bonusPercent, QuestStatusEnum questStatus)
{
var clonedQuest = _cloner.Clone(quest);
var clonedQuest = cloner.Clone(quest);
if (clonedQuest?.Rewards?.Success == null)
{
return clonedQuest;
@@ -181,7 +182,7 @@ public class QuestRewardHelper(
reward.Type == RewardType.Item
&& reward.Items != null
&& reward.Items.Count > 0
&& _paymentHelper.IsMoneyTpl(reward.Items.FirstOrDefault().Template)
&& paymentHelper.IsMoneyTpl(reward.Items.FirstOrDefault().Template)
);
foreach (var moneyReward in moneyRewards)
@@ -190,7 +191,7 @@ public class QuestRewardHelper(
var rewardItem = moneyReward.Items?.FirstOrDefault();
if (rewardItem is null)
{
_logger.Error(
logger.Error(
$"Unable to apply money reward bonus to quest: {quest.Name} as no money item found"
);
@@ -1,5 +1,6 @@
using SPTarkov.DI.Annotations;
using SPTarkov.Server.Core.Extensions;
using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
using SPTarkov.Server.Core.Models.Eft.Ragfair;
using SPTarkov.Server.Core.Models.Enums;
@@ -27,28 +28,26 @@ public class RagfairHelper(
/// </summary>
/// <param name="currencyTpl">Currency tpl</param>
/// <returns>Currency tag, e.g. RUB</returns>
public string GetCurrencyTag(string currencyTpl)
public string GetCurrencyTag(MongoId currencyTpl)
{
if (currencyTpl == Money.EUROS)
{
return "EUR";
}
else if (currencyTpl == Money.DOLLARS)
if (currencyTpl == Money.DOLLARS)
{
return "USD";
}
else if (currencyTpl == Money.ROUBLES)
if (currencyTpl == Money.ROUBLES)
{
return "RUB";
}
else if (currencyTpl == Money.GP)
if (currencyTpl == Money.GP)
{
return "GP";
}
else
{
return "";
}
return "";
}
/// <summary>
@@ -71,9 +70,9 @@ public class RagfairHelper(
}
}
public List<string> FilterCategories(string sessionId, SearchRequestData request)
public List<MongoId> FilterCategories(MongoId sessionId, SearchRequestData request)
{
var result = new List<string>();
var result = new List<MongoId>();
// Case: weapon builds
if (request.BuildCount > 0)
@@ -98,9 +97,9 @@ public class RagfairHelper(
return result;
}
public Dictionary<string, TraderAssort> GetDisplayableAssorts(string sessionId)
public Dictionary<MongoId, TraderAssort> GetDisplayableAssorts(MongoId sessionId)
{
var result = new Dictionary<string, TraderAssort>();
var result = new Dictionary<MongoId, TraderAssort>();
foreach (
var traderId in databaseService
.GetTraders()
@@ -113,12 +112,12 @@ public class RagfairHelper(
return result;
}
protected List<string> GetCategoryList(string handbookId)
protected List<MongoId> GetCategoryList(MongoId handbookId)
{
var result = new List<string>();
var result = new List<MongoId>();
// if its "mods" great-parent category, do double recursive loop
if (handbookId == "5b5f71a686f77447ed5636ab")
if (handbookId == new MongoId("5b5f71a686f77447ed5636ab"))
{
foreach (var category in handbookHelper.ChildrenCategories(handbookId))
{
@@ -19,31 +19,31 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class RagfairOfferHelper(
ISptLogger<RagfairOfferHelper> _logger,
TimeUtil _timeUtil,
BotHelper _botHelper,
RagfairSortHelper _ragfairSortHelper,
PresetHelper _presetHelper,
RagfairHelper _ragfairHelper,
PaymentHelper _paymentHelper,
TraderHelper _traderHelper,
QuestHelper _questHelper,
RagfairServerHelper _ragfairServerHelper,
ItemHelper _itemHelper,
DatabaseService _databaseService,
RagfairOfferService _ragfairOfferService,
LocaleService _localeService,
ServerLocalisationService _serverLocalisationService,
MailSendService _mailSendService,
RagfairRequiredItemsService _ragfairRequiredItemsService,
ProfileHelper _profileHelper,
EventOutputHolder _eventOutputHolder,
ConfigServer _configServer
ISptLogger<RagfairOfferHelper> logger,
TimeUtil timeUtil,
BotHelper botHelper,
RagfairSortHelper ragfairSortHelper,
PresetHelper presetHelper,
RagfairHelper ragfairHelper,
PaymentHelper paymentHelper,
TraderHelper traderHelper,
QuestHelper questHelper,
RagfairServerHelper ragfairServerHelper,
ItemHelper itemHelper,
DatabaseService databaseService,
RagfairOfferService ragfairOfferService,
LocaleService localeService,
ServerLocalisationService serverLocalisationService,
MailSendService mailSendService,
RagfairRequiredItemsService ragfairRequiredItemsService,
ProfileHelper profileHelper,
EventOutputHolder eventOutputHolder,
ConfigServer configServer
)
{
protected const string _goodSoldTemplate = "5bdabfb886f7743e152e867e 0"; // Your {soldItem} {itemCount} items were bought by {buyerNickname}.
protected readonly BotConfig _botConfig = _configServer.GetConfig<BotConfig>();
protected readonly RagfairConfig _ragfairConfig = _configServer.GetConfig<RagfairConfig>();
protected readonly BotConfig _botConfig = configServer.GetConfig<BotConfig>();
protected readonly RagfairConfig _ragfairConfig = configServer.GetConfig<RagfairConfig>();
/// <summary>
/// Pass through to ragfairOfferService.getOffers(), get flea offers a player should see
@@ -55,15 +55,15 @@ public class RagfairOfferHelper(
/// <returns>Offers the player should see</returns>
public List<RagfairOffer> GetValidOffers(
SearchRequestData searchRequest,
List<string> itemsToAdd,
Dictionary<string, TraderAssort> traderAssorts,
List<MongoId> itemsToAdd,
Dictionary<MongoId, TraderAssort> traderAssorts,
PmcData pmcData
)
{
var playerIsFleaBanned = pmcData.PlayerIsFleaBanned(_timeUtil.GetTimeStamp());
var playerIsFleaBanned = pmcData.PlayerIsFleaBanned(timeUtil.GetTimeStamp());
var tieredFlea = _ragfairConfig.TieredFlea;
var tieredFleaLimitTypes = tieredFlea.UnlocksType;
return _ragfairOfferService
return ragfairOfferService
.GetOffers()
.Where(offer =>
{
@@ -121,7 +121,7 @@ public class RagfairOfferHelper(
// Check if offer item is ammo
if (
tieredFlea.AmmoTplUnlocks is not null
&& _itemHelper.IsOfBaseclass(offerItemTpl, BaseClasses.AMMO)
&& itemHelper.IsOfBaseclass(offerItemTpl, BaseClasses.AMMO)
)
{
// Check if ammo is flagged with a level requirement
@@ -150,7 +150,7 @@ public class RagfairOfferHelper(
}
// Optimisation - Skip further checks if the item type isn't in the restricted types list
if (!_itemHelper.IsOfBaseclasses(offerItemTpl, tieredFleaLimitTypes))
if (!itemHelper.IsOfBaseclasses(offerItemTpl, tieredFleaLimitTypes))
{
return;
}
@@ -158,7 +158,7 @@ public class RagfairOfferHelper(
// Check if the item belongs to any restricted type and if player level is insufficient
if (
tieredFleaLimitTypes
.Where(tieredItemType => _itemHelper.IsOfBaseclass(offerItemTpl, tieredItemType))
.Where(tieredItemType => itemHelper.IsOfBaseclass(offerItemTpl, tieredItemType))
.Any(tieredItemType => playerLevel < tieredFlea.UnlocksType[tieredItemType])
)
{
@@ -180,7 +180,7 @@ public class RagfairOfferHelper(
)
{
// Get all offers that require the desired item and filter out offers from non traders if player below ragfair unlock
var offerIDsForItem = _ragfairRequiredItemsService.GetRequiredOffersById(
var offerIDsForItem = ragfairRequiredItemsService.GetRequiredOffersById(
searchRequest.NeededSearchId
);
@@ -190,7 +190,7 @@ public class RagfairOfferHelper(
var result = new List<RagfairOffer>();
foreach (
var offer in offerIDsForItem
.Select(_ragfairOfferService.GetOfferByOfferId)
.Select(ragfairOfferService.GetOfferByOfferId)
.Where(offer => PassesSearchFilterCriteria(searchRequest, offer, pmcData))
)
{
@@ -220,20 +220,20 @@ public class RagfairOfferHelper(
/// <returns>RagfairOffer array</returns>
public List<RagfairOffer> GetOffersForBuild(
SearchRequestData searchRequest,
List<string> itemsToAdd,
Dictionary<string, TraderAssort> traderAssorts,
List<MongoId> itemsToAdd,
Dictionary<MongoId, TraderAssort> traderAssorts,
PmcData pmcData
)
{
var offersMap = new Dictionary<string, List<RagfairOffer>>();
var offersToReturn = new List<RagfairOffer>();
var playerIsFleaBanned = pmcData.PlayerIsFleaBanned(_timeUtil.GetTimeStamp());
var playerIsFleaBanned = pmcData.PlayerIsFleaBanned(timeUtil.GetTimeStamp());
var tieredFlea = _ragfairConfig.TieredFlea;
var tieredFleaLimitTypes = tieredFlea.UnlocksType;
foreach (var desiredItemTpl in searchRequest.BuildItems)
{
var matchingOffers = _ragfairOfferService.GetOffersOfType(desiredItemTpl.Key);
var matchingOffers = ragfairOfferService.GetOffersOfType(desiredItemTpl.Key);
if (matchingOffers is null)
// No offers found for this item, skip
{
@@ -344,7 +344,7 @@ public class RagfairOfferHelper(
}
// Sort offers by price and pick the best
var offer = _ragfairSortHelper.SortOffers(offersToSort, RagfairSort.PRICE)[0];
var offer = ragfairSortHelper.SortOffers(offersToSort, RagfairSort.PRICE)[0];
offersToReturn.Add(offer);
}
@@ -363,8 +363,8 @@ public class RagfairOfferHelper(
/// <returns>True = should be shown to player</returns>
private bool IsDisplayableOffer(
SearchRequestData searchRequest,
List<string> itemsToAdd,
Dictionary<string, TraderAssort> traderAssorts,
List<MongoId> itemsToAdd,
Dictionary<MongoId, TraderAssort> traderAssorts,
RagfairOffer offer,
PmcData pmcProfile,
bool playerIsFleaBanned = false
@@ -374,7 +374,7 @@ public class RagfairOfferHelper(
// Currency offer is sold for
var moneyTypeTpl = offer.Requirements.FirstOrDefault().Template;
var isTraderOffer = _databaseService.GetTraders().ContainsKey(offer.User.Id);
var isTraderOffer = databaseService.GetTraders().ContainsKey(offer.User.Id);
if (!isTraderOffer && playerIsFleaBanned)
{
@@ -404,7 +404,7 @@ public class RagfairOfferHelper(
searchRequest.BuildItems.Count == 0
&& // Prevent equipment loadout searches filtering out presets
searchRequest.BuildCount.GetValueOrDefault(0) > 0
&& _presetHelper.HasPreset(offerRootItem.Template)
&& presetHelper.HasPreset(offerRootItem.Template)
)
{
return false;
@@ -414,7 +414,7 @@ public class RagfairOfferHelper(
// has info.removeBartering as true, this if statement removed barter items.
if (
searchRequest.RemoveBartering.GetValueOrDefault(false)
&& !_paymentHelper.IsMoneyTpl(moneyTypeTpl)
&& !paymentHelper.IsMoneyTpl(moneyTypeTpl)
)
// Don't include barter offers
{
@@ -494,7 +494,7 @@ public class RagfairOfferHelper(
{
if (!pmcProfile.TradersInfo.TryGetValue(offer.User.Id, out var userTraderSettings))
{
_logger.Warning(
logger.Warning(
$"Trader: {offer.User.Id} not found in profile, assuming offer is not locked being loyalty level"
);
return false;
@@ -512,7 +512,7 @@ public class RagfairOfferHelper(
/// <returns>true if quest locked</returns>
public bool TraderOfferItemQuestLocked(
RagfairOffer offer,
Dictionary<string, TraderAssort> traderAssorts
Dictionary<MongoId, TraderAssort> traderAssorts
)
{
var itemIds = offer.Items.Select(x => x.Id).ToHashSet();
@@ -576,16 +576,16 @@ public class RagfairOfferHelper(
/// <returns>true if restriction reached, false if no restrictions/not reached</returns>
protected bool TraderBuyRestrictionReached(RagfairOffer offer)
{
var traderAssorts = _traderHelper.GetTraderAssortsByTraderId(offer.User.Id).Items;
var traderAssorts = traderHelper.GetTraderAssortsByTraderId(offer.User.Id).Items;
// Find item being purchased from traders assorts
var assortData = traderAssorts.FirstOrDefault(item => item.Id == offer.Items[0].Id);
if (assortData is null)
{
// No trader assort data
_logger.Warning(
logger.Warning(
$"Unable to find trader: "
+ $"${offer.User.Nickname}assort for item: {_itemHelper.GetItemName(offer.Items[0].Template)} "
+ $"${offer.User.Nickname}assort for item: {itemHelper.GetItemName(offer.Items[0].Template)} "
+ $"{offer.Items[0].Template}, cannot check if buy restriction reached"
);
@@ -639,9 +639,9 @@ public class RagfairOfferHelper(
* @param sessionId Session id to process offers for
* @returns true = complete
*/
public bool ProcessOffersOnProfile(string sessionId)
public bool ProcessOffersOnProfile(MongoId sessionId)
{
var currentTimestamp = _timeUtil.GetTimeStamp();
var currentTimestamp = timeUtil.GetTimeStamp();
var profileOffers = GetProfileOffers(sessionId);
// No offers, don't do anything
@@ -691,7 +691,7 @@ public class RagfairOfferHelper(
var ratingToAdd = offer.SummaryCost / totalItemsCount * boughtAmount;
IncreaseProfileRagfairRating(
_profileHelper.GetFullProfile(sessionId),
profileHelper.GetFullProfile(sessionId),
ratingToAdd.Value
);
@@ -724,12 +724,12 @@ public class RagfairOfferHelper(
/// <param name="amountToIncrementBy">Raw amount to add to players ragfair rating (excluding the reputation gain multiplier)</param>
public void IncreaseProfileRagfairRating(SptProfile profile, double? amountToIncrementBy)
{
var ragfairGlobalsConfig = _databaseService.GetGlobals().Configuration.RagFair;
var ragfairGlobalsConfig = databaseService.GetGlobals().Configuration.RagFair;
profile.CharacterData.PmcData.RagfairInfo.IsRatingGrowing = true;
if (amountToIncrementBy is null)
{
_logger.Warning(
logger.Warning(
$"Unable to increment ragfair rating, value was not a number: {amountToIncrementBy}"
);
@@ -747,9 +747,9 @@ public class RagfairOfferHelper(
/// </summary>
/// <param name="sessionId">Session/Player id</param>
/// <returns>List of ragfair offers</returns>
protected List<RagfairOffer> GetProfileOffers(string sessionId)
protected List<RagfairOffer> GetProfileOffers(MongoId sessionId)
{
var profile = _profileHelper.GetPmcProfile(sessionId);
var profile = profileHelper.GetPmcProfile(sessionId);
if (profile.RagfairInfo?.Offers is null)
{
@@ -764,13 +764,13 @@ public class RagfairOfferHelper(
* @param sessionId Session id of profile to delete offer from
* @param offerId Id of offer to delete
*/
protected void DeleteOfferById(string sessionId, string offerId)
protected void DeleteOfferById(MongoId sessionId, string offerId)
{
var profileRagfairInfo = _profileHelper.GetPmcProfile(sessionId).RagfairInfo;
var profileRagfairInfo = profileHelper.GetPmcProfile(sessionId).RagfairInfo;
var offerIndex = profileRagfairInfo.Offers.FindIndex(o => o.Id == offerId);
if (offerIndex == -1)
{
_logger.Warning(
logger.Warning(
$"Unable to find offer: {offerId} in profile: {sessionId}, unable to delete"
);
}
@@ -781,7 +781,7 @@ public class RagfairOfferHelper(
}
// Also delete from ragfair
_ragfairOfferService.RemoveOfferById(offerId);
ragfairOfferService.RemoveOfferById(offerId);
}
/// <summary>
@@ -792,7 +792,7 @@ public class RagfairOfferHelper(
/// <param name="boughtAmount">Amount item was purchased for</param>
/// <returns>ItemEventRouterResponse</returns>
public ItemEventRouterResponse CompleteOffer(
string offerOwnerSessionId,
MongoId offerOwnerSessionId,
RagfairOffer offer,
int boughtAmount
)
@@ -809,7 +809,7 @@ public class RagfairOfferHelper(
}
// Assemble payment to send to seller now offer was purchased
var sellerProfile = _profileHelper.GetPmcProfile(offerOwnerSessionId);
var sellerProfile = profileHelper.GetPmcProfile(offerOwnerSessionId);
var rootItem = offer.Items.FirstOrDefault();
var itemTpl = rootItem.Template;
var offerStackCount = rootItem.Upd.StackObjectsCount;
@@ -824,7 +824,7 @@ public class RagfairOfferHelper(
Upd = new Upd { StackObjectsCount = requirement.Count * boughtAmount },
};
var stacks = _itemHelper.SplitStack(requestedItem);
var stacks = itemHelper.SplitStack(requestedItem);
foreach (var item in stacks)
{
var outItems = new List<Item> { item };
@@ -832,7 +832,7 @@ public class RagfairOfferHelper(
// TODO - is this code used?, may have been when adding barters to flea was still possible for player
if (requirement.OnlyFunctional.GetValueOrDefault(false))
{
var presetItems = _ragfairServerHelper.GetPresetItemsByTpl(item);
var presetItems = ragfairServerHelper.GetPresetItemsByTpl(item);
if (presetItems.Count > 0)
{
outItems.Add(presetItems[0]);
@@ -854,10 +854,10 @@ public class RagfairOfferHelper(
HandbookId = itemTpl,
};
var storageTimeSeconds = _timeUtil.GetHoursAsSeconds(
(int)_questHelper.GetMailItemRedeemTimeHoursForProfile(sellerProfile)
var storageTimeSeconds = timeUtil.GetHoursAsSeconds(
(int)questHelper.GetMailItemRedeemTimeHoursForProfile(sellerProfile)
);
_mailSendService.SendDirectNpcMessageToPlayer(
mailSendService.SendDirectNpcMessageToPlayer(
offerOwnerSessionId,
Traders.RAGMAN,
MessageType.FleamarketMessage,
@@ -872,7 +872,7 @@ public class RagfairOfferHelper(
sellerProfile.RagfairInfo.SellSum ??= 0;
sellerProfile.RagfairInfo.SellSum += offer.SummaryCost;
return _eventOutputHolder.GetOutput(offerOwnerSessionId);
return eventOutputHolder.GetOutput(offerOwnerSessionId);
}
/**
@@ -884,11 +884,11 @@ public class RagfairOfferHelper(
protected string GetLocalisedOfferSoldMessage(MongoId itemTpl, int boughtAmount)
{
// Generate a message to inform that item was sold
var globalLocales = _localeService.GetLocaleDb();
var globalLocales = localeService.GetLocaleDb();
if (!globalLocales.TryGetValue(_goodSoldTemplate, out var soldMessageLocaleGuid))
{
_logger.Error(
_serverLocalisationService.GetText(
logger.Error(
serverLocalisationService.GetText(
"ragfair-unable_to_find_locale_by_key",
_goodSoldTemplate
)
@@ -902,7 +902,7 @@ public class RagfairOfferHelper(
var tplVars = new SystemData
{
SoldItem = hasKey ? value : itemTpl,
BuyerNickname = _botHelper.GetPmcNicknameOfMaxLength(_botConfig.BotNameLengthLimit),
BuyerNickname = botHelper.GetPmcNicknameOfMaxLength(_botConfig.BotNameLengthLimit),
ItemCount = boughtAmount,
};
@@ -942,7 +942,7 @@ public class RagfairOfferHelper(
var offerMoneyTypeTpl = offer.Requirements.FirstOrDefault().Template;
if (
pmcData.Info.Level < _databaseService.GetGlobals().Configuration.RagFair.MinUserLevel
pmcData.Info.Level < databaseService.GetGlobals().Configuration.RagFair.MinUserLevel
&& isDefaultUserOffer
)
// Skip item if player is < global unlock level (default is 15) and item is from a dynamically generated source
@@ -965,7 +965,7 @@ public class RagfairOfferHelper(
if (
searchRequest.OneHourExpiration.GetValueOrDefault(false)
&& offer.EndTime - _timeUtil.GetTimeStamp() > TimeUtil.OneHourAsSeconds
&& offer.EndTime - timeUtil.GetTimeStamp() > TimeUtil.OneHourAsSeconds
)
// offer expires within an hour
{
@@ -1017,7 +1017,7 @@ public class RagfairOfferHelper(
}
else
{
var itemQualityPercent = _itemHelper.GetItemQualityModifierForItems(offer.Items) * 100;
var itemQualityPercent = itemHelper.GetItemQualityModifierForItems(offer.Items) * 100;
if (itemQualityPercent < searchRequest.ConditionFrom)
{
return false;
@@ -1029,12 +1029,12 @@ public class RagfairOfferHelper(
}
}
if (searchRequest.Currency > 0 && _paymentHelper.IsMoneyTpl(offerMoneyTypeTpl))
if (searchRequest.Currency > 0 && paymentHelper.IsMoneyTpl(offerMoneyTypeTpl))
{
// Only want offers with specific currency
if (
_ragfairHelper.GetCurrencyTag(offerMoneyTypeTpl)
!= _ragfairHelper.GetCurrencyTag(searchRequest.Currency.GetValueOrDefault(0))
ragfairHelper.GetCurrencyTag(offerMoneyTypeTpl)
!= ragfairHelper.GetCurrencyTag(searchRequest.Currency.GetValueOrDefault(0))
)
{
// Offer is for different currency to what search params allow, skip
@@ -1067,15 +1067,15 @@ public class RagfairOfferHelper(
public bool IsItemFunctional(Item offerRootItem, RagfairOffer offer)
{
// Non-preset weapons/armor are always functional
if (!_presetHelper.HasPreset(offerRootItem.Template))
if (!presetHelper.HasPreset(offerRootItem.Template))
{
return true;
}
// For armor items that can hold mods, make sure the item count is at least the amount of required plates
if (_itemHelper.ArmorItemCanHoldMods(offerRootItem.Template))
if (itemHelper.ArmorItemCanHoldMods(offerRootItem.Template))
{
var offerRootTemplate = _itemHelper.GetItem(offerRootItem.Template).Value;
var offerRootTemplate = itemHelper.GetItem(offerRootItem.Template).Value;
var requiredPlateCount = offerRootTemplate
.Properties.Slots?.Where(item => item.Required.GetValueOrDefault(false))
?.Count();
@@ -1118,7 +1118,7 @@ public class RagfairOfferHelper(
/// <returns>True if in range</returns>
protected bool ItemQualityInRange(Item item, int min, int max)
{
var itemQualityPercentage = 100 * _itemHelper.GetItemQualityModifier(item);
var itemQualityPercentage = 100 * itemHelper.GetItemQualityModifier(item);
if (min > 0 && min > itemQualityPercentage)
// Item condition too low
{
@@ -11,14 +11,14 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class RagfairSellHelper(
ISptLogger<RagfairSellHelper> _logger,
TimeUtil _timeUtil,
RandomUtil _randomUtil,
DatabaseService _databaseService,
ConfigServer _configServer
ISptLogger<RagfairSellHelper> logger,
TimeUtil timeUtil,
RandomUtil randomUtil,
DatabaseService databaseService,
ConfigServer configServer
)
{
protected readonly RagfairConfig _ragfairConfig = _configServer.GetConfig<RagfairConfig>();
protected readonly RagfairConfig _ragfairConfig = configServer.GetConfig<RagfairConfig>();
/// <summary>
/// Get the percent chance to sell an item based on its average listed price vs player chosen listing price
@@ -72,16 +72,14 @@ public class RagfairSellHelper(
bool sellInOneGo = false
)
{
var startTimestamp = _timeUtil.GetTimeStamp();
var startTimestamp = timeUtil.GetTimeStamp();
// Get a time in future to stop simulating sell chances at
var endTime =
startTimestamp
+ _timeUtil.GetHoursAsSeconds(
+ timeUtil.GetHoursAsSeconds(
(int)
_databaseService
.GetGlobals()
.Configuration.RagFair.OfferDurationTimeInHour.Value
databaseService.GetGlobals().Configuration.RagFair.OfferDurationTimeInHour.Value
);
var sellTimestamp = startTimestamp;
@@ -93,14 +91,14 @@ public class RagfairSellHelper(
if (sellChancePercent is null)
{
effectiveSellChance = _ragfairConfig.Sell.Chance.Base;
_logger.Warning(
logger.Warning(
$"Sell chance was not a number: {sellChancePercent}, defaulting to {_ragfairConfig.Sell.Chance.Base}%"
);
}
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
logger.Debug(
$"Rolling to sell: {itemSellCount} item(s) - (chance: {effectiveSellChance}%)"
);
}
@@ -113,8 +111,8 @@ public class RagfairSellHelper(
while (remainingCount > 0 && sellTimestamp < endTime)
{
var boughtAmount = sellInOneGo ? remainingCount : _randomUtil.GetInt(1, remainingCount);
if (_randomUtil.GetChance100(effectiveSellChance))
var boughtAmount = sellInOneGo ? remainingCount : randomUtil.GetInt(1, remainingCount);
if (randomUtil.GetChance100(effectiveSellChance))
{
// Passed roll check, item will be sold
// Weight time to sell towards selling faster based on how cheap the item sold
@@ -140,18 +138,18 @@ public class RagfairSellHelper(
sellTimestamp += (long)newSellTime;
result.Add(new SellResult { SellTime = sellTimestamp, Amount = boughtAmount });
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
$"Offer will sell at: {_timeUtil.GetDateTimeFromTimeStamp(sellTimestamp).ToLocalTime().ToString()}, bought: {boughtAmount}"
logger.Debug(
$"Offer will sell at: {timeUtil.GetDateTimeFromTimeStamp(sellTimestamp).ToLocalTime().ToString()}, bought: {boughtAmount}"
);
}
}
else
{
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"Offer rolled not to sell, item count: {boughtAmount}");
logger.Debug($"Offer rolled not to sell, item count: {boughtAmount}");
}
}
@@ -109,7 +109,7 @@ public class RagfairServerHelper(
* @param parentId Parent Id to check is blacklisted
* @returns true if blacklisted
*/
protected bool IsItemCategoryOnCustomFleaBlacklist(string itemParentId)
protected bool IsItemCategoryOnCustomFleaBlacklist(MongoId itemParentId)
{
return ragfairConfig.Dynamic.Blacklist.CustomItemCategoryList.Contains(itemParentId);
}
@@ -119,7 +119,7 @@ public class RagfairServerHelper(
* @param traderId
* @returns True if id was a trader
*/
public bool IsTrader(string traderId)
public bool IsTrader(MongoId traderId)
{
return databaseService.GetTraders().ContainsKey(traderId);
}
@@ -129,7 +129,7 @@ public class RagfairServerHelper(
* @param sessionID Player to send items to
* @param returnedItems Items to send to player
*/
public void ReturnItems(string sessionID, List<Item> returnedItems)
public void ReturnItems(MongoId sessionID, List<Item> returnedItems)
{
mailSendService.SendLocalisedNpcMessageToPlayer(
sessionID,
@@ -6,7 +6,7 @@ using SPTarkov.Server.Core.Services;
namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class RagfairSortHelper(LocaleService _localeService)
public class RagfairSortHelper(LocaleService localeService)
{
/**
* Sort a list of ragfair offers by something (id/rating/offer name/price/expiry time)
@@ -84,7 +84,7 @@ public class RagfairSortHelper(LocaleService _localeService)
protected int SortOffersByName(RagfairOffer a, RagfairOffer b)
{
var locale = _localeService.GetLocaleDb();
var locale = localeService.GetLocaleDb();
var tplA = a.Items[0].Template;
var tplB = b.Items[0].Template;
@@ -13,14 +13,14 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class RepairHelper(
ISptLogger<RepairHelper> _logger,
RandomUtil _randomUtil,
DatabaseService _databaseService,
ConfigServer _configServer,
ICloner _cloner
ISptLogger<RepairHelper> logger,
RandomUtil randomUtil,
DatabaseService databaseService,
ConfigServer configServer,
ICloner cloner
)
{
protected RepairConfig _repairConfig = _configServer.GetConfig<RepairConfig>();
protected RepairConfig _repairConfig = configServer.GetConfig<RepairConfig>();
/// <summary>
/// Alter an items durability after a repair by trader/repair kit
@@ -42,16 +42,16 @@ public class RepairHelper(
bool applyMaxDurabilityDegradation = true
)
{
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
logger.Debug(
$"Adding {amountToRepair} to {itemToRepairDetails.Name} using kit: {useRepairKit}"
);
}
var itemMaxDurability = _cloner.Clone(itemToRepair.Upd.Repairable.MaxDurability);
var itemCurrentDurability = _cloner.Clone(itemToRepair.Upd.Repairable.Durability);
var itemCurrentMaxDurability = _cloner.Clone(itemToRepair.Upd.Repairable.MaxDurability);
var itemMaxDurability = cloner.Clone(itemToRepair.Upd.Repairable.MaxDurability);
var itemCurrentDurability = cloner.Clone(itemToRepair.Upd.Repairable.Durability);
var itemCurrentMaxDurability = cloner.Clone(itemToRepair.Upd.Repairable.MaxDurability);
var newCurrentDurability = itemCurrentDurability + amountToRepair;
var newCurrentMaxDurability = itemCurrentMaxDurability + amountToRepair;
@@ -127,12 +127,12 @@ public class RepairHelper(
{
// Degradation value is based on the armor material
if (
!_databaseService
!databaseService
.GetGlobals()
.Configuration.ArmorMaterials.TryGetValue(material, out var armorMaterialSettings)
)
{
_logger.Error($"Unable to find armor with a type of: {material}");
logger.Error($"Unable to find armor with a type of: {material}");
}
var minMultiplier = isRepairKit
@@ -143,7 +143,7 @@ public class RepairHelper(
? armorMaterialSettings.MaxRepairKitDegradation
: armorMaterialSettings.MaxRepairDegradation;
var duraLossPercent = _randomUtil.GetDouble((double)minMultiplier, (double)maxMultiplier);
var duraLossPercent = randomUtil.GetDouble((double)minMultiplier, (double)maxMultiplier);
var duraLossMultipliedByTraderMultiplier =
duraLossPercent * armorMax * traderQualityMultiplier;
@@ -178,7 +178,7 @@ public class RepairHelper(
maxRepairDeg = itemProps.MaxRepairDegradation;
}
var duraLossPercent = _randomUtil.GetDouble((double)minRepairDeg, (double)maxRepairDeg);
var duraLossPercent = randomUtil.GetDouble((double)minRepairDeg, (double)maxRepairDeg);
var duraLossMultipliedByTraderMultiplier =
duraLossPercent * weaponMax * traderQualityMultipler;
@@ -62,7 +62,10 @@ public class RepeatableQuestHelper(
/// <param name="traderId">TraderId that should provide this quest</param>
/// <returns>Cloned quest template</returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public RepeatableQuest? GetClonedQuestTemplateForType(RepeatableQuestType type, string traderId)
public RepeatableQuest? GetClonedQuestTemplateForType(
RepeatableQuestType type,
MongoId traderId
)
{
var quest = type switch
{
@@ -109,7 +112,7 @@ public class RepeatableQuestHelper(
RepeatableQuestType type,
MongoId traderId,
PlayerGroup playerGroup,
string sessionId
MongoId sessionId
)
{
var questData = GetClonedQuestTemplateForType(type, traderId);
@@ -16,15 +16,15 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class RewardHelper(
ISptLogger<RewardHelper> _logger,
TimeUtil _timeUtil,
ItemHelper _itemHelper,
DatabaseService _databaseService,
ProfileHelper _profileHelper,
ServerLocalisationService _serverLocalisationService,
TraderHelper _traderHelper,
PresetHelper _presetHelper,
ICloner _cloner
ISptLogger<RewardHelper> logger,
TimeUtil timeUtil,
ItemHelper itemHelper,
DatabaseService databaseService,
ProfileHelper profileHelper,
ServerLocalisationService serverLocalisationService,
TraderHelper traderHelper,
PresetHelper presetHelper,
ICloner cloner
)
{
/// <summary>
@@ -42,7 +42,7 @@ public class RewardHelper(
string source,
SptProfile fullProfile,
PmcData profileData,
string rewardSourceId,
MongoId rewardSourceId,
ItemEventRouterResponse? questResponse = null
)
{
@@ -50,7 +50,7 @@ public class RewardHelper(
var pmcProfile = fullProfile?.CharacterData?.PmcData;
if (pmcProfile is null)
{
_logger.Error($"Unable to get PMC profile for: {sessionId}, no rewards given");
logger.Error($"Unable to get PMC profile for: {sessionId}, no rewards given");
return [];
}
@@ -69,27 +69,31 @@ public class RewardHelper(
{
case RewardType.Skill:
// This needs to use the passed in profileData, as it could be the scav profile
_profileHelper.AddSkillPointsToPlayer(
profileHelper.AddSkillPointsToPlayer(
profileData,
Enum.Parse<SkillTypes>(reward.Target),
reward.Value
);
break;
case RewardType.Experience:
_profileHelper.AddExperienceToPmc(
profileHelper.AddExperienceToPmc(
sessionId.Value,
int.Parse(reward.Value.ToString())
); // this must occur first as the output object needs to take the modified profile exp value
// Recalculate level in event player leveled up
pmcProfile.Info.Level = pmcProfile.CalculateLevel(
_databaseService.GetGlobals().Configuration.Exp.Level.ExperienceTable
databaseService.GetGlobals().Configuration.Exp.Level.ExperienceTable
);
break;
case RewardType.TraderStanding:
_traderHelper.AddStandingToTrader(sessionId, reward.Target, reward.Value.Value);
traderHelper.AddStandingToTrader(
sessionId.Value,
reward.Target,
reward.Value.Value
);
break;
case RewardType.TraderUnlock:
_traderHelper.SetTraderUnlockedState(reward.Target, true, sessionId);
traderHelper.SetTraderUnlockedState(reward.Target, true, sessionId.Value);
break;
case RewardType.Item:
// Item rewards are retrieved by getRewardItems() below, and returned to be handled by caller
@@ -101,34 +105,34 @@ public class RewardHelper(
AddAchievementToProfile(fullProfile, reward.Target);
break;
case RewardType.StashRows:
_profileHelper.AddStashRowsBonusToProfile(sessionId.Value, (int)reward.Value); // Add specified stash rows from reward - requires client restart
profileHelper.AddStashRowsBonusToProfile(sessionId.Value, (int)reward.Value); // Add specified stash rows from reward - requires client restart
break;
case RewardType.ProductionScheme:
FindAndAddHideoutProductionIdToProfile(
pmcProfile,
reward,
rewardSourceId,
sessionId,
sessionId.Value,
questResponse
);
break;
case RewardType.Pockets:
_profileHelper.ReplaceProfilePocketTpl(pmcProfile, reward.Target);
profileHelper.ReplaceProfilePocketTpl(pmcProfile, reward.Target);
break;
case RewardType.CustomizationDirect:
_profileHelper.AddHideoutCustomisationUnlock(fullProfile, reward, source);
profileHelper.AddHideoutCustomisationUnlock(fullProfile, reward, source);
break;
case RewardType.NotificationPopup:
// TODO: Wire up to notification system
_logger.Error("UNHANDLED: RewardType.NotificationPopup");
logger.Error("UNHANDLED: RewardType.NotificationPopup");
break;
case RewardType.WebPromoCode:
// TODO: ??? (Free arena trial from Balancing - Part 1)
_logger.Error("UNHANDLED: RewardType.WebPromoCode");
logger.Error("UNHANDLED: RewardType.WebPromoCode");
break;
default:
_logger.Error(
_serverLocalisationService.GetText(
logger.Error(
serverLocalisationService.GetText(
"reward-type_not_handled",
new { rewardType = reward.Type, questId = rewardSourceId }
)
@@ -182,16 +186,16 @@ public class RewardHelper(
protected void FindAndAddHideoutProductionIdToProfile(
PmcData pmcData,
Reward craftUnlockReward,
string questId,
string sessionID,
MongoId questId,
MongoId sessionID,
ItemEventRouterResponse response
)
{
var matchingProductions = GetRewardProductionMatch(craftUnlockReward, questId);
if (matchingProductions.Count != 1)
{
_logger.Error(
_serverLocalisationService.GetText(
logger.Error(
serverLocalisationService.GetText(
"reward-unable_to_find_matching_hideout_production",
new { questId, matchCount = matchingProductions.Count }
)
@@ -218,11 +222,11 @@ public class RewardHelper(
/// <returns>List of matching HideoutProduction objects.</returns>
public List<HideoutProduction> GetRewardProductionMatch(
Reward craftUnlockReward,
string questId
MongoId questId
)
{
// Get hideout crafts and find those that match by areatype/required level/end product tpl - hope for just one match
var craftingRecipes = _databaseService.GetHideout().Production.Recipes;
var craftingRecipes = databaseService.GetHideout().Production.Recipes;
// Area that will be used to craft unlocked item
var desiredHideoutAreaType = (HideoutAreas)int.Parse(craftUnlockReward.TraderId.ToString());
@@ -283,10 +287,10 @@ public class RewardHelper(
List<Item> mods = [];
// Is armor item that may need inserts / plates
if (reward.Items.Count == 1 && _itemHelper.ArmorItemCanHoldMods(reward.Items[0].Template))
if (reward.Items.Count == 1 && itemHelper.ArmorItemCanHoldMods(reward.Items[0].Template))
// Only process items with slots
{
if (_itemHelper.ItemHasSlots(reward.Items.FirstOrDefault().Template))
if (itemHelper.ItemHasSlots(reward.Items.FirstOrDefault().Template))
// Attempt to pull default preset from globals and add child items to reward (clones reward.items)
{
GenerateArmorRewardChildSlots(reward.Items.FirstOrDefault(), reward);
@@ -295,10 +299,10 @@ public class RewardHelper(
foreach (var rewardItem in reward.Items)
{
_itemHelper.AddUpdObjectToItem(rewardItem);
itemHelper.AddUpdObjectToItem(rewardItem);
// Reward items are granted Found in Raid status
_itemHelper.SetFoundInRaid(rewardItem);
itemHelper.SetFoundInRaid(rewardItem);
// Is root item, fix stacks
if (rewardItem.Id == reward.Target)
@@ -317,7 +321,7 @@ public class RewardHelper(
rewardItem.Upd.StackObjectsCount = 1;
}
targets = _itemHelper.SplitStack(rewardItem);
targets = itemHelper.SplitStack(rewardItem);
// splitStack created new ids for the new stacks. This would destroy the relation to possible children.
// Instead, we reset the id to preserve relations and generate a new id in the downstream loop, where we are also reparenting if required
foreach (var target in targets)
@@ -332,7 +336,7 @@ public class RewardHelper(
// Propagate FiR status into child items
{
if (
!_itemHelper.IsOfBaseclasses(
!itemHelper.IsOfBaseclasses(
rewardItem.Template,
[BaseClasses.AMMO, BaseClasses.MONEY]
)
@@ -352,19 +356,19 @@ public class RewardHelper(
foreach (var target in targets)
{
// This has all the original id relations since we reset the id to the original after the splitStack
var itemsClone = new List<Item> { _cloner.Clone(target) };
var itemsClone = new List<Item> { cloner.Clone(target) };
// Here we generate a new id for the root item
target.Id = new MongoId();
// Add cloned mods to root item array
var clonedMods = _cloner.Clone(mods);
var clonedMods = cloner.Clone(mods);
foreach (var mod in clonedMods)
{
itemsClone.Add(mod);
}
// Re-parent items + generate new ids to ensure valid ids
var itemsToAdd = _itemHelper.ReparentItemAndChildren(target, itemsClone);
var itemsToAdd = itemHelper.ReparentItemAndChildren(target, itemsClone);
rewardItems.AddRange(itemsToAdd);
}
@@ -379,11 +383,11 @@ public class RewardHelper(
protected void GenerateArmorRewardChildSlots(Item originalRewardRootItem, Reward reward)
{
// Look for a default preset from globals for armor
var defaultPreset = _presetHelper.GetDefaultPreset(originalRewardRootItem.Template);
var defaultPreset = presetHelper.GetDefaultPreset(originalRewardRootItem.Template);
if (defaultPreset is not null)
{
// Found preset, use mods to hydrate reward item
var presetAndMods = _cloner.Clone(defaultPreset.Items).ReplaceIDs().ToList();
var presetAndMods = cloner.Clone(defaultPreset.Items).ReplaceIDs().ToList();
var newRootId = presetAndMods.RemapRootItemId();
reward.Items = presetAndMods;
@@ -395,18 +399,18 @@ public class RewardHelper(
reward.Target = rootItem.Id;
// Copy over stack count otherwise reward shows as missing in client
_itemHelper.AddUpdObjectToItem(rootItem);
itemHelper.AddUpdObjectToItem(rootItem);
rootItem.Upd.StackObjectsCount = originalRewardRootItem.Upd.StackObjectsCount;
return;
}
_logger.Warning(
logger.Warning(
"Unable to find default preset for armor {originalRewardRootItem._tpl}, adding mods manually"
);
var itemDbData = _itemHelper.GetItem(originalRewardRootItem.Template).Value;
var itemDbData = itemHelper.GetItem(originalRewardRootItem.Template).Value;
// Hydrate reward with only 'required' mods - necessary for things like helmets otherwise you end up with nvgs/visors etc
reward.Items = _itemHelper.AddChildSlotItems(reward.Items, itemDbData, null, true);
reward.Items = itemHelper.AddChildSlotItems(reward.Items, itemDbData, null, true);
}
/// <summary>
@@ -415,16 +419,16 @@ public class RewardHelper(
/// </summary>
/// <param name="fullProfile">Profile to add achievement to.</param>
/// <param name="achievementId">Id of achievement to add.</param>
public void AddAchievementToProfile(SptProfile fullProfile, string achievementId)
public void AddAchievementToProfile(SptProfile fullProfile, MongoId achievementId)
{
// Add achievement id to profile with timestamp it was unlocked
fullProfile.CharacterData.PmcData.Achievements.TryAdd(
achievementId,
_timeUtil.GetTimeStamp()
timeUtil.GetTimeStamp()
);
// Check for any customisation unlocks
var achievementDataDb = _databaseService
var achievementDataDb = databaseService
.GetTemplates()
.Achievements.FirstOrDefault(achievement => achievement.Id == achievementId);
if (achievementDataDb is null)
@@ -19,19 +19,19 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class TradeHelper(
ISptLogger<TradeHelper> _logger,
TraderHelper _traderHelper,
ItemHelper _itemHelper,
QuestHelper _questHelper,
PaymentService _paymentService,
FenceService _fenceService,
ServerLocalisationService _serverLocalisationService,
HttpResponseUtil _httpResponseUtil,
InventoryHelper _inventoryHelper,
RagfairServer _ragfairServer,
TraderAssortHelper _traderAssortHelper,
TraderPurchasePersisterService _traderPurchasePersisterService,
ICloner _cloner
ISptLogger<TradeHelper> logger,
TraderHelper traderHelper,
ItemHelper itemHelper,
QuestHelper questHelper,
PaymentService paymentService,
FenceService fenceService,
ServerLocalisationService serverLocalisationService,
HttpResponseUtil httpResponseUtil,
InventoryHelper inventoryHelper,
RagfairServer ragfairServer,
TraderAssortHelper traderAssortHelper,
TraderPurchasePersisterService traderPurchasePersisterService,
ICloner cloner
)
{
protected static readonly Lock buyLock = new();
@@ -47,7 +47,7 @@ public class TradeHelper(
public void BuyItem(
PmcData pmcData,
ProcessBuyTradeRequestData buyRequestData,
string sessionID,
MongoId sessionID,
bool foundInRaid,
ItemEventRouterResponse output
)
@@ -68,7 +68,7 @@ public class TradeHelper(
// Called when player purchases PMC offer from ragfair
buyCallback = buyCount =>
{
var allOffers = _ragfairServer.GetOffers();
var allOffers = ragfairServer.GetOffers();
// We store ragfair offerId in buyRequestData.item_id
var offerWithItem = allOffers.FirstOrDefault(x =>
@@ -101,7 +101,7 @@ public class TradeHelper(
],
TraderId = buyRequestData.TransactionId,
};
_traderHelper.AddTraderPurchasesToPlayerProfile(
traderHelper.AddTraderPurchasesToPlayerProfile(
sessionID,
itemPurchaseDetails,
itemPurchased
@@ -111,8 +111,8 @@ public class TradeHelper(
// buyCallback = BuyCallback1;
// Get raw offer from ragfair, clone to prevent altering offer itself
var allOffers = _ragfairServer.GetOffers();
var offerWithItemCloned = _cloner.Clone(
var allOffers = ragfairServer.GetOffers();
var offerWithItemCloned = cloner.Clone(
allOffers.FirstOrDefault(x => x.Id == buyRequestData.ItemId)
);
offerItems = offerWithItemCloned.Items;
@@ -122,7 +122,7 @@ public class TradeHelper(
buyCallback = buyCount =>
{
// Update assort/flea item values
var traderAssorts = _traderHelper
var traderAssorts = traderHelper
.GetTraderAssortsByTraderId(buyRequestData.TransactionId)
.Items;
var itemPurchased = traderAssorts.FirstOrDefault(assort =>
@@ -132,24 +132,24 @@ public class TradeHelper(
// Decrement trader item count
itemPurchased.Upd.StackObjectsCount -= buyCount;
_fenceService.AmendOrRemoveFenceOffer(buyRequestData.ItemId, buyCount);
fenceService.AmendOrRemoveFenceOffer(buyRequestData.ItemId, buyCount);
};
var fenceItems = _fenceService.GetRawFenceAssorts().Items;
var fenceItems = fenceService.GetRawFenceAssorts().Items;
var rootItemIndex = fenceItems.FindIndex(item => item.Id == buyRequestData.ItemId);
if (rootItemIndex == -1)
{
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
logger.Debug(
$"Tried to buy item {buyRequestData.ItemId} from fence that no longer exists"
);
}
var message = _serverLocalisationService.GetText(
var message = serverLocalisationService.GetText(
"ragfair-offer_no_longer_exists"
);
_httpResponseUtil.AppendErrorToOutput(output, message);
httpResponseUtil.AppendErrorToOutput(output, message);
return;
}
@@ -161,7 +161,7 @@ public class TradeHelper(
buyCallback = buyCount =>
{
// Update assort/flea item values
var traderAssorts = _traderHelper
var traderAssorts = traderHelper
.GetTraderAssortsByTraderId(buyRequestData.TransactionId)
.Items;
var itemPurchased = traderAssorts.FirstOrDefault(item =>
@@ -208,7 +208,7 @@ public class TradeHelper(
TraderId = buyRequestData.TransactionId,
};
_traderHelper.AddTraderPurchasesToPlayerProfile(
traderHelper.AddTraderPurchasesToPlayerProfile(
sessionID,
itemPurchaseDat,
itemPurchased
@@ -217,7 +217,7 @@ public class TradeHelper(
};
// Get all trader assort items
var traderItems = _traderAssortHelper
var traderItems = traderAssortHelper
.GetAssort(sessionID, buyRequestData.TransactionId)
.Items;
@@ -225,7 +225,7 @@ public class TradeHelper(
var relevantItems = traderItems.FindAndReturnChildrenAsItems(buyRequestData.ItemId);
if (relevantItems.Count == 0)
{
_logger.Error(
logger.Error(
$"Purchased trader: {buyRequestData.TransactionId} offer: {buyRequestData.ItemId} has no items"
);
}
@@ -234,7 +234,7 @@ public class TradeHelper(
}
// Get item details from db
var itemDbDetails = _itemHelper.GetItem(offerItems.FirstOrDefault().Template).Value;
var itemDbDetails = itemHelper.GetItem(offerItems.FirstOrDefault().Template).Value;
var itemMaxStackSize = itemDbDetails.Properties.StackMaxSize;
var itemsToSendTotalCount = buyRequestData.Count;
var itemsToSendRemaining = itemsToSendTotalCount;
@@ -243,7 +243,7 @@ public class TradeHelper(
List<List<Item>> itemsToSendToPlayer = [];
while (itemsToSendRemaining > 0)
{
var offerClone = _cloner.Clone(offerItems);
var offerClone = cloner.Clone(offerItems);
// Handle stackable items that have a max stack size limit
var itemCountToSend = Math.Min(itemMaxStackSize ?? 0, itemsToSendRemaining ?? 0);
offerClone.FirstOrDefault().Upd.StackObjectsCount = itemCountToSend;
@@ -252,7 +252,7 @@ public class TradeHelper(
offerClone.RemapRootItemId();
if (offerClone.Count > 1)
{
_itemHelper.ReparentItemAndChildren(offerClone.FirstOrDefault(), offerClone);
itemHelper.ReparentItemAndChildren(offerClone.FirstOrDefault(), offerClone);
}
itemsToSendToPlayer.Add(offerClone);
@@ -271,19 +271,19 @@ public class TradeHelper(
};
// Add items + their children to stash
_inventoryHelper.AddItemsToStash(sessionID, request, pmcData, output);
inventoryHelper.AddItemsToStash(sessionID, request, pmcData, output);
if (output.Warnings?.Count > 0)
{
return;
}
/// Pay for purchase
_paymentService.PayMoney(pmcData, buyRequestData, sessionID, output);
paymentService.PayMoney(pmcData, buyRequestData, sessionID, output);
if (output.Warnings?.Count > 0)
{
var errorMessage =
$"Transaction failed: {output.Warnings.FirstOrDefault().ErrorMessage}";
_httpResponseUtil.AppendErrorToOutput(
httpResponseUtil.AppendErrorToOutput(
output,
errorMessage,
BackendErrorCodes.UnknownTradingError
@@ -304,12 +304,12 @@ public class TradeHelper(
PmcData profileWithItemsToSell,
PmcData profileToReceiveMoney,
ProcessSellTradeRequestData sellRequest,
string sessionID,
MongoId sessionID,
ItemEventRouterResponse output
)
{
// Check for and increment SoldToTrader condition counters
_questHelper.IncrementSoldToTraderCounters(
questHelper.IncrementSoldToTraderCounters(
profileWithItemsToSell,
profileToReceiveMoney,
sellRequest
@@ -329,30 +329,30 @@ public class TradeHelper(
{
var errorMessage =
$"Unable to sell item {itemToBeRemoved.Id}, cannot be found in player inventory";
_logger.Error(errorMessage);
logger.Error(errorMessage);
_httpResponseUtil.AppendErrorToOutput(output, errorMessage);
httpResponseUtil.AppendErrorToOutput(output, errorMessage);
return;
}
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
logger.Debug(
$"Selling: id: {matchingItemInInventory.Id} tpl: {matchingItemInInventory.Template}"
);
}
if (sellRequest.TransactionId == Traders.FENCE)
{
_fenceService.AddItemsToFenceAssort(
fenceService.AddItemsToFenceAssort(
profileWithItemsToSell.Inventory.Items,
matchingItemInInventory
);
}
// Remove item from inventory + any child items it has
_inventoryHelper.RemoveItem(
inventoryHelper.RemoveItem(
profileWithItemsToSell,
itemToBeRemoved.Id,
sessionID,
@@ -361,7 +361,7 @@ public class TradeHelper(
}
// Give player money for sold item(s)
_paymentService.GiveProfileMoney(
paymentService.GiveProfileMoney(
profileToReceiveMoney,
sellRequest.Price,
sellRequest,
@@ -380,20 +380,20 @@ public class TradeHelper(
/// <param name="assortId">Id of assort being purchased</param>
/// <param name="count">How many of the item are being bought</param>
protected void CheckPurchaseIsWithinTraderItemLimit(
string sessionId,
MongoId sessionId,
PmcData pmcData,
string traderId,
MongoId traderId,
Item assortBeingPurchased,
string assortId,
MongoId assortId,
double count
)
{
var traderPurchaseData = _traderPurchasePersisterService.GetProfileTraderPurchase(
var traderPurchaseData = traderPurchasePersisterService.GetProfileTraderPurchase(
sessionId,
traderId,
assortBeingPurchased.Id
);
var traderItemPurchaseLimit = _traderHelper.GetAccountTypeAdjustedTraderPurchaseLimit(
var traderItemPurchaseLimit = traderHelper.GetAccountTypeAdjustedTraderPurchaseLimit(
(double)assortBeingPurchased.Upd?.BuyRestrictionMax,
pmcData.Info.GameVersion
);
@@ -1,5 +1,6 @@
using SPTarkov.DI.Annotations;
using SPTarkov.Server.Core.Extensions;
using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
using SPTarkov.Server.Core.Models.Enums;
using SPTarkov.Server.Core.Models.Utils;
@@ -12,15 +13,15 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable(InjectionType.Singleton)]
public class TraderAssortHelper(
ISptLogger<TraderAssortHelper> _logger,
TimeUtil _timeUtil,
DatabaseService _databaseService,
ProfileHelper _profileHelper,
AssortHelper _assortHelper,
TraderPurchasePersisterService _traderPurchasePersisterService,
TraderHelper _traderHelper,
FenceService _fenceService,
ICloner _cloner
ISptLogger<TraderAssortHelper> logger,
TimeUtil timeUtil,
DatabaseService databaseService,
ProfileHelper profileHelper,
AssortHelper assortHelper,
TraderPurchasePersisterService traderPurchasePersisterService,
TraderHelper traderHelper,
FenceService fenceService,
ICloner cloner
)
{
private Dictionary<string, Dictionary<string, string>>? _mergedQuestAssorts;
@@ -38,21 +39,25 @@ public class TraderAssortHelper(
/// <param name="traderId">traders id</param>
/// <param name="showLockedAssorts">Should assorts player hasn't unlocked be returned - default false</param>
/// <returns>a traders' assorts</returns>
public TraderAssort GetAssort(string sessionId, string traderId, bool showLockedAssorts = false)
public TraderAssort GetAssort(
MongoId sessionId,
MongoId traderId,
bool showLockedAssorts = false
)
{
var traderClone = _cloner.Clone(_databaseService.GetTrader(traderId));
var fullProfile = _profileHelper.GetFullProfile(sessionId);
var traderClone = cloner.Clone(databaseService.GetTrader(traderId));
var fullProfile = profileHelper.GetFullProfile(sessionId);
var pmcProfile = fullProfile?.CharacterData?.PmcData;
if (traderId == Traders.FENCE)
{
return _fenceService.GetFenceAssorts(pmcProfile);
return fenceService.GetFenceAssorts(pmcProfile);
}
// Strip assorts player should not see yet
if (!showLockedAssorts)
{
traderClone.Assort = _assortHelper.StripLockedLoyaltyAssort(
traderClone.Assort = assortHelper.StripLockedLoyaltyAssort(
pmcProfile,
traderId,
traderClone.Assort
@@ -65,7 +70,7 @@ public class TraderAssortHelper(
traderClone.Assort.NextResupply = traderClone.Base.NextResupply;
// Adjust displayed assort counts based on values stored in profile
var assortPurchasesfromTrader = _traderPurchasePersisterService.GetProfileTraderPurchases(
var assortPurchasesfromTrader = traderPurchasePersisterService.GetProfileTraderPurchases(
sessionId,
traderId
);
@@ -76,9 +81,9 @@ public class TraderAssortHelper(
var assortToAdjust = traderClone.Assort.Items.FirstOrDefault(x => x.Id == assortId.Key);
if (assortToAdjust is null)
{
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
logger.Debug(
$"Cannot find trader: {traderClone.Base.Nickname} assort: {assortId} to adjust BuyRestrictionCurrent value, skipping"
);
}
@@ -88,9 +93,9 @@ public class TraderAssortHelper(
if (assortToAdjust.Upd is null)
{
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
logger.Debug(
$"Unable to adjust assort: {assortToAdjust.Id} item: {assortToAdjust.Template} BuyRestrictionCurrent value, assort has a null upd object"
);
}
@@ -103,7 +108,7 @@ public class TraderAssortHelper(
);
}
traderClone.Assort = _assortHelper.StripLockedQuestAssort(
traderClone.Assort = assortHelper.StripLockedQuestAssort(
pmcProfile,
traderId,
traderClone.Assort,
@@ -148,7 +153,7 @@ public class TraderAssortHelper(
var result = new Dictionary<string, Dictionary<string, string>>();
// Loop every trader
var traders = _databaseService.GetTraders();
var traders = databaseService.GetTraders();
foreach (var (_, trader) in traders)
{
if (trader?.QuestAssort is null)
@@ -188,7 +193,7 @@ public class TraderAssortHelper(
trader.Assort.Items = GetPristineTraderAssorts(trader.Base.Id);
// Update resupply value to next timestamp
trader.Base.NextResupply = (int)_traderHelper.GetNextUpdateTimestamp(trader.Base.Id);
trader.Base.NextResupply = (int)traderHelper.GetNextUpdateTimestamp(trader.Base.Id);
// Flag a refresh is needed so ragfair update() will pick it up
trader.Base.RefreshTraderRagfairOffers = true;
@@ -199,10 +204,10 @@ public class TraderAssortHelper(
/// </summary>
/// <param name="traderID">Trader to check</param>
/// <returns>true they need refreshing</returns>
public bool TraderAssortsHaveExpired(string traderID)
public bool TraderAssortsHaveExpired(MongoId traderID)
{
var time = _timeUtil.GetTimeStamp();
var trader = _databaseService.GetTables().Traders[traderID];
var time = timeUtil.GetTimeStamp();
var trader = databaseService.GetTables().Traders[traderID];
return trader.Base.NextResupply <= time;
}
@@ -212,8 +217,8 @@ public class TraderAssortHelper(
/// </summary>
/// <param name="traderId">trader id</param>
/// <returns>array of Items</returns>
protected List<Item> GetPristineTraderAssorts(string traderId)
protected List<Item> GetPristineTraderAssorts(MongoId traderId)
{
return _cloner.Clone(_traderHelper.GetTraderAssortsByTraderId(traderId).Items);
return cloner.Clone(traderHelper.GetTraderAssortsByTraderId(traderId).Items);
}
}
@@ -16,17 +16,17 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class TraderHelper(
ISptLogger<TraderHelper> _logger,
DatabaseService _databaseService,
ProfileHelper _profileHelper,
HandbookHelper _handbookHelper,
ItemHelper _itemHelper,
ServerLocalisationService _serverLocalisationService,
FenceService _fenceService,
TraderStore _traderStore,
TimeUtil _timeUtil,
RandomUtil _randomUtil,
ConfigServer _configServer
ISptLogger<TraderHelper> logger,
DatabaseService databaseService,
ProfileHelper profileHelper,
HandbookHelper handbookHelper,
ItemHelper itemHelper,
ServerLocalisationService serverLocalisationService,
FenceService fenceService,
TraderStore traderStore,
TimeUtil timeUtil,
RandomUtil randomUtil,
ConfigServer configServer
)
{
protected readonly List<string> _gameVersions =
@@ -35,11 +35,11 @@ public class TraderHelper(
GameEditions.UNHEARD,
];
protected readonly Dictionary<string, double> _highestTraderPriceItems = new();
protected readonly TraderConfig _traderConfig = _configServer.GetConfig<TraderConfig>();
protected readonly TraderConfig _traderConfig = configServer.GetConfig<TraderConfig>();
public TraderBase? GetTraderByNickName(string traderName)
{
return _databaseService
return databaseService
.GetTraders()
.Select(dict => dict.Value.Base)
.FirstOrDefault(t =>
@@ -55,18 +55,18 @@ public class TraderHelper(
/// <param name="traderID">Traders Id to get</param>
/// <param name="sessionID">Players id</param>
/// <returns>Trader base</returns>
public TraderBase? GetTrader(string traderID, string sessionID)
public TraderBase? GetTrader(string traderID, MongoId sessionID)
{
if (traderID == "ragfair")
{
return new TraderBase { Currency = CurrencyType.RUB };
}
var pmcData = _profileHelper.GetPmcProfile(sessionID);
var pmcData = profileHelper.GetPmcProfile(sessionID);
if (pmcData == null)
{
throw new Exception(
_serverLocalisationService.GetText(
serverLocalisationService.GetText(
"trader-unable_to_find_profile_with_id",
sessionID
)
@@ -81,11 +81,11 @@ public class TraderHelper(
LevelUp(traderID, pmcData);
}
var traderBase = _databaseService.GetTrader(traderID).Base;
var traderBase = databaseService.GetTrader(traderID).Base;
if (traderBase == null)
{
_logger.Error(
_serverLocalisationService.GetText("trader-unable_to_find_trader_by_id", traderID)
logger.Error(
serverLocalisationService.GetText("trader-unable_to_find_trader_by_id", traderID)
);
}
@@ -100,8 +100,8 @@ public class TraderHelper(
public TraderAssort GetTraderAssortsByTraderId(MongoId traderId)
{
return traderId == Traders.FENCE
? _fenceService.GetRawFenceAssorts()
: _databaseService.GetTrader(traderId).Assort;
? fenceService.GetRawFenceAssorts()
: databaseService.GetTrader(traderId).Assort;
}
/// <summary>
@@ -115,9 +115,9 @@ public class TraderHelper(
var traderAssorts = GetTraderAssortsByTraderId(traderId);
if (traderAssorts is null)
{
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"No assorts on trader: {traderId} found");
logger.Debug($"No assorts on trader: {traderId} found");
}
return null;
@@ -127,9 +127,9 @@ public class TraderHelper(
var purchasedAssort = traderAssorts.Items.FirstOrDefault(item => item.Id == assortId);
if (purchasedAssort is null)
{
if (_logger.IsLogEnabled(LogLevel.Debug))
if (logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"No assort {assortId} on trader: {traderId} found");
logger.Debug($"No assort {assortId} on trader: {traderId} found");
}
return null;
@@ -144,22 +144,22 @@ public class TraderHelper(
/// </summary>
/// <param name="sessionID">session id of player</param>
/// <param name="traderID">trader id to reset</param>
public void ResetTrader(string sessionID, string traderID)
public void ResetTrader(MongoId sessionID, MongoId traderID)
{
var profiles = _databaseService.GetProfileTemplates();
var trader = _databaseService.GetTrader(traderID);
var profiles = databaseService.GetProfileTemplates();
var trader = databaseService.GetTrader(traderID);
var fullProfile = _profileHelper.GetFullProfile(sessionID);
var fullProfile = profileHelper.GetFullProfile(sessionID);
if (fullProfile is null)
{
throw new Exception(
_serverLocalisationService.GetText("trader-unable_to_find_profile_by_id", sessionID)
serverLocalisationService.GetText("trader-unable_to_find_profile_by_id", sessionID)
);
}
// Get matching profile 'type' e.g. 'standard'
var pmcData = fullProfile.CharacterData.PmcData;
var matchingSide = _profileHelper.GetProfileTemplateForSide(
var matchingSide = profileHelper.GetProfileTemplateForSide(
fullProfile.ProfileInfo.Edition,
pmcData.Info.Side
);
@@ -195,7 +195,7 @@ public class TraderHelper(
)
{
// Get traders clothing
var clothing = _databaseService.GetTrader(traderID).Suits;
var clothing = databaseService.GetTrader(traderID).Suits;
if (clothing?.Count > 0)
// Force suit ids into profile
{
@@ -206,7 +206,7 @@ public class TraderHelper(
// Template has flea block
if ((profileTemplateTraderData.FleaBlockedDays ?? 0) > 0)
{
var newBanDateTime = _timeUtil.GetTimeStampFromNowDays(
var newBanDateTime = timeUtil.GetTimeStampFromNowDays(
profileTemplateTraderData.FleaBlockedDays ?? 0
);
var existingBan = pmcData.Info.Bans?.FirstOrDefault(ban =>
@@ -237,7 +237,10 @@ public class TraderHelper(
/// <param name="traderId">Trader id to get standing for</param>
/// <param name="rawProfileTemplate">Raw profile from profiles.json to look up standing from</param>
/// <returns>Standing value</returns>
protected double? GetStartingStanding(string traderId, ProfileTraderTemplate rawProfileTemplate)
protected double? GetStartingStanding(
MongoId traderId,
ProfileTraderTemplate rawProfileTemplate
)
{
if (rawProfileTemplate.InitialStanding.TryGetValue(traderId, out var standing))
{
@@ -259,13 +262,13 @@ public class TraderHelper(
/// <param name="traderId">Trader to alter</param>
/// <param name="status">New status to use</param>
/// <param name="sessionId">Session id of player</param>
public void SetTraderUnlockedState(string traderId, bool status, string sessionId)
public void SetTraderUnlockedState(MongoId traderId, bool status, MongoId sessionId)
{
var pmcData = _profileHelper.GetPmcProfile(sessionId);
var pmcData = profileHelper.GetPmcProfile(sessionId);
var profileTraderData = pmcData.TradersInfo[traderId];
if (profileTraderData is null)
{
_logger.Error(
logger.Error(
$"Unable to set trader {traderId} unlocked state to: {status} as trader cannot be found in profile"
);
@@ -281,9 +284,9 @@ public class TraderHelper(
/// <param name="sessionId">Session id of player</param>
/// <param name="traderId">Traders id to add standing to</param>
/// <param name="standingToAdd">Standing value to add to trader</param>
public void AddStandingToTrader(string sessionId, string traderId, double standingToAdd)
public void AddStandingToTrader(MongoId sessionId, MongoId traderId, double standingToAdd)
{
var fullProfile = _profileHelper.GetFullProfile(sessionId);
var fullProfile = profileHelper.GetFullProfile(sessionId);
var pmcTraderInfo = fullProfile.CharacterData.PmcData.TradersInfo[traderId];
// Add standing to trader
@@ -317,10 +320,10 @@ public class TraderHelper(
/// Iterate over a profile's traders and ensure they have the correct loyalty level for the player.
/// </summary>
/// <param name="sessionId">Profile to check.</param>
public void ValidateTraderStandingsAndPlayerLevelForProfile(string sessionId)
public void ValidateTraderStandingsAndPlayerLevelForProfile(MongoId sessionId)
{
var profile = _profileHelper.GetPmcProfile(sessionId);
var traders = _databaseService.GetTraders();
var profile = profileHelper.GetPmcProfile(sessionId);
var traders = databaseService.GetTraders();
foreach (var trader in traders)
{
LevelUp(trader.Key, profile);
@@ -333,13 +336,13 @@ public class TraderHelper(
/// </summary>
/// <param name="traderID">Trader to check standing of.</param>
/// <param name="pmcData">Profile to update trader in.</param>
public void LevelUp(string traderID, PmcData pmcData)
public void LevelUp(MongoId traderID, PmcData pmcData)
{
var loyaltyLevels = _databaseService.GetTrader(traderID).Base.LoyaltyLevels;
var loyaltyLevels = databaseService.GetTrader(traderID).Base.LoyaltyLevels;
// Level up player
pmcData.Info.Level = pmcData.CalculateLevel(
_databaseService.GetGlobals().Configuration.Exp.Level.ExperienceTable
databaseService.GetGlobals().Configuration.Exp.Level.ExperienceTable
);
// Level up traders
@@ -372,9 +375,9 @@ public class TraderHelper(
/// </summary>
/// <param name="traderID">Trader to look up update value for.</param>
/// <returns>Future timestamp.</returns>
public long GetNextUpdateTimestamp(string traderID)
public long GetNextUpdateTimestamp(MongoId traderID)
{
var time = _timeUtil.GetTimeStamp();
var time = timeUtil.GetTimeStamp();
var updateSeconds = GetTraderUpdateSeconds(traderID) ?? 0;
return time + updateSeconds;
}
@@ -384,13 +387,13 @@ public class TraderHelper(
/// </summary>
/// <param name="traderId">Trader to look up.</param>
/// <returns>Time in seconds.</returns>
public long? GetTraderUpdateSeconds(string traderId)
public long? GetTraderUpdateSeconds(MongoId traderId)
{
var traderDetails = _traderConfig.UpdateTime.FirstOrDefault(x => x.TraderId == traderId);
if (traderDetails?.Seconds?.Min is null || traderDetails.Seconds?.Max is null)
{
_logger.Warning(
_serverLocalisationService.GetText(
logger.Warning(
serverLocalisationService.GetText(
"trader-missing_trader_details_using_default_refresh_time",
new { traderId, updateTime = _traderConfig.UpdateTimeDefault }
)
@@ -411,12 +414,12 @@ public class TraderHelper(
return null;
}
return _randomUtil.GetInt(traderDetails.Seconds.Min, traderDetails.Seconds.Max);
return randomUtil.GetInt(traderDetails.Seconds.Min, traderDetails.Seconds.Max);
}
public TraderLoyaltyLevel GetLoyaltyLevel(string traderID, PmcData pmcData)
public TraderLoyaltyLevel GetLoyaltyLevel(MongoId traderID, PmcData pmcData)
{
var traderBase = _databaseService.GetTrader(traderID).Base;
var traderBase = databaseService.GetTrader(traderID).Base;
int? loyaltyLevel = null;
if (pmcData.TradersInfo.TryGetValue(traderID, out var traderInfo))
@@ -443,18 +446,18 @@ public class TraderHelper(
/// <param name="sessionID">Session id</param>
/// <param name="newPurchaseDetails">New item assort id + count</param>
public void AddTraderPurchasesToPlayerProfile(
string sessionID,
MongoId sessionID,
PurchaseDetails newPurchaseDetails,
Item itemPurchased
)
{
var profile = _profileHelper.GetFullProfile(sessionID);
var profile = profileHelper.GetFullProfile(sessionID);
var traderId = newPurchaseDetails.TraderId;
// Iterate over assorts bought and add to profile
foreach (var purchasedItem in newPurchaseDetails.Items)
{
var currentTime = _timeUtil.GetTimeStamp();
var currentTime = timeUtil.GetTimeStamp();
// Nullguard traderPurchases
profile.TraderPurchases ??=
@@ -488,7 +491,7 @@ public class TraderHelper(
)
{
throw new Exception(
_serverLocalisationService.GetText(
serverLocalisationService.GetText(
"trader-unable_to_purchase_item_limit_reached",
new { traderId, limit = itemPurchased.Upd.BuyRestrictionMax }
)
@@ -534,7 +537,7 @@ public class TraderHelper(
}
// Init dict and fill
foreach (var trader in _traderStore.GetAllTraders())
foreach (var trader in traderStore.GetAllTraders())
{
// Skip some traders
if (trader.Id == Traders.FENCE)
@@ -543,7 +546,7 @@ public class TraderHelper(
}
// Get assorts for trader, skip trader if no assorts found
var traderAssorts = _databaseService.GetTrader(trader.Id).Assort;
var traderAssorts = databaseService.GetTrader(trader.Id).Assort;
if (traderAssorts is null)
{
continue;
@@ -562,7 +565,7 @@ public class TraderHelper(
var roubleAmount =
barterScheme.Template == Money.ROUBLES
? barterScheme.Count
: _handbookHelper.InRUB(barterScheme.Count ?? 1, barterScheme.Template);
: handbookHelper.InRUB(barterScheme.Count ?? 1, barterScheme.Template);
// Existing price smaller in dict than current iteration, overwrite
if (_highestTraderPriceItems[item.Template] < roubleAmount)
@@ -584,15 +587,15 @@ public class TraderHelper(
{
// Find largest trader price for item
var highestPrice = 1d; // Default price
foreach (var trader in _traderStore.GetAllTraders())
foreach (var trader in traderStore.GetAllTraders())
{
// Get trader and check buy category allows tpl
var traderBase = _databaseService.GetTrader(trader.Id).Base;
var traderBase = databaseService.GetTrader(trader.Id).Base;
// Skip traders that don't sell this category of item
if (
traderBase is null
|| !_itemHelper.IsOfBaseclasses(tpl, traderBase.ItemsBuy.Category)
|| !itemHelper.IsOfBaseclasses(tpl, traderBase.ItemsBuy.Category)
)
{
continue;
@@ -604,8 +607,8 @@ public class TraderHelper(
var traderBuyBackPricePercent =
100 - traderBase.LoyaltyLevels.FirstOrDefault().BuyPriceCoefficient;
var itemHandbookPrice = _handbookHelper.GetTemplatePrice(tpl);
var priceTraderBuysItemAt = _randomUtil.GetPercentOfValue(
var itemHandbookPrice = handbookHelper.GetTemplatePrice(tpl);
var priceTraderBuysItemAt = randomUtil.GetPercentOfValue(
traderBuyBackPricePercent ?? 0,
itemHandbookPrice,
0
@@ -626,8 +629,8 @@ public class TraderHelper(
/// </summary>
/// <param name="traderId">Trader id</param>
/// <returns>True if a Trader exists with given ID</returns>
public bool TraderExists(string traderId)
public bool TraderExists(MongoId traderId)
{
return _traderStore.GetTraderById(traderId) != null;
return traderStore.GetTraderById(traderId) != null;
}
}
@@ -9,12 +9,12 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class WeatherHelper(
ISptLogger<WeatherHelper> _logger,
TimeUtil _timeUtil,
ConfigServer _configServer
ISptLogger<WeatherHelper> logger,
TimeUtil timeUtil,
ConfigServer configServer
)
{
protected readonly WeatherConfig _weatherConfig = _configServer.GetConfig<WeatherConfig>();
protected readonly WeatherConfig _weatherConfig = configServer.GetConfig<WeatherConfig>();
/// <summary>
/// Assumes current time
@@ -23,7 +23,7 @@ public class WeatherHelper(
/// <returns>Date object of current in-raid time</returns>
public DateTime GetInRaidTime()
{
return GetInRaidTime(_timeUtil.GetTimeStamp());
return GetInRaidTime(timeUtil.GetTimeStamp());
}
/// <summary>
@@ -34,11 +34,11 @@ public class WeatherHelper(
public DateTime GetInRaidTime(long timestamp)
{
// tarkov time = (real time * 7 % 24 hr) + 3 hour
var russiaOffsetSeconds = _timeUtil.GetHoursAsSeconds(3);
var twentyFourHoursSeconds = _timeUtil.GetHoursAsSeconds(24);
var russiaOffsetSeconds = timeUtil.GetHoursAsSeconds(3);
var twentyFourHoursSeconds = timeUtil.GetHoursAsSeconds(24);
var currentTimestampSeconds = timestamp;
var tarkovTime = _timeUtil.GetDateTimeFromTimeStamp(
var tarkovTime = timeUtil.GetDateTimeFromTimeStamp(
(long)(russiaOffsetSeconds + currentTimestampSeconds * _weatherConfig.Acceleration)
% twentyFourHoursSeconds
);
@@ -9,9 +9,9 @@ namespace SPTarkov.Server.Core.Helpers;
[Injectable]
public class WeightedRandomHelper(
ISptLogger<WeightedRandomHelper> _logger,
ISptLogger<WeightedRandomHelper> logger,
ServerLocalisationService localisationService,
RandomUtil _randomUtil
RandomUtil randomUtil
)
{
/// <summary>
@@ -51,19 +51,19 @@ public class WeightedRandomHelper(
{
if (items.Count == 0)
{
_logger.Error(localisationService.GetText("weightedrandomhelper-supplied_items_empty"));
logger.Error(localisationService.GetText("weightedrandomhelper-supplied_items_empty"));
}
if (weights.Count == 0)
{
_logger.Error(
logger.Error(
localisationService.GetText("weightedrandomhelper-supplied_weights_empty")
);
}
if (items.Count != weights.Count)
{
_logger.Error(
logger.Error(
localisationService.GetText(
"weightedrandomhelper-supplied_data_doesnt_match",
new { itemCount = items.Count, weightCount = weights.Count }
@@ -78,7 +78,7 @@ public class WeightedRandomHelper(
{
if (weights[i] < 0)
{
_logger.Warning($"Weight at index: {i} is negative ({weights[i]}), skipping");
logger.Warning($"Weight at index: {i} is negative ({weights[i]}), skipping");
continue;
}
@@ -89,12 +89,12 @@ public class WeightedRandomHelper(
if (sumOfWeights == weights.Count)
{
// Weights are all the same, early exit
var randomIndex = _randomUtil.GetInt(0, items.Count - 1);
var randomIndex = randomUtil.GetInt(0, items.Count - 1);
return new WeightedRandomResult<T> { Item = items[randomIndex], Index = randomIndex };
}
// Getting the random number in a range of [0...sum(weights)]
var randomNumber = sumOfWeights * _randomUtil.GetDouble(0, 1);
var randomNumber = sumOfWeights * randomUtil.GetDouble(0, 1);
// Picking the random item based on its weight.
for (var itemIndex = 0; itemIndex < items.Count; itemIndex++)
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
using SPTarkov.Server.Core.Models.Common;
namespace SPTarkov.Server.Core.Models.Eft.Common.Tables;
@@ -11,7 +12,7 @@ public record Achievement
public required int Index { get; set; }
[JsonPropertyName("id")]
public required string Id { get; set; }
public required MongoId Id { get; set; }
[JsonPropertyName("imageUrl")]
public required string ImageUrl { get; set; }
@@ -42,7 +42,7 @@ public record Quest
public string? Note { get; set; }
[JsonPropertyName("traderId")]
public required string TraderId { get; set; }
public required MongoId TraderId { get; set; }
[JsonPropertyName("location")]
public required string Location { get; set; }
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Enums;
using SPTarkov.Server.Core.Models.Utils;
@@ -70,7 +71,7 @@ public record SearchRequestData : IRequestData
public string? NeededSearchId { get; set; }
[JsonPropertyName("buildItems")]
public Dictionary<string, double>? BuildItems { get; set; }
public Dictionary<MongoId, double>? BuildItems { get; set; }
[JsonPropertyName("buildCount")]
public int? BuildCount { get; set; }