From ebe8f9ded582f0a1c9b3880b2bae3e969caaa3ab Mon Sep 17 00:00:00 2001 From: Jesse Date: Thu, 3 Jul 2025 16:42:16 +0200 Subject: [PATCH] Mongoid changes (#440) * Remove old IsValidMongoId and Regex * Convert more configs to MongoId, as well as BaseClasses * Remove HashUtil.Generate(), replaced with new MongoId() --- .../Callbacks/BtrDeliveryCallbacks.cs | 3 +- .../Callbacks/DialogueCallbacks.cs | 2 +- .../Controllers/InsuranceController.cs | 2 +- .../Generators/BotEquipmentModGenerator.cs | 2 +- .../Generators/BotWeaponGenerator.cs | 1 + .../Generators/LocationLootGenerator.cs | 2 +- .../Generators/LootGenerator.cs | 2 +- .../Generators/RagfairAssortGenerator.cs | 2 +- .../Generators/RagfairOfferGenerator.cs | 2 +- .../Helpers/BotWeaponGeneratorHelper.cs | 9 +- .../Helpers/CounterTrackerHelper.cs | 9 +- .../ProfileCommand/ProfileSptCommand.cs | 2 +- .../TraderCommand/TraderSptCommand.cs | 2 +- .../Helpers/InventoryHelper.cs | 13 +-- .../Helpers/ItemHelper.cs | 36 ++----- .../Helpers/NotificationSendHelper.cs | 3 +- .../Helpers/NotifierHelper.cs | 3 +- .../Helpers/PaymentHelper.cs | 5 +- .../Helpers/RagfairOfferHelper.cs | 5 +- .../Models/Common/MongoId.cs | 5 + .../Models/Eft/Dialog/ChatServer.cs | 3 +- .../Models/Eft/Hideout/HideoutProduction.cs | 2 +- .../Models/Eft/Profile/SptProfile.cs | 4 +- .../Models/Enums/Money.cs | 10 +- .../Models/Spt/Bots/GenerateWeaponRequest.cs | 4 +- .../Models/Spt/Bots/ModToSpawnRequest.cs | 2 +- .../Models/Spt/Config/AirdropConfig.cs | 4 +- .../Models/Spt/Config/BotConfig.cs | 2 +- .../Models/Spt/Config/HideoutConfig.cs | 10 +- .../Models/Spt/Config/InsuranceConfig.cs | 3 +- .../Models/Spt/Config/InventoryConfig.cs | 14 +-- .../Models/Spt/Config/LocationConfig.cs | 6 +- .../Models/Spt/Config/PlayerScavConfig.cs | 3 +- .../Models/Spt/Config/RagfairConfig.cs | 26 ++--- .../Models/Spt/Config/ScavCaseConfig.cs | 6 +- .../Models/Spt/Config/SeasonalEventConfig.cs | 7 +- .../Models/Spt/Config/TraderConfig.cs | 12 +-- .../Models/Spt/Services/LootRequest.cs | 2 +- .../Servers/RagfairServer.cs | 2 +- .../Services/BotEquipmentFilterService.cs | 3 +- .../Services/BtrDeliveryService.cs | 3 +- .../Services/DatabaseService.cs | 5 +- .../Services/FenceService.cs | 12 +-- .../Services/ItemBaseClassService.cs | 17 ++-- .../Services/LocationLifecycleService.cs | 4 +- .../Services/MailSendService.cs | 9 +- .../Services/Mod/CustomItemService.cs | 4 +- .../Services/RagfairLinkedItemService.cs | 7 +- .../Services/RagfairOfferService.cs | 3 +- .../Services/SeasonalEventService.cs | 4 +- .../SPTarkov.Server.Core/Utils/HashUtil.cs | 45 --------- .../Utils/RagfairOfferHolder.cs | 5 +- UnitTests/Tests/Utils/HashUtilTests.cs | 97 ------------------- 53 files changed, 159 insertions(+), 291 deletions(-) delete mode 100644 UnitTests/Tests/Utils/HashUtilTests.cs diff --git a/Libraries/SPTarkov.Server.Core/Callbacks/BtrDeliveryCallbacks.cs b/Libraries/SPTarkov.Server.Core/Callbacks/BtrDeliveryCallbacks.cs index 95c53e26..a37d6313 100644 --- a/Libraries/SPTarkov.Server.Core/Callbacks/BtrDeliveryCallbacks.cs +++ b/Libraries/SPTarkov.Server.Core/Callbacks/BtrDeliveryCallbacks.cs @@ -1,6 +1,7 @@ using SPTarkov.DI.Annotations; using SPTarkov.Server.Core.DI; using SPTarkov.Server.Core.Extensions; +using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Eft.Profile; using SPTarkov.Server.Core.Models.Spt.Config; using SPTarkov.Server.Core.Models.Utils; @@ -110,7 +111,7 @@ public class BtrDeliveryCallbacks( foreach (var package in packagesToBeDelivered) { // Create a new root parent ID for the message we'll be sending the player - var rootItemParentId = _hashUtil.Generate(); + var rootItemParentId = new MongoId(); // Update the delivery items to have the new root parent ID for root/orphaned items package.Items = package.Items.AdoptOrphanedItems(rootItemParentId); diff --git a/Libraries/SPTarkov.Server.Core/Callbacks/DialogueCallbacks.cs b/Libraries/SPTarkov.Server.Core/Callbacks/DialogueCallbacks.cs index 3beb3c93..c04db30e 100644 --- a/Libraries/SPTarkov.Server.Core/Callbacks/DialogueCallbacks.cs +++ b/Libraries/SPTarkov.Server.Core/Callbacks/DialogueCallbacks.cs @@ -47,7 +47,7 @@ public class DialogueCallbacks( { new() { - Id = _hashUtil.Generate(), + Id = new Models.Common.MongoId(), RegistrationId = 20, DateTime = _timeUtil.GetTimeStamp(), IsDeveloper = true, diff --git a/Libraries/SPTarkov.Server.Core/Controllers/InsuranceController.cs b/Libraries/SPTarkov.Server.Core/Controllers/InsuranceController.cs index 204e7247..82781913 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/InsuranceController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/InsuranceController.cs @@ -122,7 +122,7 @@ public class InsuranceController( foreach (var insured in insuranceDetails) { // Create a new root parent ID for the message we'll be sending the player - var rootItemParentId = _hashUtil.Generate(); + var rootItemParentId = new MongoId(); // Update the insured items to have the new root parent ID for root/orphaned items insured.Items = insured.Items.AdoptOrphanedItems(rootItemParentId); diff --git a/Libraries/SPTarkov.Server.Core/Generators/BotEquipmentModGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/BotEquipmentModGenerator.cs index af052233..ef2854e9 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/BotEquipmentModGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/BotEquipmentModGenerator.cs @@ -2064,7 +2064,7 @@ public class BotEquipmentModGenerator( public HashSet FilterSightsByWeaponType( Item weapon, HashSet scopes, - Dictionary> botWeaponSightWhitelist + Dictionary> botWeaponSightWhitelist ) { var weaponDetails = _itemHelper.GetItem(weapon.Template); diff --git a/Libraries/SPTarkov.Server.Core/Generators/BotWeaponGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/BotWeaponGenerator.cs index 1e6d2cb4..13926038 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/BotWeaponGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/BotWeaponGenerator.cs @@ -794,6 +794,7 @@ public class BotWeaponGenerator( var magazineTemplate = _itemHelper.GetItem( magazineSlot.Props?.Filters.FirstOrDefault()?.Filter?.FirstOrDefault() + ?? new MongoId(null) ); if (!magazineTemplate.Key) { diff --git a/Libraries/SPTarkov.Server.Core/Generators/LocationLootGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/LocationLootGenerator.cs index 7cb0a325..eaae244d 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/LocationLootGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/LocationLootGenerator.cs @@ -542,7 +542,7 @@ public class LocationLootGenerator( var containerTpl = containerClone.Template.Items.FirstOrDefault().Template; // Create new unique parent id to prevent any collisions - var parentId = _hashUtil.Generate(); + var parentId = new MongoId(); containerClone.Template.Root = parentId; containerClone.Template.Items.FirstOrDefault().Id = parentId; diff --git a/Libraries/SPTarkov.Server.Core/Generators/LootGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/LootGenerator.cs index 8edc277e..d795b9f2 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/LootGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/LootGenerator.cs @@ -180,7 +180,7 @@ public class LootGenerator( /// /// Dictionary of item tpls with minmax values /// Array of Item - public List> CreateForcedLoot(Dictionary> forcedLootToAdd) + public List> CreateForcedLoot(Dictionary> forcedLootToAdd) { var result = new List>(); diff --git a/Libraries/SPTarkov.Server.Core/Generators/RagfairAssortGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/RagfairAssortGenerator.cs index 05215169..36b784bb 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/RagfairAssortGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/RagfairAssortGenerator.cs @@ -22,7 +22,7 @@ public class RagfairAssortGenerator( { protected readonly RagfairConfig RagfairConfig = configServer.GetConfig(); - protected readonly List RagfairItemInvalidBaseTypes = + protected readonly List RagfairItemInvalidBaseTypes = [ BaseClasses.LOOT_CONTAINER, // Safe, barrel cache etc BaseClasses.STASH, // Player inventory stash diff --git a/Libraries/SPTarkov.Server.Core/Generators/RagfairOfferGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/RagfairOfferGenerator.cs index 2dbb1749..14b47c0b 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/RagfairOfferGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/RagfairOfferGenerator.cs @@ -149,7 +149,7 @@ public class RagfairOfferGenerator( var offer = new RagfairOffer { - Id = hashUtil.Generate(), + Id = new MongoId(), InternalId = offerCounter, User = CreateUserDataForFleaOffer(userId, ragfairServerHelper.IsTrader(userId)), Root = rootItem.Id, diff --git a/Libraries/SPTarkov.Server.Core/Helpers/BotWeaponGeneratorHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/BotWeaponGeneratorHelper.cs index 4f9287b8..0a74bb08 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/BotWeaponGeneratorHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/BotWeaponGeneratorHelper.cs @@ -34,10 +34,11 @@ public class BotWeaponGeneratorHelper( double? chamberBulletCount = 0; if (MagazineIsCylinderRelated(parentItem.Name)) { - var firstSlotAmmoTpl = magTemplate - .Properties.Cartridges.FirstOrDefault() - ?.Props.Filters[0] - .Filter.FirstOrDefault(); + var firstSlotAmmoTpl = + magTemplate + .Properties.Cartridges.FirstOrDefault() + ?.Props.Filters[0] + .Filter.FirstOrDefault() ?? new MongoId(null); var ammoMaxStackSize = _itemHelper.GetItem(firstSlotAmmoTpl).Value?.Properties?.StackMaxSize ?? 1; chamberBulletCount = diff --git a/Libraries/SPTarkov.Server.Core/Helpers/CounterTrackerHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/CounterTrackerHelper.cs index 955cd7d3..470cc767 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/CounterTrackerHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/CounterTrackerHelper.cs @@ -1,18 +1,19 @@ using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Models.Common; namespace SPTarkov.Server.Core.Helpers { [Injectable] public class CounterTrackerHelper { - private Dictionary _maxCounts = new(); - private readonly Dictionary _trackedCounts = new(); + private Dictionary _maxCounts = new(); + private readonly Dictionary _trackedCounts = new(); /// /// Add dictionary of keys and their matching limits to track /// /// Values to store - public void AddDataToTrack(Dictionary maxCounts) + public void AddDataToTrack(Dictionary maxCounts) { _maxCounts = maxCounts; } @@ -23,7 +24,7 @@ namespace SPTarkov.Server.Core.Helpers /// /// /// True = above max count - public bool IncrementCount(string key, int countToIncrementBy = 1) + public bool IncrementCount(MongoId key, int countToIncrementBy = 1) { // Not tracked, skip if (!_maxCounts.Any() || !_maxCounts.ContainsKey(key)) diff --git a/Libraries/SPTarkov.Server.Core/Helpers/Dialogue/Commando/SptCommands/ProfileCommand/ProfileSptCommand.cs b/Libraries/SPTarkov.Server.Core/Helpers/Dialogue/Commando/SptCommands/ProfileCommand/ProfileSptCommand.cs index b81eeef2..7d219ffd 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/Dialogue/Commando/SptCommands/ProfileCommand/ProfileSptCommand.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/Dialogue/Commando/SptCommands/ProfileCommand/ProfileSptCommand.cs @@ -143,7 +143,7 @@ public class ProfileSptCommand( Id = new MongoId(), Template = Money.ROUBLES, Upd = new Upd { StackObjectsCount = 1 }, - ParentId = _hashUtil.Generate(), + ParentId = new MongoId(), SlotId = "main", }, ], diff --git a/Libraries/SPTarkov.Server.Core/Helpers/Dialogue/Commando/SptCommands/TraderCommand/TraderSptCommand.cs b/Libraries/SPTarkov.Server.Core/Helpers/Dialogue/Commando/SptCommands/TraderCommand/TraderSptCommand.cs index 5d5c8c8c..f1976851 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/Dialogue/Commando/SptCommands/TraderCommand/TraderSptCommand.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/Dialogue/Commando/SptCommands/TraderCommand/TraderSptCommand.cs @@ -111,7 +111,7 @@ public class TraderSptCommand( Id = new MongoId(), Template = Money.ROUBLES, Upd = new Upd { StackObjectsCount = 1 }, - ParentId = _hashUtil.Generate(), + ParentId = new MongoId(), SlotId = "main", }, ], diff --git a/Libraries/SPTarkov.Server.Core/Helpers/InventoryHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/InventoryHelper.cs index c172cdeb..c1fe39b2 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/InventoryHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/InventoryHelper.cs @@ -4,6 +4,7 @@ using System.Text.Json.Serialization; 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.Inventory; @@ -36,7 +37,7 @@ public class InventoryHelper( ICloner _cloner ) { - private static readonly FrozenSet _variableSizeItemTypes = + private static readonly FrozenSet _variableSizeItemTypes = [ BaseClasses.WEAPON, BaseClasses.FUNCTIONAL_MOD, @@ -962,8 +963,8 @@ public class InventoryHelper( { var inventoryItemHash = new InventoryItemHash { - ByItemId = new Dictionary(), - ByParentId = new Dictionary>(), + ByItemId = new Dictionary(), + ByParentId = new Dictionary>(), }; foreach (var item in inventoryItems) { @@ -1367,7 +1368,7 @@ public class InventoryHelper( public void ValidateInventoryUsesMongoIds(List itemsToValidate) { var errors = itemsToValidate - .Where(item => !_hashUtil.IsValidMongoId(item.Id)) + .Where(item => !item.Id.IsValidMongoId()) .Select(item => $"Id: {item.Id} - tpl: {item.Template}") .ToList(); foreach (var message in errors) @@ -1411,8 +1412,8 @@ public class InventoryHelper( public class InventoryItemHash { [JsonPropertyName("byItemId")] - public Dictionary ByItemId { get; set; } + public Dictionary ByItemId { get; set; } [JsonPropertyName("byParentId")] - public Dictionary> ByParentId { get; set; } + public Dictionary> ByParentId { get; set; } } diff --git a/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs index ed998e15..07e72355 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs @@ -28,7 +28,7 @@ public class ItemHelper( ICloner _cloner ) { - protected static readonly FrozenSet _defaultInvalidBaseTypes = + protected static readonly FrozenSet _defaultInvalidBaseTypes = [ BaseClasses.LOOT_CONTAINER, BaseClasses.MOB_CONTAINER, @@ -97,7 +97,7 @@ public class ItemHelper( "right_side_plate", ]; - protected static readonly FrozenSet _armorSlotsThatCanHoldMods = + protected static readonly FrozenSet _armorSlotsThatCanHoldMods = [ BaseClasses.HEADWEAR, BaseClasses.VEST, @@ -283,7 +283,7 @@ public class ItemHelper( /// Template id to check /// OPTIONAL - Base types deemed invalid /// true for items that may be in player possession and not quest items - public bool IsValidItem(string tpl, ICollection? invalidBaseTypes = null) + public bool IsValidItem(MongoId tpl, ICollection? invalidBaseTypes = null) { var baseTypes = invalidBaseTypes ?? _defaultInvalidBaseTypes; var itemDetails = GetItem(tpl); @@ -306,7 +306,7 @@ public class ItemHelper( /// Item template id to check /// Baseclass to check for /// is the tpl a descendant - public bool IsOfBaseclass(MongoId tpl, string baseClassTpl) + public bool IsOfBaseclass(MongoId tpl, MongoId baseClassTpl) { return _itemBaseClassService.ItemHasBaseClass(tpl, [baseClassTpl]); } @@ -317,29 +317,11 @@ public class ItemHelper( /// Item to check base classes of /// Base classes to check for /// True if any supplied base classes match - public bool IsOfBaseclasses(string tpl, ICollection baseClassTpls) + public bool IsOfBaseclasses(MongoId tpl, ICollection baseClassTpls) { return _itemBaseClassService.ItemHasBaseClass(tpl, baseClassTpls); } - /// - /// Temporary until we have better MongoId handling - /// - /// - /// - /// - public bool IsOfBaseclasses(string tpl, ICollection baseClassTpls) - { - List MongoList = []; - - foreach (var baseTpl in baseClassTpls) - { - MongoList.Add(baseTpl); - } - - return _itemBaseClassService.ItemHasBaseClass(tpl, MongoList); - } - /// /// Does the provided item have the chance to require soft armor inserts /// Only applies to helmets/vest/armors @@ -347,7 +329,7 @@ public class ItemHelper( /// /// Tpl to check /// Does item have the possibility ot need soft inserts - public bool ArmorItemCanHoldMods(string itemTpl) + public bool ArmorItemCanHoldMods(MongoId itemTpl) { return IsOfBaseclasses(itemTpl, _armorSlotsThatCanHoldMods); } @@ -526,7 +508,7 @@ public class ItemHelper( /// /// template id to look up /// KvP, key = bool, value = template item object - public KeyValuePair GetItem(string itemTpl) + public KeyValuePair GetItem(MongoId itemTpl) { // -> Gets item from if (_databaseService.GetItems().TryGetValue(itemTpl, out var item)) @@ -542,7 +524,7 @@ public class ItemHelper( /// /// Template id of the item to check /// True if the item has slots - public bool ItemHasSlots(string itemTpl) + public bool ItemHasSlots(MongoId itemTpl) { if (_databaseService.GetItems().TryGetValue(itemTpl, out var item)) { @@ -1347,7 +1329,7 @@ public class ItemHelper( /// ItemSize object (width and height) public ItemSize GetItemSize(ICollection items, MongoId rootItemId) { - var rootTemplate = GetItem(items.FirstOrDefault(x => x.Id == rootItemId)?.Template).Value; + var rootTemplate = GetItem(items.FirstOrDefault(x => x.Id == rootItemId).Template).Value; var width = rootTemplate.Properties.Width; var height = rootTemplate.Properties.Height; diff --git a/Libraries/SPTarkov.Server.Core/Helpers/NotificationSendHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/NotificationSendHelper.cs index f2ecf9ca..d584b4c2 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/NotificationSendHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/NotificationSendHelper.cs @@ -1,4 +1,5 @@ using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Eft.Profile; using SPTarkov.Server.Core.Models.Eft.Ws; using SPTarkov.Server.Core.Models.Enums; @@ -76,7 +77,7 @@ public class NotificationSendHelper( dialog.New += 1; var message = new Message { - Id = _hashUtil.Generate(), + Id = new MongoId(), UserId = dialog.Id, MessageType = messageType, DateTime = _timeUtil.GetTimeStamp(), diff --git a/Libraries/SPTarkov.Server.Core/Helpers/NotifierHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/NotifierHelper.cs index 6c208a8e..ee05a8dd 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/NotifierHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/NotifierHelper.cs @@ -1,4 +1,5 @@ using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Eft.Profile; using SPTarkov.Server.Core.Models.Eft.Ws; using SPTarkov.Server.Core.Utils; @@ -57,7 +58,7 @@ public class NotifierHelper(HttpServerHelper httpServerHelper, HashUtil hashUtil return new WsRagfairNewRating { EventType = NotificationEventType.RagfairNewRating, - EventIdentifier = hashUtil.Generate(), + EventIdentifier = new MongoId(), Rating = rating, IsRatingGrowing = isGrowing, }; diff --git a/Libraries/SPTarkov.Server.Core/Helpers/PaymentHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/PaymentHelper.cs index 100d24b8..8749a378 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/PaymentHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/PaymentHelper.cs @@ -1,4 +1,5 @@ using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Enums; using SPTarkov.Server.Core.Models.Spt.Config; using SPTarkov.Server.Core.Servers; @@ -10,7 +11,7 @@ public class PaymentHelper(ConfigServer configServer) { protected bool _addedCustomMoney; protected readonly InventoryConfig _inventoryConfig = configServer.GetConfig(); - protected readonly HashSet _moneyTpls = + protected readonly HashSet _moneyTpls = [ Money.DOLLARS, Money.EUROS, @@ -23,7 +24,7 @@ public class PaymentHelper(ConfigServer configServer) /// /// Item Tpl to check /// - public bool IsMoneyTpl(string tpl) + public bool IsMoneyTpl(MongoId tpl) { // Add custom currency first time this method is accessed if (!_addedCustomMoney) diff --git a/Libraries/SPTarkov.Server.Core/Helpers/RagfairOfferHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/RagfairOfferHelper.cs index 5eaa3b43..9ce238bb 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/RagfairOfferHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/RagfairOfferHelper.cs @@ -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; @@ -112,7 +113,7 @@ public class RagfairOfferHelper( protected void CheckAndLockOfferFromPlayerTieredFlea( TieredFlea tieredFlea, RagfairOffer offer, - List tieredFleaLimitTypes, + List tieredFleaLimitTypes, int playerLevel ) { @@ -819,7 +820,7 @@ public class RagfairOfferHelper( // Create an item template item var requestedItem = new Item { - Id = _hashUtil.Generate(), + Id = new MongoId(), Template = requirement.Template, Upd = new Upd { StackObjectsCount = requirement.Count * boughtAmount }, }; diff --git a/Libraries/SPTarkov.Server.Core/Models/Common/MongoId.cs b/Libraries/SPTarkov.Server.Core/Models/Common/MongoId.cs index 6f7af548..d8447c63 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Common/MongoId.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Common/MongoId.cs @@ -23,6 +23,11 @@ public readonly struct MongoId : IEquatable return; } + if (id == "hideout") + { + throw new Exception("wtf"); + } + if (id.Length != 24) { // TODO: Items.json root item has an empty parentId property diff --git a/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/ChatServer.cs b/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/ChatServer.cs index 87d1b105..51f3a3db 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/ChatServer.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Eft/Dialog/ChatServer.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using SPTarkov.Server.Core.Models.Common; namespace SPTarkov.Server.Core.Models.Eft.Dialog; @@ -8,7 +9,7 @@ public record ChatServer public Dictionary? ExtensionData { get; set; } [JsonPropertyName("_id")] - public string? Id { get; set; } + public MongoId Id { get; set; } [JsonPropertyName("RegistrationId")] public int? RegistrationId { get; set; } diff --git a/Libraries/SPTarkov.Server.Core/Models/Eft/Hideout/HideoutProduction.cs b/Libraries/SPTarkov.Server.Core/Models/Eft/Hideout/HideoutProduction.cs index a820f963..a1dc8757 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Eft/Hideout/HideoutProduction.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Eft/Hideout/HideoutProduction.cs @@ -70,7 +70,7 @@ public record Requirement public Dictionary? ExtensionData { get; set; } [JsonPropertyName("templateId")] - public string? TemplateId { get; set; } + public MongoId TemplateId { get; set; } [JsonPropertyName("count")] public int? Count { get; set; } diff --git a/Libraries/SPTarkov.Server.Core/Models/Eft/Profile/SptProfile.cs b/Libraries/SPTarkov.Server.Core/Models/Eft/Profile/SptProfile.cs index dd8f9844..ecfd3061 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Eft/Profile/SptProfile.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Eft/Profile/SptProfile.cs @@ -458,10 +458,10 @@ public record AcceptedCultistReward public long? Timestamp { get; set; } [JsonPropertyName("sacrificeItems")] - public List? SacrificeItems { get; set; } + public List? SacrificeItems { get; set; } [JsonPropertyName("rewardItems")] - public List? RewardItems { get; set; } + public List? RewardItems { get; set; } } public record PendingPrestige diff --git a/Libraries/SPTarkov.Server.Core/Models/Enums/Money.cs b/Libraries/SPTarkov.Server.Core/Models/Enums/Money.cs index a8c9ca5e..573dd584 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Enums/Money.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Enums/Money.cs @@ -8,12 +8,12 @@ public record Money [JsonExtensionData] public Dictionary? ExtensionData { get; set; } - public static readonly MongoId ROUBLES = new MongoId("5449016a4bdc2d6f028b456f"); - public static readonly MongoId EUROS = new MongoId("569668774bdc2da2298b4568"); - public static readonly MongoId DOLLARS = new MongoId("5696686a4bdc2da3298b456a"); - public static readonly MongoId GP = new MongoId("5d235b4d86f7742e017bc88a"); + public static readonly MongoId ROUBLES = new("5449016a4bdc2d6f028b456f"); + public static readonly MongoId EUROS = new("569668774bdc2da2298b4568"); + public static readonly MongoId DOLLARS = new("5696686a4bdc2da3298b456a"); + public static readonly MongoId GP = new("5d235b4d86f7742e017bc88a"); - public static HashSet GetMoneyTpls() + public static HashSet GetMoneyTpls() { return [ROUBLES, EUROS, DOLLARS, GP]; } diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Bots/GenerateWeaponRequest.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Bots/GenerateWeaponRequest.cs index 69250bb3..5d084826 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Bots/GenerateWeaponRequest.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Bots/GenerateWeaponRequest.cs @@ -121,7 +121,7 @@ public record BotModLimits public int? ScopeMax { get; set; } [JsonPropertyName("scopeBaseTypes")] - public List? ScopeBaseTypes { get; set; } + public List? ScopeBaseTypes { get; set; } [JsonPropertyName("flashlightLaser")] public ItemCount? FlashlightLaser { get; set; } @@ -130,7 +130,7 @@ public record BotModLimits public int? FlashlightLaserMax { get; set; } [JsonPropertyName("flashlightLaserBaseTypes")] - public List? FlashlightLaserBaseTypes { get; set; } + public List? FlashlightLaserBaseTypes { get; set; } } public record ItemCount diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Bots/ModToSpawnRequest.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Bots/ModToSpawnRequest.cs index 36d3a226..3e8e6525 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Bots/ModToSpawnRequest.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Bots/ModToSpawnRequest.cs @@ -30,7 +30,7 @@ public record ModToSpawnRequest /// Parent slot the item will be a part of /// [JsonPropertyName("botWeaponSightWhitelist")] - public Dictionary>? BotWeaponSightWhitelist { get; set; } + public Dictionary>? BotWeaponSightWhitelist { get; set; } /// /// Blacklist to prevent mods from being picked diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/AirdropConfig.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/AirdropConfig.cs index c2d31c30..38e4ce2f 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/AirdropConfig.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/AirdropConfig.cs @@ -19,7 +19,7 @@ public record AirdropConfig : BaseConfig public required Dictionary Loot { get; set; } [JsonPropertyName("customAirdropMapping")] - public required Dictionary CustomAirdropMapping { get; set; } + public required Dictionary CustomAirdropMapping { get; set; } } /// @@ -98,7 +98,7 @@ public record AirdropLoot public bool UseForcedLoot { get; set; } [JsonPropertyName("forcedLoot")] - public Dictionary>? ForcedLoot { get; set; } + public Dictionary>? ForcedLoot { get; set; } [JsonPropertyName("useRewardItemBlacklist")] public bool UseRewardItemBlacklist { get; set; } diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/BotConfig.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/BotConfig.cs index 8a3bb8e5..cb3be53b 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/BotConfig.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/BotConfig.cs @@ -355,7 +355,7 @@ public record EquipmentFilters /// Whitelist for weapon sight types allowed per gun /// [JsonPropertyName("weaponSightWhitelist")] - public Dictionary> WeaponSightWhitelist { get; set; } + public Dictionary> WeaponSightWhitelist { get; set; } /// /// Chance face shield is down/active diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/HideoutConfig.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/HideoutConfig.cs index 036fdbf7..7fbdf409 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/HideoutConfig.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/HideoutConfig.cs @@ -55,16 +55,16 @@ public record HideoutCraftToAdd /// The new mongoId for the craft to use /// [JsonPropertyName("newId")] - public required string NewId { get; set; } + public required MongoId NewId { get; set; } [JsonPropertyName("requirements")] public required List Requirements { get; set; } [JsonPropertyName("craftIdToCopy")] - public required string CraftIdToCopy { get; set; } + public required MongoId CraftIdToCopy { get; set; } [JsonPropertyName("craftOutputTpl")] - public required string CraftOutputTpl { get; set; } + public required MongoId CraftOutputTpl { get; set; } } public record CultistCircleSettings @@ -157,10 +157,10 @@ public record DirectRewardSettings public Dictionary? ExtensionData { get; set; } [JsonPropertyName("reward")] - public required List Reward { get; set; } + public required List Reward { get; set; } [JsonPropertyName("requiredItems")] - public required List RequiredItems { get; set; } + public required List RequiredItems { get; set; } [JsonPropertyName("craftTimeSeconds")] public required int CraftTimeSeconds { get; set; } diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/InsuranceConfig.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/InsuranceConfig.cs index 924ee3ad..db5d274b 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/InsuranceConfig.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/InsuranceConfig.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using SPTarkov.Server.Core.Models.Common; namespace SPTarkov.Server.Core.Models.Spt.Config; @@ -11,7 +12,7 @@ public record InsuranceConfig : BaseConfig /// Chance item is returned as insurance, keyed by trader id /// [JsonPropertyName("returnChancePercent")] - public Dictionary ReturnChancePercent { get; set; } = []; + public Dictionary ReturnChancePercent { get; set; } = []; /// /// Item slots that should never be returned as insurance diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/InventoryConfig.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/InventoryConfig.cs index e652c1e3..96d7291e 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/InventoryConfig.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/InventoryConfig.cs @@ -15,7 +15,7 @@ public record InventoryConfig : BaseConfig public bool NewItemsMarkedFound { get; set; } [JsonPropertyName("randomLootContainers")] - public required Dictionary RandomLootContainers { get; set; } + public required Dictionary RandomLootContainers { get; set; } [JsonPropertyName("sealedAirdropContainer")] public required SealedAirdropContainerSettings SealedAirdropContainer { get; set; } @@ -24,7 +24,7 @@ public record InventoryConfig : BaseConfig /// Contains item tpls that the server should consider money and treat the same as roubles/euros/dollars /// [JsonPropertyName("customMoneyTpls")] - public required List CustomMoneyTpls { get; set; } + public required List CustomMoneyTpls { get; set; } /// /// Multipliers for skill gain when inside menus, NOT in-game @@ -36,7 +36,7 @@ public record InventoryConfig : BaseConfig /// Container Tpls that should be deprioritised when choosing where to take money from for payments /// [JsonPropertyName("deprioritisedMoneyContainers")] - public required HashSet DeprioritisedMoneyContainers { get; set; } + public required HashSet DeprioritisedMoneyContainers { get; set; } } public record RewardDetails @@ -54,7 +54,7 @@ public record RewardDetails public bool FoundInRaid { get; set; } [JsonPropertyName("rewardTplPool")] - public Dictionary? RewardTplPool { get; set; } + public Dictionary? RewardTplPool { get; set; } [JsonPropertyName("rewardTypePool")] public List? RewardTypePool { get; set; } @@ -78,13 +78,13 @@ public record SealedAirdropContainerSettings public bool FoundInRaid { get; set; } [JsonPropertyName("weaponModRewardLimits")] - public required Dictionary> WeaponModRewardLimits { get; set; } + public required Dictionary> WeaponModRewardLimits { get; set; } [JsonPropertyName("rewardTypeLimits")] - public required Dictionary> RewardTypeLimits { get; set; } + public required Dictionary> RewardTypeLimits { get; set; } [JsonPropertyName("ammoBoxWhitelist")] - public required List AmmoBoxWhitelist { get; set; } + public required List AmmoBoxWhitelist { get; set; } [JsonPropertyName("allowBossItems")] public bool AllowBossItems { get; set; } diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/LocationConfig.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/LocationConfig.cs index 80dbfd58..cb6e3ee2 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/LocationConfig.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/LocationConfig.cs @@ -37,7 +37,7 @@ public record LocationConfig : BaseConfig /// Key = map id, value = dict of item tpls that should only have x forced loot spawn position /// [JsonPropertyName("lootMaxSpawnLimits")] - public required Dictionary> LootMaxSpawnLimits { get; set; } + public required Dictionary> LootMaxSpawnLimits { get; set; } /// /// How many attempts should be taken to fit an item into a container before giving up @@ -130,7 +130,7 @@ public record LocationConfig : BaseConfig /// Containers to remove all children from when generating static/loose loot /// [JsonPropertyName("tplsToStripChildItemsFrom")] - public required HashSet TplsToStripChildItemsFrom { get; set; } + public required HashSet TplsToStripChildItemsFrom { get; set; } /// /// Map ids players cannot visit @@ -232,7 +232,7 @@ public record ContainerRandomisationSettings /// Some container types don't work when randomised /// [JsonPropertyName("containerTypesToNotRandomise")] - public required HashSet ContainerTypesToNotRandomise { get; set; } + public required HashSet ContainerTypesToNotRandomise { get; set; } [JsonPropertyName("containerGroupMinSizeMultiplier")] public double ContainerGroupMinSizeMultiplier { get; set; } diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/PlayerScavConfig.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/PlayerScavConfig.cs index 6fb44903..9e1729e3 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/PlayerScavConfig.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/PlayerScavConfig.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Enums; @@ -28,7 +29,7 @@ public record KarmaLevel public required Dictionary ItemLimits { get; set; } [JsonPropertyName("equipmentBlacklist")] - public required Dictionary> EquipmentBlacklist { get; set; } + public required Dictionary> EquipmentBlacklist { get; set; } [JsonPropertyName("labsAccessCardChancePercent")] public double? LabsAccessCardChancePercent { get; set; } diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/RagfairConfig.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/RagfairConfig.cs index 6555238c..e5503618 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/RagfairConfig.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/RagfairConfig.cs @@ -30,7 +30,7 @@ public record RagfairConfig : BaseConfig /// Trader ids + should their assorts be listed on flea /// [JsonPropertyName("traders")] - public Dictionary Traders { get; set; } + public required Dictionary Traders { get; set; } [JsonPropertyName("dynamic")] public Dynamic Dynamic { get; set; } @@ -159,7 +159,7 @@ public record Dynamic /// Tpls that should not use the variable price system when their quality is less than 100% (lower dura/uses = lower price) /// [JsonPropertyName("ignoreQualityPriceVarianceBlacklist")] - public HashSet IgnoreQualityPriceVarianceBlacklist { get; set; } + public HashSet IgnoreQualityPriceVarianceBlacklist { get; set; } [JsonPropertyName("endTimeSeconds")] public MinMax EndTimeSeconds { get; set; } @@ -198,7 +198,7 @@ public record Dynamic /// A multipler to apply to individual tpls price just prior to item quality adjustment /// [JsonPropertyName("itemPriceMultiplier")] - public Dictionary? ItemPriceMultiplier { get; set; } + public Dictionary? ItemPriceMultiplier { get; set; } [JsonPropertyName("_currencies")] public string? CurrenciesDescription { get; set; } @@ -207,13 +207,13 @@ public record Dynamic /// Percentages to sell offers in each currency /// [JsonPropertyName("currencies")] - public Dictionary Currencies { get; set; } + public Dictionary Currencies { get; set; } /// /// Item tpls that should be forced to sell as a single item /// [JsonPropertyName("showAsSingleStack")] - public HashSet ShowAsSingleStack { get; set; } + public HashSet ShowAsSingleStack { get; set; } /// /// Should christmas/halloween items be removed from flea when not within the seasonal bounds @@ -231,13 +231,13 @@ public record Dynamic /// Dict of price limits keyed by item type /// [JsonPropertyName("unreasonableModPrices")] - public Dictionary UnreasonableModPrices { get; set; } + public Dictionary UnreasonableModPrices { get; set; } /// /// Custom rouble prices for items to override values from prices.json /// [JsonPropertyName("itemPriceOverrideRouble")] - public Dictionary ItemPriceOverrideRouble { get; set; } + public Dictionary ItemPriceOverrideRouble { get; set; } } public record PriceRanges @@ -300,7 +300,7 @@ public record BarterDetails /// Item Tpls to never be turned into a barter /// [JsonPropertyName("itemTypeBlacklist")] - public HashSet ItemTypeBlacklist { get; set; } + public HashSet ItemTypeBlacklist { get; set; } } public record PackDetails @@ -330,7 +330,7 @@ public record PackDetails /// item types to allow being a pack /// [JsonPropertyName("itemTypeWhitelist")] - public HashSet ItemTypeWhitelist { get; set; } + public HashSet ItemTypeWhitelist { get; set; } } public record OfferAdjustment @@ -399,7 +399,7 @@ public record RagfairBlacklist /// Custom blacklist for item Tpls /// [JsonPropertyName("custom")] - public HashSet Custom { get; set; } + public HashSet Custom { get; set; } /// /// BSG blacklist a large number of items from flea, true = use blacklist @@ -513,16 +513,16 @@ public record TieredFlea /// key: tpl, value: playerlevel /// [JsonPropertyName("unlocksTpl")] - public Dictionary UnlocksTpl { get; set; } + public Dictionary UnlocksTpl { get; set; } /// /// key: item type id, value: playerlevel /// [JsonPropertyName("unlocksType")] - public Dictionary UnlocksType { get; set; } + public Dictionary UnlocksType { get; set; } [JsonPropertyName("ammoTplUnlocks")] - public Dictionary? AmmoTplUnlocks { get; set; } + public Dictionary? AmmoTplUnlocks { get; set; } [JsonPropertyName("ammoTiersEnabled")] public bool AmmoTiersEnabled { get; set; } diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/ScavCaseConfig.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/ScavCaseConfig.cs index 23ddb7b9..3a08d9f7 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/ScavCaseConfig.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/ScavCaseConfig.cs @@ -18,10 +18,10 @@ public record ScavCaseConfig : BaseConfig public required AmmoRewards AmmoRewards { get; set; } [JsonPropertyName("rewardItemParentBlacklist")] - public required HashSet RewardItemParentBlacklist { get; set; } + public required HashSet RewardItemParentBlacklist { get; set; } [JsonPropertyName("rewardItemBlacklist")] - public required HashSet RewardItemBlacklist { get; set; } + public required HashSet RewardItemBlacklist { get; set; } [JsonPropertyName("allowMultipleMoneyRewardsPerRarity")] public bool AllowMultipleMoneyRewardsPerRarity { get; set; } @@ -78,7 +78,7 @@ public record AmmoRewards public int AmmoRewardChancePercent { get; set; } [JsonPropertyName("ammoRewardBlacklist")] - public required Dictionary> AmmoRewardBlacklist { get; set; } + public required Dictionary> AmmoRewardBlacklist { get; set; } [JsonPropertyName("ammoRewardValueRangeRub")] public required Dictionary> AmmoRewardValueRangeRub { get; set; } diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/SeasonalEventConfig.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/SeasonalEventConfig.cs index 426f887c..d399da1d 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/SeasonalEventConfig.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/SeasonalEventConfig.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Eft.Common; using SPTarkov.Server.Core.Models.Enums; using SPTarkov.Server.Core.Utils.Json.Converters; @@ -19,7 +20,7 @@ public record SeasonalEventConfig : BaseConfig [JsonPropertyName("eventGear")] public required Dictionary< SeasonalEventType, - Dictionary>> + Dictionary>> > EventGear { get; set; } /// @@ -28,7 +29,7 @@ public record SeasonalEventConfig : BaseConfig [JsonPropertyName("eventLoot")] public required Dictionary< SeasonalEventType, - Dictionary>> + Dictionary>> > EventLoot { get; set; } [JsonPropertyName("events")] @@ -70,7 +71,7 @@ public record SeasonalEventConfig : BaseConfig [JsonPropertyName("botAppearanceChanges")] public required Dictionary< SeasonalEventType, - Dictionary>> + Dictionary>> > BotAppearanceChanges { get; set; } } diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/TraderConfig.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/TraderConfig.cs index a9c43296..ace6a170 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/TraderConfig.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/TraderConfig.cs @@ -43,7 +43,7 @@ public record UpdateTime public string Name { get; set; } = string.Empty; [JsonPropertyName("traderId")] - public string TraderId { get; set; } = string.Empty; + public MongoId TraderId { get; set; } = string.Empty; /// /// Seconds between trader resets @@ -97,16 +97,16 @@ public record FenceConfig /// Key: item tpl /// [JsonPropertyName("itemStackSizeOverrideMinMax")] - public required Dictionary?> ItemStackSizeOverrideMinMax { get; set; } + public required Dictionary?> ItemStackSizeOverrideMinMax { get; set; } [JsonPropertyName("itemTypeLimits")] - public required Dictionary ItemTypeLimits { get; set; } + public required Dictionary ItemTypeLimits { get; set; } /// /// Prevent duplicate offers of items of specific categories by parentId /// [JsonPropertyName("preventDuplicateOffersOfCategory")] - public required List PreventDuplicateOffersOfCategory { get; set; } + public required List PreventDuplicateOffersOfCategory { get; set; } [JsonPropertyName("regenerateAssortsOnRefresh")] public bool RegenerateAssortsOnRefresh { get; set; } @@ -115,7 +115,7 @@ public record FenceConfig /// Max rouble price before item is not listed on flea /// [JsonPropertyName("itemCategoryRoublePriceLimit")] - public required Dictionary ItemCategoryRoublePriceLimit { get; set; } + public required Dictionary ItemCategoryRoublePriceLimit { get; set; } /// /// Each slotid with % to be removed prior to listing on fence @@ -136,7 +136,7 @@ public record FenceConfig public double AmmoMaxPenLimit { get; set; } [JsonPropertyName("blacklist")] - public required HashSet Blacklist { get; set; } + public required HashSet Blacklist { get; set; } [JsonPropertyName("coopExtractGift")] public required CoopExtractReward CoopExtractGift { get; set; } diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Services/LootRequest.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Services/LootRequest.cs index 8a6674ea..20f3e892 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Services/LootRequest.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Services/LootRequest.cs @@ -82,7 +82,7 @@ public record LootRequest /// Item tpls + count of items to force include /// [JsonPropertyName("forcedLoot")] - public Dictionary>? ForcedLoot { get; set; } + public Dictionary>? ForcedLoot { get; set; } /// /// Should seasonal items appear when it's not the season for them diff --git a/Libraries/SPTarkov.Server.Core/Servers/RagfairServer.cs b/Libraries/SPTarkov.Server.Core/Servers/RagfairServer.cs index fb9f9349..e1957bd0 100644 --- a/Libraries/SPTarkov.Server.Core/Servers/RagfairServer.cs +++ b/Libraries/SPTarkov.Server.Core/Servers/RagfairServer.cs @@ -77,7 +77,7 @@ public class RagfairServer( /// Get traders who need to be periodically refreshed /// /// List of traders - public List GetUpdateableTraders() + public List GetUpdateableTraders() { return _ragfairConfig.Traders.Keys.ToList(); } diff --git a/Libraries/SPTarkov.Server.Core/Services/BotEquipmentFilterService.cs b/Libraries/SPTarkov.Server.Core/Services/BotEquipmentFilterService.cs index 473751ef..afdc1506 100644 --- a/Libraries/SPTarkov.Server.Core/Services/BotEquipmentFilterService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/BotEquipmentFilterService.cs @@ -1,6 +1,7 @@ using SPTarkov.Common.Extensions; using SPTarkov.DI.Annotations; using SPTarkov.Server.Core.Helpers; +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.Spt.Bots; @@ -160,7 +161,7 @@ public class BotEquipmentFilterService( /// /// equipment role of bot to look up /// Dictionary of weapon type and their whitelisted scope types - public Dictionary> GetBotWeaponSightWhitelist(string botEquipmentRole) + public Dictionary> GetBotWeaponSightWhitelist(string botEquipmentRole) { var botEquipmentSettings = _botConfig.Equipment[botEquipmentRole]; diff --git a/Libraries/SPTarkov.Server.Core/Services/BtrDeliveryService.cs b/Libraries/SPTarkov.Server.Core/Services/BtrDeliveryService.cs index 320eec6b..d0451426 100644 --- a/Libraries/SPTarkov.Server.Core/Services/BtrDeliveryService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/BtrDeliveryService.cs @@ -1,4 +1,5 @@ using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Eft.Match; using SPTarkov.Server.Core.Models.Eft.Profile; @@ -82,7 +83,7 @@ public class BtrDeliveryService( .BtrDeliveryList.Add( new BtrDelivery { - Id = _hashUtil.Generate(), + Id = new MongoId(), ScheduledTime = (int)GetBTRDeliveryReturnTimestamp(), Items = items, } diff --git a/Libraries/SPTarkov.Server.Core/Services/DatabaseService.cs b/Libraries/SPTarkov.Server.Core/Services/DatabaseService.cs index 549ce630..63398247 100644 --- a/Libraries/SPTarkov.Server.Core/Services/DatabaseService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/DatabaseService.cs @@ -1,6 +1,7 @@ using System.Diagnostics; 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; @@ -414,7 +415,7 @@ public class DatabaseService( { foreach (var keyValuePair in table) { - if (!_hashUtil.IsValidMongoId(keyValuePair.Key)) + if (!keyValuePair.Key.IsValidMongoId()) { _logger.Error($"Invalid {tableType} ID: '{keyValuePair.Key}'"); return false; @@ -428,7 +429,7 @@ public class DatabaseService( { foreach (var keyValuePair in table) { - if (!_hashUtil.IsValidMongoId(keyValuePair.Key)) + if (!keyValuePair.Key.IsValidMongoId()) { _logger.Error($"Invalid {tableType} ID: '{keyValuePair.Key}'"); return false; diff --git a/Libraries/SPTarkov.Server.Core/Services/FenceService.cs b/Libraries/SPTarkov.Server.Core/Services/FenceService.cs index 4e2bff8b..9d54439b 100644 --- a/Libraries/SPTarkov.Server.Core/Services/FenceService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/FenceService.cs @@ -782,7 +782,7 @@ public class FenceService( int? assortCount, CreateFenceAssortsResult assorts, TraderAssort baseFenceAssortClone, - Dictionary itemTypeLimits, + Dictionary itemTypeLimits, int loyaltyLevel ) { @@ -1066,8 +1066,8 @@ public class FenceService( } protected (int current, int max)? GetMatchingItemLimit( - Dictionary itemTypeLimits, - string itemTpl + Dictionary itemTypeLimits, + MongoId itemTpl ) { foreach (var baseTypeKey in itemTypeLimits.Keys) @@ -1680,11 +1680,11 @@ public class FenceService( /// /// Limits as defined in config /// Record, key: item tplId, value: current/max item count allowed - protected Dictionary InitItemLimitCounter( - Dictionary limits + protected Dictionary InitItemLimitCounter( + Dictionary limits ) { - var itemTypeCounts = new Dictionary(); + var itemTypeCounts = new Dictionary(); foreach (var x in limits.Keys) { diff --git a/Libraries/SPTarkov.Server.Core/Services/ItemBaseClassService.cs b/Libraries/SPTarkov.Server.Core/Services/ItemBaseClassService.cs index d5239b61..a67cc9a5 100644 --- a/Libraries/SPTarkov.Server.Core/Services/ItemBaseClassService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/ItemBaseClassService.cs @@ -1,4 +1,5 @@ using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Utils; using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel; @@ -16,7 +17,7 @@ public class ItemBaseClassService( ) { private bool _cacheGenerated; - private Dictionary> _itemBaseClassesCache; + private Dictionary> _itemBaseClassesCache = []; /// /// Create cache and store inside ItemBaseClassService
@@ -25,7 +26,7 @@ public class ItemBaseClassService( public void HydrateItemBaseClassCache() { // Clear existing cache - _itemBaseClassesCache = new Dictionary>(); + _itemBaseClassesCache = new Dictionary>(); var items = _databaseService.GetItems(); var filteredDbItems = items.Where(x => @@ -50,12 +51,12 @@ public class ItemBaseClassService( ///
/// Item tpl to store base ids against in dictionary /// Item being checked - protected void AddBaseItems(string itemIdToUpdate, TemplateItem item) + protected void AddBaseItems(MongoId itemIdToUpdate, TemplateItem item) { _itemBaseClassesCache[itemIdToUpdate].Add(item.Parent); _databaseService.GetItems().TryGetValue(item.Parent, out var parent); - if (parent is not null && !string.IsNullOrEmpty(parent.Parent)) + if (parent is not null && !parent.Parent.IsEmpty()) { AddBaseItems(itemIdToUpdate, parent); } @@ -67,14 +68,14 @@ public class ItemBaseClassService( /// ItemTpl item to check base classes of /// BaseClass base class to check for /// true if item inherits from base class passed in - public bool ItemHasBaseClass(string itemTpl, ICollection baseClasses) + public bool ItemHasBaseClass(MongoId itemTpl, ICollection baseClasses) { if (!_cacheGenerated) { HydrateItemBaseClassCache(); } - if (string.IsNullOrEmpty(itemTpl)) + if (itemTpl.IsEmpty()) { _logger.Warning("Unable to check itemTpl base class as value passed is null"); @@ -119,7 +120,7 @@ public class ItemBaseClassService( /// /// ItemTemplateId item to check /// True if item is of type Item - private bool CachedItemIsOfItemType(string itemTemplateId) + private bool CachedItemIsOfItemType(MongoId itemTemplateId) { return string.Equals( _databaseService.GetItems()[itemTemplateId]?.Type, @@ -133,7 +134,7 @@ public class ItemBaseClassService( /// /// ItemTpl item to get base classes for /// array of base classes - public List GetItemBaseClasses(string itemTpl) + public List GetItemBaseClasses(MongoId itemTpl) { if (!_cacheGenerated) { diff --git a/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs b/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs index 7db9fa8f..f09e60c0 100644 --- a/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/LocationLifecycleService.cs @@ -171,7 +171,7 @@ public class LocationLifecycleService Transition = new Transition { TransitionType = TransitionType.NONE, - TransitionRaidId = _hashUtil.Generate(), + TransitionRaidId = new MongoId(), TransitionCount = 0, VisitedLocations = [], }, @@ -520,7 +520,7 @@ public class LocationLifecycleService // Generate randomised reward for taking coop extract var loot = _lootGenerator.CreateRandomLoot(_traderConfig.Fence.CoopExtractGift); - var parentId = _hashUtil.Generate(); + var parentId = new MongoId(); foreach (var itemAndChildren in loot) { // Set all root items parent to new id diff --git a/Libraries/SPTarkov.Server.Core/Services/MailSendService.cs b/Libraries/SPTarkov.Server.Core/Services/MailSendService.cs index e635330d..15d344a6 100644 --- a/Libraries/SPTarkov.Server.Core/Services/MailSendService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/MailSendService.cs @@ -1,6 +1,7 @@ using SPTarkov.DI.Annotations; using SPTarkov.Server.Core.Extensions; using SPTarkov.Server.Core.Helpers; +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; @@ -194,7 +195,7 @@ public class MailSendService( // add items to message if (items?.Count > 0) { - var rootItemParentId = _hashUtil.Generate(); + var rootItemParentId = new MongoId(); details.Items.AddRange(items.AdoptOrphanedItems(rootItemParentId)); details.ItemsMaxStorageLifetimeSeconds = maxStorageTimeSeconds; @@ -366,7 +367,7 @@ public class MailSendService( dialogWithNpc.Messages.Add( new Message { - Id = _hashUtil.Generate(), + Id = new MongoId(), DateTime = _timeUtil.GetTimeStamp(), HasRewards = false, UserId = playerProfile.CharacterData.PmcData.Id, @@ -387,7 +388,7 @@ public class MailSendService( { Message message = new() { - Id = _hashUtil.Generate(), + Id = new MongoId(), UserId = dialogId, MessageType = messageDetails.Sender, DateTime = _timeUtil.GetTimeStamp(), @@ -506,7 +507,7 @@ public class MailSendService( // No parent id, generate random id and add (doesn't need to be actual parentId from db, only unique) if (parentItem?.ParentId is null) { - parentItem.ParentId = _hashUtil.Generate(); + parentItem.ParentId = new MongoId(); } // Prep return object diff --git a/Libraries/SPTarkov.Server.Core/Services/Mod/CustomItemService.cs b/Libraries/SPTarkov.Server.Core/Services/Mod/CustomItemService.cs index fd27a461..56daabb5 100644 --- a/Libraries/SPTarkov.Server.Core/Services/Mod/CustomItemService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/Mod/CustomItemService.cs @@ -137,9 +137,9 @@ public class CustomItemService( /// /// ID supplied to code /// ItemID - protected string GetOrGenerateIdForItem(string newId) + protected MongoId GetOrGenerateIdForItem(string newId) { - return newId == "" ? hashUtil.Generate() : newId; + return string.IsNullOrEmpty(newId) ? new MongoId() : new MongoId(newId); } /// diff --git a/Libraries/SPTarkov.Server.Core/Services/RagfairLinkedItemService.cs b/Libraries/SPTarkov.Server.Core/Services/RagfairLinkedItemService.cs index 63a6d1d4..4e879806 100644 --- a/Libraries/SPTarkov.Server.Core/Services/RagfairLinkedItemService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/RagfairLinkedItemService.cs @@ -1,4 +1,5 @@ using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Extensions; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Eft.Common.Tables; @@ -128,8 +129,10 @@ public class RagfairLinkedItemService( } // Get the first cylinder filter tpl - var cylinderTpl = cylinderMod.Props?.Filters?[0].Filter?.FirstOrDefault(); - if (string.IsNullOrEmpty(cylinderTpl)) + var cylinderTpl = + cylinderMod.Props?.Filters?[0].Filter?.FirstOrDefault() ?? new MongoId(null); + + if (!cylinderTpl.IsValidMongoId()) { // No cylinder, nothing to do return; diff --git a/Libraries/SPTarkov.Server.Core/Services/RagfairOfferService.cs b/Libraries/SPTarkov.Server.Core/Services/RagfairOfferService.cs index b8cc54bf..c498babb 100644 --- a/Libraries/SPTarkov.Server.Core/Services/RagfairOfferService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/RagfairOfferService.cs @@ -1,6 +1,7 @@ using SPTarkov.Common.Extensions; using SPTarkov.DI.Annotations; using SPTarkov.Server.Core.Helpers; +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.Spt.Config; @@ -268,7 +269,7 @@ public class RagfairOfferService( var unstackedItems = UnstackOfferItems(playerOffer.Items); // Need to regenerate Ids to ensure returned item(s) have correct parent values - var newParentId = hashUtil.Generate(); + var newParentId = new MongoId(); foreach (var item in unstackedItems) { // Refresh root items' parentIds diff --git a/Libraries/SPTarkov.Server.Core/Services/SeasonalEventService.cs b/Libraries/SPTarkov.Server.Core/Services/SeasonalEventService.cs index 3b197dd8..fd74242d 100644 --- a/Libraries/SPTarkov.Server.Core/Services/SeasonalEventService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/SeasonalEventService.cs @@ -209,7 +209,7 @@ public class SeasonalEventService( /// /// Name of event to get gear changes for /// bots with equipment changes - protected Dictionary>>? GetEventBotGear( + protected Dictionary>>? GetEventBotGear( SeasonalEventType eventType ) { @@ -221,7 +221,7 @@ public class SeasonalEventService( /// /// Name of event to get gear changes for /// bots with loot changes - protected Dictionary>> GetEventBotLoot( + protected Dictionary>> GetEventBotLoot( SeasonalEventType eventType ) { diff --git a/Libraries/SPTarkov.Server.Core/Utils/HashUtil.cs b/Libraries/SPTarkov.Server.Core/Utils/HashUtil.cs index 2bb21c82..9238a8a4 100644 --- a/Libraries/SPTarkov.Server.Core/Utils/HashUtil.cs +++ b/Libraries/SPTarkov.Server.Core/Utils/HashUtil.cs @@ -1,7 +1,6 @@ using System.IO.Hashing; using System.Security.Cryptography; using System.Text; -using System.Text.RegularExpressions; using SPTarkov.DI.Annotations; namespace SPTarkov.Server.Core.Utils; @@ -9,47 +8,6 @@ namespace SPTarkov.Server.Core.Utils; [Injectable(InjectionType.Singleton)] public partial class HashUtil(RandomUtil _randomUtil) { - /// - /// Create a 24 character MongoId - /// - /// 24 character objectId - public string Generate() - { - // Allocate a span directly onto the stack, will dispose whenever we finished running - // Span is recommended to work with stackalloc and we can use stackalloc here because we don't do anything with this afterwards - Span objectId = stackalloc byte[12]; - - // Time stamp (4 bytes) - var timestamp = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds(); - // Convert to big-endian - objectId[0] = (byte)(timestamp >> 24); - objectId[1] = (byte)(timestamp >> 16); - objectId[2] = (byte)(timestamp >> 8); - objectId[3] = (byte)timestamp; - - // Random value (5 bytes) - _randomUtil.NextBytes(objectId.Slice(4, 5)); - - // Incrementing counter (3 bytes) - // 24-bit counter - var counter = _randomUtil.GetInt(0, 16777215); - objectId[9] = (byte)(counter >> 16); - objectId[10] = (byte)(counter >> 8); - objectId[11] = (byte)counter; - - return Convert.ToHexStringLower(objectId); - } - - /// - /// is the passed in string a valid mongo id - /// - /// String to check - /// True when string is a valid mongo id - public bool IsValidMongoId(string stringToCheck) - { - return MongoIdRegex().IsMatch(stringToCheck); - } - public uint GenerateCrc32ForData(string data) { return Crc32.HashToUInt32(new ArraySegment(Encoding.UTF8.GetBytes(data))); @@ -124,9 +82,6 @@ public partial class HashUtil(RandomUtil _randomUtil) return _randomUtil.Random.Next(min, max + 1); } - - [GeneratedRegex("^[a-fA-F0-9]{24}$")] - private static partial Regex MongoIdRegex(); } public enum HashingAlgorithm diff --git a/Libraries/SPTarkov.Server.Core/Utils/RagfairOfferHolder.cs b/Libraries/SPTarkov.Server.Core/Utils/RagfairOfferHolder.cs index 03f244a1..128685be 100644 --- a/Libraries/SPTarkov.Server.Core/Utils/RagfairOfferHolder.cs +++ b/Libraries/SPTarkov.Server.Core/Utils/RagfairOfferHolder.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; using SPTarkov.DI.Annotations; using SPTarkov.Server.Core.Extensions; using SPTarkov.Server.Core.Helpers; +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.Utils; @@ -137,10 +138,10 @@ public class RagfairOfferHolder( // Keep generating IDs until we get a unique one while (_offersById.ContainsKey(offer.Id)) { - offer.Id = _hashUtil.Generate(); + offer.Id = new MongoId(); } - var itemTpl = offer.Items?.FirstOrDefault()?.Template; + var itemTpl = offer.Items?.FirstOrDefault()?.Template ?? new MongoId(null); var sellerId = offer.User.Id; var sellerIsTrader = _ragfairServerHelper.IsTrader(sellerId); diff --git a/UnitTests/Tests/Utils/HashUtilTests.cs b/UnitTests/Tests/Utils/HashUtilTests.cs deleted file mode 100644 index 19c7e537..00000000 --- a/UnitTests/Tests/Utils/HashUtilTests.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System.Collections.Concurrent; -using System.Diagnostics; -using SPTarkov.Server.Core.Utils; - -namespace UnitTests.Tests.Utils; - -[TestClass] -public class HashUtilTests -{ - private HashUtil _hashUtil; - - [TestInitialize] - public void Initialize() - { - _hashUtil = DI.GetService(); - } - - [TestMethod] - public void GenerateTest() - { - // Generate 100 MongoId's - for (var i = 0; i < 100; i++) - { - // Invalid mongoId character - var result = _hashUtil.Generate(); - - // Invalid mongoId length - var test = _hashUtil.IsValidMongoId(result); - - Assert.AreEqual(true, test, $"IsValidMongoId() `{result}` is not a valid MongoId."); - } - } - - [TestMethod] - [DataRow( - "677ddb67406e9918a0264bbz", - false, - "677ddb67406e9918a0264bbz contains invalid char `z`, but result was true" - )] - [DataRow( - "677ddb67406e9918a0264bbcc", - false, - "677ddb67406e9918a0264bbcc is 25 characters, but result was true" - )] - [DataRow( - "677ddb67406e9918a0264bbc", - true, - "IsValidMongoId() `677ddb67406e9918a0264bbc` is a valid mongoId, but result was false" - )] - public void IsValidMongoIdTest(string mongoId, bool passes, string failMessage) - { - var result = _hashUtil.IsValidMongoId(mongoId); - Assert.AreEqual(passes, result, failMessage); - } - - [TestMethod] - [DataRow( - "123456789", - "25F9E794323B453885F5181F1B624D0B", - "Not valid output, expected '25F9E794323B453885F5181F1B624D0B'" - )] - public void GenerateValidMd5Test(string input, string expectedOutput, string failMessage) - { - var result = _hashUtil.GenerateHashForData(HashingAlgorithm.MD5, input); - Assert.AreEqual(expectedOutput, result, failMessage); - } - - [TestMethod] - public void MultiThreadedMongoIDGenerationTest() - { - var concurrentBag = new ConcurrentBag(); - var random = new Random(); - var stopwatch = new Stopwatch(); - stopwatch.Start(); - - Parallel.For( - 0, - 1000, - i => - { - Thread.Sleep(random.Next(0, 10)); - var mongoId = _hashUtil.Generate(); - concurrentBag.Add(mongoId); - } - ); - - stopwatch.Stop(); - Console.WriteLine($"Elapsed time: {stopwatch.ElapsedMilliseconds} ms"); - var uniqueCount = concurrentBag.Distinct().Count(); - var totalCount = concurrentBag.Count; - Assert.AreEqual( - totalCount, - uniqueCount, - $"Expected all generated MongoId's to be unique, but found {totalCount - uniqueCount} duplicates." - ); - } -}