From 3f0d68dbf65df38518c21a66bb6f95ddd166a47b Mon Sep 17 00:00:00 2001 From: Chomp Date: Sun, 17 Aug 2025 15:47:03 +0100 Subject: [PATCH] Minor refresh of `RagfairRequiredItemsService` Adding a new set + lookup is now atomic Returns a readonly set, caller shouldn't be able to ever modify this data Removed memory allocation when calling `GetRequiredOffersById` with a tpl that doesn't have any offerIds --- .../Services/RagfairRequiredItemsService.cs | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/Libraries/SPTarkov.Server.Core/Services/RagfairRequiredItemsService.cs b/Libraries/SPTarkov.Server.Core/Services/RagfairRequiredItemsService.cs index 0bea2005..3a96a4df 100644 --- a/Libraries/SPTarkov.Server.Core/Services/RagfairRequiredItemsService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/RagfairRequiredItemsService.cs @@ -11,43 +11,46 @@ public class RagfairRequiredItemsService(RagfairOfferService ragfairOfferService /// /// Key = tpl /// - protected readonly ConcurrentDictionary> _requiredItemsCache = new(); + protected readonly ConcurrentDictionary> RequiredItemsCache = new(); + + /// + /// Empty hashset to be returned when no keys found by GetRequiredOffersById (reduces memory allocations) + /// + protected readonly IReadOnlySet EmptyOfferIdSet = new HashSet(); /// /// Get the offerId of offers that require the supplied tpl /// /// Tpl to find offers ids for - /// - public HashSet GetRequiredOffersById(MongoId tpl) + /// Set of OfferIds + public IReadOnlySet GetRequiredOffersById(MongoId tpl) { - if (_requiredItemsCache.TryGetValue(tpl, out var offerIds)) - { - return offerIds; - } - - return []; + return RequiredItemsCache.TryGetValue(tpl, out var offerIds) ? offerIds : EmptyOfferIdSet; } /// - /// Create a cache of requirements to purchase item + /// Create a cache of offer Ids keyed against the item tpl they require /// public void BuildRequiredItemTable() { - _requiredItemsCache.Clear(); + RequiredItemsCache.Clear(); foreach (var offer in ragfairOfferService.GetOffers()) - foreach (var requirement in offer.Requirements) { - if (paymentHelper.IsMoneyTpl(requirement.TemplateId)) - // This would just be too noisy + foreach (var requirement in offer.Requirements ?? []) { - continue; + // Skip offers for currency, it's too expensive to process + // Only process barter offers + if (paymentHelper.IsMoneyTpl(requirement.TemplateId)) + { + continue; + } + + // Ensure cache has Hashset init for this tpl + var offerIds = RequiredItemsCache.GetOrAdd(requirement.TemplateId, _ => []); + + // Add offer id against the tpl key + offerIds.Add(offer.Id); } - - // Ensure key is init - _requiredItemsCache.TryAdd(requirement.TemplateId, []); - - // Add matching offer - _requiredItemsCache.GetValueOrDefault(requirement.TemplateId)?.Add(offer.Id); } } }