diff --git a/Core/Controllers/CustomizationController.cs b/Core/Controllers/CustomizationController.cs index 10b34c00..cdcc8071 100644 --- a/Core/Controllers/CustomizationController.cs +++ b/Core/Controllers/CustomizationController.cs @@ -1,25 +1,71 @@ using Core.Annotations; +using Core.Helpers; using Core.Models.Eft.Common; using Core.Models.Eft.Common.Tables; using Core.Models.Eft.Customization; using Core.Models.Eft.Hideout; using Core.Models.Eft.ItemEvent; using Core.Models.Eft.Profile; +using Core.Models.Enums; +using Core.Routers; +using Core.Servers; +using Core.Services; +using Core.Utils.Cloners; +using ILogger = Core.Models.Utils.ILogger; +using Product = Core.Models.Eft.ItemEvent.Product; namespace Core.Controllers; [Injectable] public class CustomizationController { + protected ILogger _logger; + protected EventOutputHolder _eventOutputHolder; + protected DatabaseService _databaseService; + protected SaveServer _saveServer; + protected LocalisationService _localisationService; + protected ProfileHelper _profileHelper; + protected ICloner _cloner; + + public CustomizationController + ( + ILogger logger, + EventOutputHolder eventOutputHolder, + DatabaseService databaseService, + SaveServer saveServer, + LocalisationService localisationService, + ProfileHelper profileHelper, + ICloner cloner + ) + { + _logger = logger; + _eventOutputHolder = eventOutputHolder; + _databaseService = databaseService; + _saveServer = saveServer; + _localisationService = localisationService; + _profileHelper = profileHelper; + _cloner = cloner; + } + /// /// Get purchasable clothing items from trader that match players side (usec/bear) /// /// trader to look up clothing for /// Session id /// Suit array - public Suit GetTraderSuits(string traderId, string sessionId) + public List GetTraderSuits(string traderId, string sessionId) { - throw new NotImplementedException(); + var pmcData = _profileHelper.GetPmcProfile(sessionId); + var clothing = _databaseService.GetCustomization(); + var suits = _databaseService.GetTrader(traderId).Suits; + + var matchingSuits = suits.Where(s => clothing.ContainsKey(s.SuiteId)).ToList(); + matchingSuits = matchingSuits?.Where(s => clothing[s.SuiteId].Properties.Side.Contains(pmcData.Info.Side)).ToList(); + + if (matchingSuits == null) + throw new Exception(_localisationService.GetText("customisation-unable_to_get_trader_suits", traderId)); + + return matchingSuits; } /// @@ -35,7 +81,41 @@ public class CustomizationController BuyClothingRequestData buyClothingRequest, string sessionId) { - throw new NotImplementedException(); + var output = _eventOutputHolder.GetOutput(sessionId); + + var traderOffer = GetTraderClothingOffer(sessionId, buyClothingRequest.Offer); + if (traderOffer == null) + { + _logger.Error(_localisationService.GetText("customisation-unable_to_find_suit_by_id", buyClothingRequest.Offer)); + return output; + } + + var suitId = traderOffer.SuiteId; + if (OutfitAlreadyPurchased(suitId, sessionId)) + { + var suitDetails = _databaseService.GetCustomization()[suitId]; + _logger.Error(_localisationService.GetText("customisation-item_already_purchased", new + { + ItemId = suitDetails.Id, + ItemName = suitDetails.Name, + })); + } + + return output; + } + + private bool OutfitAlreadyPurchased(object suitId, string sessionId) + { + return _saveServer.GetProfile(sessionId).Suits.Contains(suitId); + } + + private Suit GetTraderClothingOffer(string sessionId, string? offerId) + { + var foundSuit = GetAllTraderSuits(sessionId).FirstOrDefault(s => s.Id == offerId); + if (foundSuit == null) + throw new Exception(_localisationService.GetText("customisation-unable_to_find_suit_with_id", offerId)); + + return foundSuit; } /// @@ -45,13 +125,13 @@ public class CustomizationController /// Player profile /// Clothing purchased /// Client response - private void PayForClothingItems( - string sessionId, - PmcData pmcData, - List itemsToPayForClothingWith, + private void PayForClothingItems(string sessionId, PmcData pmcData, List itemsToPayForClothingWith, ItemEventRouterResponse output) { - throw new NotImplementedException(); + foreach (var inventoryItemToProcess in itemsToPayForClothingWith) + { + PayForClothingItem(sessionId, pmcData, inventoryItemToProcess, output); + } } /// @@ -61,13 +141,65 @@ public class CustomizationController /// Player profile /// Payment details /// Client response - private void PayForClothingItem( - string sessionId, - PmcData pmcData, - PaymentItemForClothing paymentItemDetails, - ItemEventRouterResponse output) + private void PayForClothingItem(string sessionId, PmcData pmcData, PaymentItemForClothing paymentItemDetails, ItemEventRouterResponse output) { - throw new NotImplementedException(); + var inventoryItem = pmcData.Inventory.Items.FirstOrDefault(x => x.Id == paymentItemDetails.Id); + if (inventoryItem == null) + { + _logger.Error(_localisationService.GetText("customisation-unable_to_find_clothing_item_in_inventory", paymentItemDetails.Id)); + return; + } + + if (paymentItemDetails.Del != null) + { + output.ProfileChanges[sessionId].Items.DeletedItems.Add(new Product + { + Id = inventoryItem.Id, + Template = inventoryItem.Template, + ParentId = inventoryItem.ParentId, + SlotId = inventoryItem.SlotId, + Location = (ItemLocation)inventoryItem.Location, + Upd = inventoryItem.Upd + }); + + pmcData.Inventory.Items.Remove(inventoryItem); + } + + if (inventoryItem.Upd == null) + inventoryItem.Upd = new() { StackObjectsCount = 1 }; + + if (inventoryItem.Upd.StackObjectsCount == null) + inventoryItem.Upd.StackObjectsCount = 1; + + if (inventoryItem.Upd.StackObjectsCount == paymentItemDetails.Count) + { + output.ProfileChanges[sessionId].Items.DeletedItems.Add(new Product + { + Id = inventoryItem.Id, + Template = inventoryItem.Template, + ParentId = inventoryItem.ParentId, + SlotId = inventoryItem.SlotId, + Location = (ItemLocation)inventoryItem.Location, + Upd = inventoryItem.Upd + }); + + pmcData.Inventory.Items.Remove(inventoryItem); + return; + } + + if (inventoryItem.Upd.StackObjectsCount > paymentItemDetails.Count) + { + inventoryItem.Upd.StackObjectsCount -= paymentItemDetails.Count; + output.ProfileChanges[sessionId].Items.ChangedItems.Add(new Product + { + Id = inventoryItem.Id, + Template = inventoryItem.Template, + ParentId = inventoryItem.ParentId, + SlotId = inventoryItem.SlotId, + Location = (ItemLocation)inventoryItem.Location, + Upd = inventoryItem.Upd + }); + } } /// @@ -77,7 +209,16 @@ public class CustomizationController /// private List GetAllTraderSuits(string sessionId) { - throw new NotImplementedException(); + var traders = _databaseService.GetTraders(); + var result = new List(); + + foreach (var trader in traders) + { + if (trader.Value.Base.CustomizationSeller.Value) + result.AddRange(GetTraderSuits(trader.Key, sessionId)); + } + + return result; } /// @@ -86,11 +227,9 @@ public class CustomizationController /// /// /// - public HideoutCustomisation GetHideoutCustomisation( - string sessionId, - EmptyRequestData info) + public HideoutCustomisation GetHideoutCustomisation(string sessionId, EmptyRequestData info) { - throw new NotImplementedException(); + return _databaseService.GetHideout().Customisation; } /// @@ -103,7 +242,79 @@ public class CustomizationController string sessionId, EmptyRequestData info) { - throw new NotImplementedException(); + var customisationResultsClone = _cloner.Clone(_databaseService.GetTemplates().CustomisationStorage); + + var profile = _profileHelper.GetFullProfile(sessionId); + switch (GetGameEdition(profile)) + { + case GameEditions.EDGE_OF_DARKNESS: + customisationResultsClone.Add(new () + { + Id = "6746fd09bafff85008048838", + Source = "default", + Type = "dogTag" + }); + customisationResultsClone.Add(new () + { + Id = "67471938bafff850080488b7", + Source = "default", + Type = "dogTag" + }); + break; + case GameEditions.UNHEARD: + customisationResultsClone.Add(new () + { + Id = "6746fd09bafff85008048838", + Source = "default", + Type = "dogTag" + }); + customisationResultsClone.Add(new () + { + Id = "67471938bafff850080488b7", + Source = "default", + Type = "dogTag" + }); + customisationResultsClone.Add(new () + { + Id = "67471928d17d6431550563b5", + Source = "default", + Type = "dogTag" + }); + customisationResultsClone.Add(new () + { + Id = "6747193f170146228c0d2226", + Source = "default", + Type = "dogTag" + }); + break; + default: + throw new Exception($"Unknown game edition given from profile {profile}"); + } + + var prestigeLevel = profile.CharacterData.PmcData.Info.PrestigeLevel; + if (prestigeLevel != null) + { + if (prestigeLevel >= 1) + { + customisationResultsClone.Add(new () + { + Id = "674dbf593bee1152d407f005", + Source = "default", + Type = "dogTag" + }); + } + if (prestigeLevel >= 2) + { + customisationResultsClone.Add(new () + { + Id = "675dcfea7ae1a8792107ca99", + Source = "default", + Type = "dogTag" + }); + } + } + + return customisationResultsClone; } /// @@ -113,7 +324,22 @@ public class CustomizationController /// private string GetGameEdition(SptProfile profile) { - throw new NotImplementedException(); + var edition = profile.CharacterData.PmcData.Info.GameVersion; + if (edition == null) + { + var launcherEdition = profile.ProfileInfo.Edition; + switch (launcherEdition.ToLower()) + { + case "edge of darkness": + return GameEditions.EDGE_OF_DARKNESS; + case "unheard": + return GameEditions.UNHEARD; + default: + return GameEditions.STANDARD; + } + } + + return edition; } /// @@ -123,12 +349,25 @@ public class CustomizationController /// /// /// - public ItemEventRouterResponse SetClothing( - string sessionId, - CustomizationSetRequest request, - PmcData pmcData) + public ItemEventRouterResponse SetClothing(string sessionId, CustomizationSetRequest request, PmcData pmcData) { - throw new NotImplementedException(); + foreach (var customisation in request.Customizations) + { + switch (customisation.Id) + { + case "dogTag": + pmcData.Customization.DogTag = customisation.Id; + break; + case "suite": + ApplyClothingItemToProfile(customisation, pmcData); + break; + default: + _logger.Error($"Unhandled customisation type: {customisation.Type}"); + break; + } + } + + return _eventOutputHolder.GetOutput(sessionId); } /// @@ -136,10 +375,26 @@ public class CustomizationController /// /// Suit to apply to profile /// Profile to update - private void ApplyClothingItemToProfile( - CustomizationSetOption customization, - PmcData pmcData) + private void ApplyClothingItemToProfile(CustomizationSetOption customisation, PmcData pmcData) { - throw new NotImplementedException(); + var dbSuit = _databaseService.GetCustomization()[customisation.Id]; + if (dbSuit == null) + { + _logger.Error($"Unable to find suit customisation id: {customisation.Id}, cannot apply clothing to player profile: {pmcData.Id}"); + return; + } + + if (dbSuit.Parent == "5cd944d01388ce000a659df9") + { + pmcData.Customization.Body = dbSuit.Properties.Body; + pmcData.Customization.Hands = dbSuit.Properties.Hands; + + return; + } + + if (dbSuit.Parent == "5cd944ca1388ce03a44dc2a4") + { + pmcData.Customization.Feet = dbSuit.Properties.Feet; + } } }