diff --git a/Libraries/Core/Callbacks/RagfairCallbacks.cs b/Libraries/Core/Callbacks/RagfairCallbacks.cs index 038c20c2..ce96ebfb 100644 --- a/Libraries/Core/Callbacks/RagfairCallbacks.cs +++ b/Libraries/Core/Callbacks/RagfairCallbacks.cs @@ -19,6 +19,7 @@ public class RagfairCallbacks( RagfairServer _ragfairServer, RagfairController _ragfairController, RagfairTaxService _ragfairTaxService, + RagfairPriceService _ragfairPriceService, ConfigServer _configServer ) : OnLoad, OnUpdate { @@ -27,6 +28,7 @@ public class RagfairCallbacks( public Task OnLoad() { _ragfairServer.Load(); + _ragfairPriceService.Load(); return Task.CompletedTask; } diff --git a/Libraries/Core/Controllers/RagfairController.cs b/Libraries/Core/Controllers/RagfairController.cs index 017bbf5c..75823257 100644 --- a/Libraries/Core/Controllers/RagfairController.cs +++ b/Libraries/Core/Controllers/RagfairController.cs @@ -223,21 +223,33 @@ public class RagfairController * @param offer Flea offer to update * @param fullProfile Players full profile */ - private void SetTraderOfferPurchaseLimits(RagfairOffer offer, SptProfile fullProfile) + private void SetTraderOfferPurchaseLimits(RagfairOffer offerToUpdate, SptProfile fullProfile) { - // No trader found, create a blank record for them - fullProfile.TraderPurchases[offer.User.Id] ??= new(); + var assortId = offerToUpdate.Items.First().Id; - var traderAssorts = _traderHelper.GetTraderAssortsByTraderId(offer.User.Id).Items; - var assortId = offer.Items.First().Id; - var assortData = traderAssorts.FirstOrDefault((item) => item.Id == assortId); + // No trader found in profile, create a blank record for them + var existsInProfile = !fullProfile.TraderPurchases.TryAdd(offerToUpdate.User.Id, new Dictionary()); + if (!existsInProfile) + { + // Not purchased by player before, use value from assort data - // Use value stored in profile, otherwise use value directly from in-memory trader assort data - offer.BuyRestrictionCurrent = (int)(fullProfile.TraderPurchases[offer.User.Id][assortId] is not null - ? fullProfile.TraderPurchases[offer.User.Id][assortId].PurchaseCount - : assortData.Upd.BuyRestrictionCurrent); + // Find patching assort by its id + var traderAssorts = _traderHelper.GetTraderAssortsByTraderId(offerToUpdate.User.Id).Items; + var assortData = traderAssorts.FirstOrDefault((item) => item.Id == assortId); - offer.BuyRestrictionMax = assortData.Upd.BuyRestrictionMax; + // Set restriction based on data found above + offerToUpdate.BuyRestrictionMax = assortData.Upd.BuyRestrictionMax; + + return; + } + + // Get purchases player made with trader since last reset + var traderPurchases = fullProfile.TraderPurchases[offerToUpdate.User.Id]; + + // Get specific assort purchase data and set current purchase buy value + traderPurchases.TryGetValue(assortId, out var assortTraderPurchaseData); + + offerToUpdate.BuyRestrictionCurrent = (int?)assortTraderPurchaseData?.PurchaseCount ?? 0; } /** @@ -292,7 +304,7 @@ public class RagfairController */ private bool IsLinkedSearch(SearchRequestData searchRequest) { - return searchRequest.LinkedSearchId != ""; + return !string.IsNullOrEmpty(searchRequest.LinkedSearchId); } /** @@ -302,7 +314,7 @@ public class RagfairController */ private bool IsRequiredSearch(SearchRequestData searchRequest) { - return searchRequest.NeededSearchId != ""; + return !string.IsNullOrEmpty(searchRequest.NeededSearchId); } /** @@ -317,7 +329,7 @@ public class RagfairController PmcData pmcProfile) { // Searching for items in preset menu - if (searchRequest.BuildCount is not null) + if (searchRequest.BuildCount > 0) { return _ragfairOfferHelper.GetOffersForBuild(searchRequest, itemsToAdd, traderAssorts, pmcProfile); } diff --git a/Libraries/Core/Helpers/RagfairHelper.cs b/Libraries/Core/Helpers/RagfairHelper.cs index df0c54fd..1a942d22 100644 --- a/Libraries/Core/Helpers/RagfairHelper.cs +++ b/Libraries/Core/Helpers/RagfairHelper.cs @@ -1,4 +1,4 @@ -using SptCommon.Annotations; +using SptCommon.Annotations; using Core.Models.Eft.Common.Tables; using Core.Models.Eft.Ragfair; using Core.Models.Enums; @@ -50,12 +50,12 @@ public class RagfairHelper( var result = new List(); // Case: weapon builds - if (request.BuildCount != null) { + if (request.BuildCount > 0) { return request.BuildItems.Keys.ToList(); } // Case: search - if (request.LinkedSearchId != null) { + if (!string.IsNullOrEmpty(request.LinkedSearchId)) { var data = ragfairLinkedItemService.GetLinkedItems(request.LinkedSearchId); result = data == null ? [] : [..data]; } diff --git a/Libraries/Core/Helpers/RagfairOfferHelper.cs b/Libraries/Core/Helpers/RagfairOfferHelper.cs index 39b2c5f3..89b5c6e3 100644 --- a/Libraries/Core/Helpers/RagfairOfferHelper.cs +++ b/Libraries/Core/Helpers/RagfairOfferHelper.cs @@ -362,7 +362,7 @@ public class RagfairOfferHelper( // Performing a required search and offer doesn't have requirement for item if ( - searchRequest.NeededSearchId is not null && + !string.IsNullOrEmpty(searchRequest.NeededSearchId) && !offer.Requirements.Any(requirement => requirement.Template == searchRequest.NeededSearchId) ) { diff --git a/Libraries/Core/Helpers/RagfairSortHelper.cs b/Libraries/Core/Helpers/RagfairSortHelper.cs index caffcdea..21f4ecd5 100644 --- a/Libraries/Core/Helpers/RagfairSortHelper.cs +++ b/Libraries/Core/Helpers/RagfairSortHelper.cs @@ -1,11 +1,13 @@ -using SptCommon.Annotations; +using SptCommon.Annotations; using Core.Models.Eft.Ragfair; using Core.Models.Enums; +using Core.Services; namespace Core.Helpers; [Injectable] -public class RagfairSortHelper +public class RagfairSortHelper( + LocaleService _localeService) { /** * Sort a list of ragfair offers by something (id/rating/offer name/price/expiry time) @@ -16,27 +18,71 @@ public class RagfairSortHelper */ public List SortOffers(List offers, RagfairSort type, int direction = 0) { - throw new NotImplementedException(); + // Sort results + switch (type) + { + case RagfairSort.ID: + offers.Sort(SortOffersByID); + break; + + case RagfairSort.BARTER: + offers.Sort(SortOffersByBarter); + break; + + case RagfairSort.RATING: + offers.Sort(SortOffersByRating); + break; + + case RagfairSort.OFFER_TITLE: + offers.Sort((a, b) => SortOffersByName(a, b)); + break; + + case RagfairSort.PRICE: + offers.Sort(SortOffersByPrice); + break; + + case RagfairSort.EXPIRY: + offers.Sort(SortOffersByExpiry); + break; + } + + // 0=ASC 1=DESC + if (direction == 1) + { + offers.Reverse(); + } + + return offers; } protected int SortOffersByID(RagfairOffer a, RagfairOffer b) { - throw new NotImplementedException(); + return a.InternalId.Value - b.InternalId.Value; } protected int SortOffersByBarter(RagfairOffer a, RagfairOffer b) { - throw new NotImplementedException(); + var aIsOnlyMoney = a.Requirements.Count == 1 && Money.GetMoneyTpls().Contains(a.Requirements[0].Template) ? 1 : 0; + var bIsOnlyMoney = b.Requirements.Count == 1 && Money.GetMoneyTpls().Contains(b.Requirements[0].Template) ? 1 : 0; + + return aIsOnlyMoney - bIsOnlyMoney; } protected int SortOffersByRating(RagfairOffer a, RagfairOffer b) { - throw new NotImplementedException(); + return (int)(a.User.Rating.Value - b.User.Rating.Value); } protected int SortOffersByName(RagfairOffer a, RagfairOffer b) { - throw new NotImplementedException(); + var locale = _localeService.GetLocaleDb(); + + var tplA = a.Items[0].Template; + var tplB = b.Items[0].Template; + var nameA = locale.GetValueOrDefault($"{tplA} Name", tplA); + var nameB = locale.GetValueOrDefault($"{tplB} Name", tplB); + + return string.Compare(nameA, nameB); } /** @@ -47,11 +93,11 @@ public class RagfairSortHelper */ protected int SortOffersByPrice(RagfairOffer a, RagfairOffer b) { - throw new NotImplementedException(); + return (int)(a.RequirementsCost.Value - b.RequirementsCost.Value); } protected int SortOffersByExpiry(RagfairOffer a, RagfairOffer b) { - throw new NotImplementedException(); + return (int)(a.EndTime - b.EndTime); } } diff --git a/Libraries/Core/Models/Enums/Money.cs b/Libraries/Core/Models/Enums/Money.cs index 821485a1..c108be23 100644 --- a/Libraries/Core/Models/Enums/Money.cs +++ b/Libraries/Core/Models/Enums/Money.cs @@ -1,4 +1,4 @@ -namespace Core.Models.Enums; +namespace Core.Models.Enums; public record Money { @@ -6,4 +6,9 @@ public record Money public const string EUROS = "569668774bdc2da2298b4568"; public const string DOLLARS = "5696686a4bdc2da3298b456a"; public const string GP = "5d235b4d86f7742e017bc88a"; + + public static List GetMoneyTpls() + { + return [ROUBLES, EUROS, DOLLARS, GP]; + } } diff --git a/Libraries/Core/Services/ItemBaseClassService.cs b/Libraries/Core/Services/ItemBaseClassService.cs index b26f66b6..140394df 100644 --- a/Libraries/Core/Services/ItemBaseClassService.cs +++ b/Libraries/Core/Services/ItemBaseClassService.cs @@ -1,4 +1,4 @@ -using SptCommon.Annotations; +using SptCommon.Annotations; using Core.Models.Eft.Common.Tables; using Core.Models.Utils; @@ -49,7 +49,7 @@ public class ItemBaseClassService( _itemBaseClassesCache[itemIdToUpdate].Add(item.Parent); var parent = _databaseService.GetItems()[item.Parent]; - if (parent.Parent != "") + if (!string.IsNullOrEmpty(parent.Parent)) { AddBaseItems(itemIdToUpdate, parent); } diff --git a/Libraries/Core/Services/RagfairPriceService.cs b/Libraries/Core/Services/RagfairPriceService.cs index 1873faaa..677beab7 100644 --- a/Libraries/Core/Services/RagfairPriceService.cs +++ b/Libraries/Core/Services/RagfairPriceService.cs @@ -30,7 +30,7 @@ public class RagfairPriceService( /// /// Generate static (handbook) and dynamic (prices.json) flea prices, store inside class as dictionaries /// - public async Task OnLoadAsync() + public void Load() { RefreshStaticPrices(); RefreshDynamicPrices(); @@ -133,8 +133,10 @@ public class RagfairPriceService( public Dictionary GetAllFleaPrices() { var dynamicPrices = _databaseService.GetPrices(); - // { ...this.prices.dynamic, ...this.prices.static }; - return dynamicPrices.Concat(_staticPrices).ToDictionary(); + // Use dynamic prices first, fill in any gaps with data from static prices (handbook) + return dynamicPrices.Concat(_staticPrices) + .GroupBy(x => x.Key) + .ToDictionary(x => x.Key, x => x.First().Value); } public Dictionary GetAllStaticPrices()