diff --git a/Libraries/SPTarkov.Server.Core/Callbacks/LauncherCallbacks.cs b/Libraries/SPTarkov.Server.Core/Callbacks/LauncherCallbacks.cs index 91ef86b6..cdc87e32 100644 --- a/Libraries/SPTarkov.Server.Core/Callbacks/LauncherCallbacks.cs +++ b/Libraries/SPTarkov.Server.Core/Callbacks/LauncherCallbacks.cs @@ -24,13 +24,13 @@ public class LauncherCallbacks( public ValueTask Login(string url, LoginRequestData info, MongoId sessionID) { var output = launcherController.Login(info); - return new ValueTask(output.IsEmpty() ? "FAILED" : output.ToString()); + return new ValueTask(output.IsEmpty ? "FAILED" : output.ToString()); } public async ValueTask Register(string url, RegisterData info, MongoId sessionID) { var output = await launcherController.Register(info); - return output.IsEmpty() ? string.Empty : output.ToString(); + return output.IsEmpty ? string.Empty : output.ToString(); } public ValueTask Get(string url, LoginRequestData info, MongoId sessionID) @@ -54,7 +54,7 @@ public class LauncherCallbacks( public ValueTask Wipe(string url, RegisterData info, MongoId sessionID) { var output = launcherController.Wipe(info); - return new ValueTask(output.IsEmpty() ? "FAILED" : "OK"); + return new ValueTask(output.IsEmpty ? "FAILED" : "OK"); } public ValueTask GetServerVersion() diff --git a/Libraries/SPTarkov.Server.Core/Controllers/GameController.cs b/Libraries/SPTarkov.Server.Core/Controllers/GameController.cs index 02d31e51..cec58bd7 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/GameController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/GameController.cs @@ -52,7 +52,7 @@ public class GameController( { profileActivityService.AddActiveProfile(sessionId, startTimeStampMs); - if (sessionId.IsEmpty()) + if (sessionId.IsEmpty) { logger.Error($"{nameof(sessionId)} is empty on GameController.GameStart"); return; diff --git a/Libraries/SPTarkov.Server.Core/Controllers/HideoutController.cs b/Libraries/SPTarkov.Server.Core/Controllers/HideoutController.cs index 0e2eda28..13ed43ce 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/HideoutController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/HideoutController.cs @@ -192,7 +192,7 @@ public class HideoutController( } // Upgrade includes a container improvement/addition - if (hideoutStage.Container.HasValue && !hideoutStage.Container.Value.IsEmpty()) + if (hideoutStage.Container.HasValue && !hideoutStage.Container.Value.IsEmpty) { AddContainerImprovementToProfile(output, sessionID, pmcData, profileHideoutArea, hideoutData, hideoutStage); } diff --git a/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs b/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs index d74e00a4..88d68f9c 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/LauncherController.cs @@ -144,7 +144,7 @@ public class LauncherController( { var sessionID = Login(info); - if (!sessionID.IsEmpty()) + if (!sessionID.IsEmpty) { saveServer.GetProfile(sessionID).ProfileInfo!.Username = info.Change; } @@ -182,7 +182,7 @@ public class LauncherController( var sessionId = Login(info); - if (!sessionId.IsEmpty()) + if (!sessionId.IsEmpty) { var profileInfo = saveServer.GetProfile(sessionId).ProfileInfo; profileInfo!.Edition = info.Edition; diff --git a/Libraries/SPTarkov.Server.Core/Controllers/LauncherV2Controller.cs b/Libraries/SPTarkov.Server.Core/Controllers/LauncherV2Controller.cs index a85f95a1..9c590a87 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/LauncherV2Controller.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/LauncherV2Controller.cs @@ -62,7 +62,7 @@ public class LauncherV2Controller( { var sessionId = GetSessionId(info); - return !sessionId.IsEmpty(); + return !sessionId.IsEmpty; } /// @@ -93,7 +93,7 @@ public class LauncherV2Controller( { var sessionId = GetSessionId(info); - if (sessionId.IsEmpty()) + if (sessionId.IsEmpty) { return false; } @@ -117,7 +117,7 @@ public class LauncherV2Controller( { var sessionId = GetSessionId(info); - return !sessionId.IsEmpty() && saveServer.RemoveProfile(sessionId); + return !sessionId.IsEmpty && saveServer.RemoveProfile(sessionId); } /// diff --git a/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs b/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs index c072cfae..e0f81aad 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/RagfairController.cs @@ -322,7 +322,7 @@ public class RagfairController( return ragfairOfferHelper.GetOffersForBuild(searchRequest, itemsToAdd, traderAssorts, pmcProfile); } - if (searchRequest.NeededSearchId != null && !searchRequest.NeededSearchId.Value.IsEmpty()) + if (searchRequest.NeededSearchId != null && !searchRequest.NeededSearchId.Value.IsEmpty) { return ragfairOfferHelper.GetOffersThatRequireItem(searchRequest, pmcProfile); } @@ -931,7 +931,7 @@ public class RagfairController( { return requirements.Sum(requirement => { - if (requirement.Template.IsEmpty() || !requirement.Count.HasValue || requirement.Count == 0) + if (requirement.Template.IsEmpty || !requirement.Count.HasValue || requirement.Count == 0) { return 0; } diff --git a/Libraries/SPTarkov.Server.Core/Controllers/RepeatableQuestController.cs b/Libraries/SPTarkov.Server.Core/Controllers/RepeatableQuestController.cs index d498ce0b..538b5f86 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/RepeatableQuestController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/RepeatableQuestController.cs @@ -378,7 +378,7 @@ public class RepeatableQuestController( .ToList(); var traderId = randomUtil.DrawRandomFromList(traders).FirstOrDefault(); - if (traderId.IsEmpty()) + if (traderId.IsEmpty) { logger.Error(serverLocalisationService.GetText("repeatable-unable_to_find_trader_in_pool")); diff --git a/Libraries/SPTarkov.Server.Core/Extensions/ProfileExtensions.cs b/Libraries/SPTarkov.Server.Core/Extensions/ProfileExtensions.cs index 3d0908cf..83df3712 100644 --- a/Libraries/SPTarkov.Server.Core/Extensions/ProfileExtensions.cs +++ b/Libraries/SPTarkov.Server.Core/Extensions/ProfileExtensions.cs @@ -254,7 +254,7 @@ public static class ProfileExtensions /// OPTIONAL - ItemEventRouterResponse public static void RemoveItem(this PmcData profile, MongoId itemId, MongoId sessionId, ItemEventRouterResponse? output = null) { - if (itemId.IsEmpty()) + if (itemId.IsEmpty) { return; } diff --git a/Libraries/SPTarkov.Server.Core/Generators/BotEquipmentModGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/BotEquipmentModGenerator.cs index ec922241..e084821e 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/BotEquipmentModGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/BotEquipmentModGenerator.cs @@ -204,7 +204,7 @@ public class BotEquipmentModGenerator( { modTpl = exhaustableModPool.GetRandomValue(); if ( - !modTpl.Value.IsEmpty() + !modTpl.Value.IsEmpty && !botGeneratorHelper .IsItemIncompatibleWithCurrentItems(equipment, modTpl.Value, modSlotName) .Incompatible.GetValueOrDefault(false) diff --git a/Libraries/SPTarkov.Server.Core/Generators/BotWeaponGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/BotWeaponGenerator.cs index bd7d6fbe..13700959 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/BotWeaponGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/BotWeaponGenerator.cs @@ -446,7 +446,7 @@ public class BotWeaponGenerator( } // Has an UBGL - if (generatedWeaponResult.ChosenUbglAmmoTemplate is not null && !generatedWeaponResult.ChosenUbglAmmoTemplate.Value.IsEmpty()) + if (generatedWeaponResult.ChosenUbglAmmoTemplate is not null && !generatedWeaponResult.ChosenUbglAmmoTemplate.Value.IsEmpty) { AddUbglGrenadesToBotInventory(weaponAndMods, generatedWeaponResult, inventory); } diff --git a/Libraries/SPTarkov.Server.Core/Generators/FenceBaseAssortGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/FenceBaseAssortGenerator.cs index 2cbf3bf2..40f5b4ca 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/FenceBaseAssortGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/FenceBaseAssortGenerator.cs @@ -255,7 +255,7 @@ public class FenceBaseAssortGenerator( { var modItemDbDetails = itemHelper.GetItem(requiredSlot.Props.Filters.First().Plate.Value).Value; var plateTpl = requiredSlot.Props.Filters.First().Plate; // `Plate` property appears to be the 'default' item for slot - if (plateTpl is null || plateTpl.Value.IsEmpty()) + if (plateTpl is null || plateTpl.Value.IsEmpty) // Some bsg plate properties are empty, skip mod { continue; diff --git a/Libraries/SPTarkov.Server.Core/Generators/RagfairAssortGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/RagfairAssortGenerator.cs index fca37fe5..a445f7a9 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/RagfairAssortGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/RagfairAssortGenerator.cs @@ -119,7 +119,7 @@ public class RagfairAssortGenerator( /// Hydrated Item object protected Item CreateRagfairAssortRootItem(MongoId tplId, MongoId? id = null) { - if (id == null || id.Value.IsEmpty()) + if (id == null || id.Value.IsEmpty) { id = new MongoId(); } diff --git a/Libraries/SPTarkov.Server.Core/Helpers/InventoryHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/InventoryHelper.cs index 33ca7b2c..8db557c9 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/InventoryHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/InventoryHelper.cs @@ -436,7 +436,7 @@ public class InventoryHelper( /// OPTIONAL - ItemEventRouterResponse public void RemoveItem(PmcData profile, MongoId itemId, MongoId sessionId, ItemEventRouterResponse? output = null) { - if (itemId.IsEmpty()) + if (itemId.IsEmpty) { logger.Warning(serverLocalisationService.GetText("inventory-unable_to_remove_item_no_id_given")); @@ -562,7 +562,7 @@ public class InventoryHelper( ItemEventRouterResponse output ) { - if (itemId.IsEmpty()) + if (itemId.IsEmpty) { return output; } diff --git a/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs index d1ec2242..4056a842 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs @@ -1670,7 +1670,7 @@ public class ItemHelper( } var chosenTpl = GetCompatibleTplFromArray(itemPool, incompatibleModTpls); - if (chosenTpl.IsEmpty()) + if (chosenTpl.IsEmpty) { if (logger.IsLogEnabled(LogLevel.Debug)) { diff --git a/Libraries/SPTarkov.Server.Core/Helpers/PresetHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/PresetHelper.cs index 9100e3dd..f3734be1 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/PresetHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/PresetHelper.cs @@ -92,7 +92,7 @@ public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper /// True = preset exists for this id public bool IsPreset(MongoId id) { - if (id.IsEmpty()) + if (id.IsEmpty) { return false; } diff --git a/Libraries/SPTarkov.Server.Core/Helpers/RagfairHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/RagfairHelper.cs index 12ab3928..0e6aba3e 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/RagfairHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/RagfairHelper.cs @@ -88,7 +88,7 @@ public class RagfairHelper( } // Case: category - if (request.HandbookId.HasValue && !request.HandbookId.Value.IsEmpty()) + if (request.HandbookId.HasValue && !request.HandbookId.Value.IsEmpty) { var handbook = GetCategoryList(request.HandbookId.Value); result = (result?.Count > 0 ? result.IntersectWith(handbook) : handbook).ToList(); diff --git a/Libraries/SPTarkov.Server.Core/Helpers/RagfairOfferHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/RagfairOfferHelper.cs index a503403b..0b4c4049 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/RagfairOfferHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/RagfairOfferHelper.cs @@ -365,7 +365,7 @@ public class RagfairOfferHelper( // Performing a required search and offer doesn't have requirement for item if ( !searchRequest.NeededSearchId.HasValue - && !searchRequest.NeededSearchId.Value.IsEmpty() + && !searchRequest.NeededSearchId.Value.IsEmpty && !offer.Requirements.Any(requirement => requirement.TemplateId == searchRequest.NeededSearchId) ) { diff --git a/Libraries/SPTarkov.Server.Core/Models/Common/MongoId.cs b/Libraries/SPTarkov.Server.Core/Models/Common/MongoId.cs index 393476d3..3595d32f 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Common/MongoId.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Common/MongoId.cs @@ -1,71 +1,140 @@ -using SPTarkov.Server.Core.Extensions; +using System.Buffers.Binary; +using System.Security.Cryptography; +using SPTarkov.Server.Core.Extensions; namespace SPTarkov.Server.Core.Models.Common; +/// +/// Represents a 12-byte MongoDB-style ObjectId, consisting of: +/// +/// 4-byte timestamp (seconds since Unix epoch, big-endian) +/// 3-byte machine identifier +/// 2-byte process identifier (big-endian) +/// 3-byte incrementing counter (big-endian) +/// +/// +/// +/// +/// This struct stores the ObjectId in two packed fields for efficient memory usage +/// and comparison: +/// +/// : First 8 bytes (timestamp + machine ID) +/// : Last 4 bytes (process ID + counter) +/// +/// +/// +/// The struct is immutable and implements for fast comparisons. +/// +/// public readonly struct MongoId : IEquatable, IComparable { - private readonly string? _stringId; + /// + /// The first 8 bytes: 4-byte timestamp + 3-byte machine ID + 1 byte of PID. + /// + private readonly long _timestampAndMachine; - public MongoId(string? id) + /// + /// The last 4 bytes: remaining 1 byte of PID + 3-byte counter. + /// + private readonly int _pidAndIncrement; + + private static readonly int _machine = BitConverter.ToInt32(RandomNumberGenerator.GetBytes(4), 0) & 0xFFFFFF; + private static readonly short _pid = (short)Environment.ProcessId; + private static int _increment = RandomNumberGenerator.GetInt32(0, 0xFFFFFF); + + public bool IsEmpty { - // Handle null strings, various id's are null either by BSG or by our own doing with LINQ - if (string.IsNullOrEmpty(id)) - { - _stringId = null; - - return; - } - - if (id.Length != 24) - { - // TODO: Items.json root item has an empty parentId property - Console.WriteLine($"Critical MongoId error: Incorrect length. id: {id}"); - } - - if (!IsValidMongoId(id)) - { - Console.WriteLine($"Critical MongoId error: Incorrect format. Must be a hexadecimal [a-f0-9] of 24 characters. id: {id}"); - } - - _stringId = string.Intern(id); - } - - public MongoId() - { - _stringId = Generate(); + get { return _timestampAndMachine == 0 && _pidAndIncrement == 0; } } /// - /// Create a 24 character MongoId + /// Initializes a new with a generated value + /// based on the current time, machine ID, process ID, and counter. /// - /// 24 character objectId - private static string Generate() + public MongoId() { - Span objectId = stackalloc byte[12]; - - // 4 bytes: current timestamp (big endian) var timestamp = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds(); - objectId[0] = (byte)(timestamp >> 24); - objectId[1] = (byte)(timestamp >> 16); - objectId[2] = (byte)(timestamp >> 8); - objectId[3] = (byte)timestamp; + Span bytes = stackalloc byte[12]; - // 5 bytes: random machine/process identifier - Random.Shared.NextBytes(objectId.Slice(4, 5)); + // timestamp (4 bytes, big-endian) + BinaryPrimitives.WriteInt32BigEndian(bytes, timestamp); - // 3 bytes: random counter fallback (no static state) - var counter = Random.Shared.Next(0, 0xFFFFFF); - objectId[9] = (byte)(counter >> 16); - objectId[10] = (byte)(counter >> 8); - objectId[11] = (byte)counter; + // machine ID (3 bytes) + bytes[4] = (byte)(_machine >> 16); + bytes[5] = (byte)(_machine >> 8); + bytes[6] = (byte)_machine; - // Convert to lowercase hex string (24 chars) - return Convert.ToHexStringLower(objectId); + // PID (2 bytes) + BinaryPrimitives.WriteInt16BigEndian(bytes[7..9], _pid); + + // increment (3 bytes, big-endian) + var inc = Interlocked.Increment(ref _increment) & 0xFFFFFF; + bytes[9] = (byte)(inc >> 16); + bytes[10] = (byte)(inc >> 8); + bytes[11] = (byte)inc; + + // pack into fields (avoids array allocations later) + _timestampAndMachine = BitConverter.ToInt64(bytes); + _pidAndIncrement = BitConverter.ToInt32(bytes[8..]); } + public MongoId(string? hex) + { + if (string.IsNullOrEmpty(hex) || hex == "000000000000000000000000") + { + _timestampAndMachine = 0; + _pidAndIncrement = 0; + return; + } + + if (hex.Length != 24) + { + throw new ArgumentException("ObjectId must be a 24-character hex string.", nameof(hex)); + } + + Span bytes = stackalloc byte[12]; + Span chars = stackalloc char[24]; + hex.AsSpan().CopyTo(chars); + + for (var i = 0; i < 12; i++) + { + var hi = HexCharToValue(hex[2 * i]); + var lo = HexCharToValue(hex[2 * i + 1]); + + if (hi == -1 || lo == -1) + { + throw new FormatException("ObjectId contains invalid hex characters."); + } + + bytes[i] = (byte)((hi << 4) | lo); + } + + _timestampAndMachine = BitConverter.ToInt64(bytes); + _pidAndIncrement = BitConverter.ToInt32(bytes[8..]); + } + + private static int HexCharToValue(char c) + { + return c >= '0' && c <= '9' ? c - '0' + : c >= 'a' && c <= 'f' ? c - 'a' + 10 + : c >= 'A' && c <= 'F' ? c - 'A' + 10 + : -1; + } + + /// + /// Returns the MongoId as a 24-character lowercase hexadecimal string. + /// public override string ToString() { - return _stringId ?? string.Empty; + if (_timestampAndMachine == 0 && _pidAndIncrement == 0) + { + return string.Empty; + } + + Span bytes = stackalloc byte[12]; + BitConverter.TryWriteBytes(bytes, _timestampAndMachine); + BitConverter.TryWriteBytes(bytes[8..], _pidAndIncrement); + return Convert.ToHexString(bytes).ToLowerInvariant(); } public bool Equals(MongoId? other) @@ -75,17 +144,39 @@ public readonly struct MongoId : IEquatable, IComparable return false; } - return other.ToString().Equals(ToString(), StringComparison.InvariantCultureIgnoreCase); + return _timestampAndMachine == other.Value._timestampAndMachine && _pidAndIncrement == other.Value._pidAndIncrement; + } + + /// + public bool Equals(MongoId other) + { + return _timestampAndMachine == other._timestampAndMachine && _pidAndIncrement == other._pidAndIncrement; } public bool Equals(string? other) { - if (other is null) + if (other == null || other.Length != 24) { - return _stringId == null; + return false; } - return other.Equals(ToString(), StringComparison.InvariantCultureIgnoreCase); + Span bytes = stackalloc byte[12]; + for (var i = 0; i < 12; i++) + { + var hi = HexCharToValue(other[2 * i]); + var lo = HexCharToValue(other[2 * i + 1]); + if (hi == -1 || lo == -1) + { + return false; + } + + bytes[i] = (byte)((hi << 4) | lo); + } + + var a = BitConverter.ToInt64(bytes); + var b = BitConverter.ToInt32(bytes[8..]); + + return _timestampAndMachine == a && _pidAndIncrement == b; } public static bool IsValidMongoId(string stringToCheck) @@ -103,16 +194,13 @@ public readonly struct MongoId : IEquatable, IComparable return new MongoId(mongoId); } - public bool Equals(MongoId other) - { - return string.Equals(_stringId, other._stringId, StringComparison.OrdinalIgnoreCase); - } - public int CompareTo(MongoId other) { - return string.CompareOrdinal(_stringId, other._stringId); + var compare = _timestampAndMachine.CompareTo(other._timestampAndMachine); + return compare != 0 ? compare : _pidAndIncrement.CompareTo(other._pidAndIncrement); } + /// public override bool Equals(object? obj) { return obj is MongoId other && Equals(other); @@ -125,7 +213,7 @@ public readonly struct MongoId : IEquatable, IComparable public static bool operator !=(MongoId left, MongoId? right) { - return left.Equals(right); + return !left.Equals(right); } public static bool operator ==(MongoId left, MongoId? right) @@ -138,19 +226,10 @@ public readonly struct MongoId : IEquatable, IComparable return !left.Equals(right); } + /// public override int GetHashCode() { - return (_stringId ?? string.Empty).GetHashCode(); - } - - public bool IsEmpty() - { - if (string.IsNullOrEmpty(_stringId) || _stringId == "000000000000000000000000") - { - return true; - } - - return false; + return HashCode.Combine(_timestampAndMachine, _pidAndIncrement); } public static MongoId Empty() diff --git a/Libraries/SPTarkov.Server.Core/Servers/SaveServer.cs b/Libraries/SPTarkov.Server.Core/Servers/SaveServer.cs index ae116209..4d0661b7 100644 --- a/Libraries/SPTarkov.Server.Core/Servers/SaveServer.cs +++ b/Libraries/SPTarkov.Server.Core/Servers/SaveServer.cs @@ -106,7 +106,7 @@ public class SaveServer( /// Thrown when sessionId is null / empty or no profiles with that ID are found public SptProfile GetProfile(MongoId sessionId) { - if (sessionId.IsEmpty()) + if (sessionId.IsEmpty) { throw new Exception("session id provided was empty, did you restart the server while the game was running?"); } diff --git a/Libraries/SPTarkov.Server.Core/Services/AirdropService.cs b/Libraries/SPTarkov.Server.Core/Services/AirdropService.cs index aebe9dfa..7290c332 100644 --- a/Libraries/SPTarkov.Server.Core/Services/AirdropService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/AirdropService.cs @@ -219,7 +219,7 @@ public class AirdropService( var itemTypeBlacklist = _itemFilterService.GetItemRewardBaseTypeBlacklist(); var itemsMatchingTypeBlacklist = databaseService .GetItems() - .Where(kvp => !kvp.Value.Parent.IsEmpty()) + .Where(kvp => !kvp.Value.Parent.IsEmpty) .Where(kvp => _itemHelper.IsOfBaseclasses(kvp.Value.Parent, itemTypeBlacklist)) .Select(kvp => kvp.Key) .ToHashSet(); diff --git a/Libraries/SPTarkov.Server.Core/Services/FenceService.cs b/Libraries/SPTarkov.Server.Core/Services/FenceService.cs index 56e0f202..d823c147 100644 --- a/Libraries/SPTarkov.Server.Core/Services/FenceService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/FenceService.cs @@ -1158,7 +1158,7 @@ public class FenceService( var durabilityValues = GetRandomisedArmorDurabilityValues(modItemDbDetails, traderConfig.Fence.ArmorMaxDurabilityPercentMinMax); var plateTpl = requiredSlot.Props.Filters.First().Plate ?? string.Empty; // "Plate" property appears to be the 'default' item for slot - if (plateTpl.IsEmpty()) + if (plateTpl.IsEmpty) // Some bsg plate properties are empty, skip mod { continue; @@ -1206,7 +1206,7 @@ public class FenceService( foreach (var plateSlot in plateSlots) { var plateTpl = plateSlot.Props.Filters.First().Plate; - if (plateTpl == null || plateTpl.Value.IsEmpty()) + if (plateTpl == null || plateTpl.Value.IsEmpty) // Bsg data lacks a default plate, skip randomising for this mod { continue; diff --git a/Libraries/SPTarkov.Server.Core/Services/ItemBaseClassService.cs b/Libraries/SPTarkov.Server.Core/Services/ItemBaseClassService.cs index 2ed8573d..5c2a55d2 100644 --- a/Libraries/SPTarkov.Server.Core/Services/ItemBaseClassService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/ItemBaseClassService.cs @@ -65,7 +65,7 @@ public class ItemBaseClassService( _itemBaseClassesCache[itemIdToUpdate].Add(item.Parent); databaseService.GetItems().TryGetValue(item.Parent, out var parent); - if (parent is not null && !parent.Parent.IsEmpty()) + if (parent is not null && !parent.Parent.IsEmpty) { AddBaseItems(itemIdToUpdate, parent); } @@ -84,7 +84,7 @@ public class ItemBaseClassService( HydrateItemBaseClassCache(); } - if (itemTpl.IsEmpty()) + if (itemTpl.IsEmpty) { logger.Warning("Unable to check itemTpl base class as value passed is null"); @@ -136,7 +136,7 @@ public class ItemBaseClassService( HydrateItemBaseClassCache(); } - if (itemTpl.IsEmpty()) + if (itemTpl.IsEmpty) { logger.Warning("Unable to check itemTpl base class as value passed is null"); diff --git a/Libraries/SPTarkov.Server.Core/Services/NotificationService.cs b/Libraries/SPTarkov.Server.Core/Services/NotificationService.cs index 3b1e0567..68c3a1d3 100644 --- a/Libraries/SPTarkov.Server.Core/Services/NotificationService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/NotificationService.cs @@ -56,7 +56,7 @@ public class NotificationService /// Session/player id public List Get(MongoId sessionID) { - if (sessionID.IsEmpty()) + if (sessionID.IsEmpty) { throw new Exception("sessionID missing"); } diff --git a/Libraries/SPTarkov.Server.Core/Services/ProfileFixerService.cs b/Libraries/SPTarkov.Server.Core/Services/ProfileFixerService.cs index c982a10a..512fe6d4 100644 --- a/Libraries/SPTarkov.Server.Core/Services/ProfileFixerService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/ProfileFixerService.cs @@ -581,7 +581,7 @@ public class ProfileFixerService( protected Bonus? GetBonusFromProfile(IEnumerable? profileBonuses, Bonus bonus) { // match by id first, used by "TextBonus" bonuses - if (!bonus.Id.IsEmpty()) + if (!bonus.Id.IsEmpty) { return profileBonuses?.FirstOrDefault(x => x.Id == bonus.Id); } diff --git a/Libraries/SPTarkov.Server.Core/Utils/RagfairOfferHolder.cs b/Libraries/SPTarkov.Server.Core/Utils/RagfairOfferHolder.cs index e4c27f14..3f897714 100644 --- a/Libraries/SPTarkov.Server.Core/Utils/RagfairOfferHolder.cs +++ b/Libraries/SPTarkov.Server.Core/Utils/RagfairOfferHolder.cs @@ -143,7 +143,7 @@ public class RagfairOfferHolder( var itemTpl = offer.Items?.FirstOrDefault()?.Template ?? new MongoId(); if ( - !itemTpl.IsEmpty() // Has tpl + !itemTpl.IsEmpty // Has tpl && offer.IsFakePlayerOffer() && _fakePlayerOffers.TryGetValue(itemTpl, out var offers) && offers?.Count >= _ragfairServerHelper.GetOfferCountByBaseType(_itemHelper.GetItem(itemTpl).Value.Parent)