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; + } } } diff --git a/Core/Controllers/GameController.cs b/Core/Controllers/GameController.cs index 08cbfb46..38b8d18a 100644 --- a/Core/Controllers/GameController.cs +++ b/Core/Controllers/GameController.cs @@ -1,10 +1,15 @@ using Core.Annotations; +using Core.Context; +using Core.Helpers; using Core.Models.Eft.Common; using Core.Models.Eft.Game; using Core.Models.Eft.Profile; using Core.Models.Enums; using Core.Models.Spt.Config; using Core.Servers; +using Core.Services; +using Core.Utils; +using Core.Utils.Cloners; using ILogger = Core.Models.Utils.ILogger; namespace Core.Controllers; @@ -12,19 +17,86 @@ namespace Core.Controllers; [Injectable] public class GameController { - private readonly ConfigServer _configServer; private readonly ILogger _logger; + private readonly ConfigServer _configServer; + private readonly DatabaseService _databaseService; + private readonly TimeUtil _timeUtil; + // private readonly PreSptModLoader _preSptModLoader; + private readonly HttpServerHelper _httpServerHelper; + private readonly InventoryHelper _inventoryHelper; + private readonly RandomUtil _randomUtil; + private readonly HideoutHelper _hideoutHelper; + private readonly ProfileHelper _profileHelper; + private readonly ProfileFixerService _profileFixerService; + private readonly LocalisationService _localisationService; + private readonly PostDbLoadService _postDbLoadService; + private readonly CustomLocationWaveService _customLocationWaveService; + private readonly OpenZoneService _openZoneService; + private readonly SeasonalEventService _seasonalEventService; + private readonly ItemBaseClassService _itemBaseClassService; + private readonly GiftService _giftService; + private readonly RaidTimeAdjustmentService _raidTimeAdjustmentService; + private readonly ProfileActivityService _profileActivityService; + private readonly ApplicationContext _applicationContext; + private readonly ICloner _cloner; + private readonly CoreConfig _coreConfig; - + private readonly HttpConfig _httpConfig; + private readonly RagfairConfig _ragfairConfig; + private readonly HideoutConfig _hideoutConfig; + private readonly BotConfig _botConfig; public GameController( ILogger logger, - ConfigServer configServer) + ConfigServer configServer, + DatabaseService databaseService, + TimeUtil timeUtil, + HttpServerHelper httpServerHelper, + InventoryHelper inventoryHelper, + RandomUtil randomUtil, + HideoutHelper hideoutHelper, + ProfileHelper profileHelper, + ProfileFixerService profileFixerService, + LocalisationService localisationService, + PostDbLoadService postDbLoadService, + CustomLocationWaveService customLocationWaveService, + OpenZoneService openZoneService, + SeasonalEventService seasonalEventService, + ItemBaseClassService itemBaseClassService, + GiftService giftService, + RaidTimeAdjustmentService raidTimeAdjustmentService, + ProfileActivityService profileActivityService, + ApplicationContext applicationContext, + ICloner cloner + ) { _logger = logger; _configServer = configServer; + _databaseService = databaseService; + _timeUtil = timeUtil; + _httpServerHelper = httpServerHelper; + _inventoryHelper = inventoryHelper; + _randomUtil = randomUtil; + _hideoutHelper = hideoutHelper; + _profileHelper = profileHelper; + _profileFixerService = profileFixerService; + _localisationService = localisationService; + _postDbLoadService = postDbLoadService; + _customLocationWaveService = customLocationWaveService; + _openZoneService = openZoneService; + _seasonalEventService = seasonalEventService; + _itemBaseClassService = itemBaseClassService; + _giftService = giftService; + _raidTimeAdjustmentService = raidTimeAdjustmentService; + _profileActivityService = profileActivityService; + _applicationContext = applicationContext; + _cloner = cloner; _coreConfig = configServer.GetConfig(ConfigTypes.CORE); + _httpConfig = configServer.GetConfig(ConfigTypes.HTTP); + _ragfairConfig = configServer.GetConfig(ConfigTypes.RAGFAIR); + _hideoutConfig = configServer.GetConfig(ConfigTypes.HIDEOUT); + _botConfig = configServer.GetConfig(ConfigTypes.BOT); } /// @@ -34,11 +106,93 @@ public class GameController /// /// /// - public void GameStart( - string url, - EmptyRequestData info, - string sessionId, - long startTimeStampMs) + public void GameStart(string url, EmptyRequestData info, string sessionId, long startTimeStampMs) + { + // Store client start time in app context + _applicationContext.AddValue(ContextVariableType.CLIENT_START_TIMESTAMP, $"{sessionId}_{startTimeStampMs}"); + + _profileActivityService.SetActivityTimestamp(sessionId); + + // repeatableQuests are stored by in profile.Quests due to the responses of the client (e.g. Quests in + // offraidData). Since we don't want to clutter the Quests list, we need to remove all completed (failed or + // successful) repeatable quests. We also have to remove the Counters from the repeatableQuests + if (sessionId != null) + { + var fullProfile = _profileHelper.GetFullProfile(sessionId); + if (fullProfile.ProfileInfo.IsWiped.Value) + return; + + if (fullProfile.SptData.Migrations == null) + fullProfile.SptData.Migrations = new(); + + if (fullProfile.FriendProfileIds == null) + fullProfile.FriendProfileIds = new(); + + if (fullProfile.SptData.Version.Contains("3.9.") && !fullProfile.SptData.Migrations.Any(m => m.Key == "39x")) + { + _inventoryHelper.ValidateInventoryUsesMongoIds(fullProfile.CharacterData.PmcData.Inventory.Items); + Migrate39xProfile(fullProfile); + + // flag as migrated + fullProfile.SptData.Migrations.Add("39x", _timeUtil.GetTimeStamp()); + _logger.Success($"Migration of 3.9.x profile: {fullProfile.ProfileInfo.Username} completed successfully"); + } + + // with our method of converting type from array for this prop, we *might* not need this? + // if (Array.isArray(fullProfile.characters.pmc.WishList)) { + // fullProfile.characters.pmc.WishList = {}; + // } + // + // if (Array.isArray(fullProfile.characters.scav.WishList)) { + // fullProfile.characters.scav.WishList = {}; + // } + + if (fullProfile.DialogueRecords != null) + _profileFixerService.CheckForAndFixDialogueAttachments(fullProfile); + + _logger.Debug($"Started game with session {sessionId} {fullProfile.ProfileInfo.Username}"); + + var pmcProfile = fullProfile.CharacterData.PmcData; + + if (_coreConfig.Fixes.FixProfileBreakingInventoryItemIssues) + _profileFixerService.FixProfileBreakingInventoryItemIssues(pmcProfile); + + if (pmcProfile.Health != null) + UpdateProfileHealthValues(pmcProfile); + + if (pmcProfile.Inventory != null) + { + SendPraporGiftsToNewProfiles(pmcProfile); + _profileFixerService.CheckForOrphanedModdedItems(sessionId, fullProfile); + } + + _profileFixerService.CheckForAndRemoveInvalidTraders(fullProfile); + _profileFixerService.CheckForAndFixPmcProfileIssues(pmcProfile); + + if (pmcProfile.Hideout != null) + { + _profileFixerService.AddMissingHideoutBonusesToProfile(pmcProfile); + _hideoutHelper.SetHideoutImprovementsToCompleted(pmcProfile); + _hideoutHelper.UnlockHideoutWallInProfile(pmcProfile); + } + + LogProfileDetails(fullProfile); + SaveActiveModsToProfile(fullProfile); + + if (pmcProfile.Info != null) + { + AddPlayerToPmcNames(pmcProfile); + CheckForAndRemoveUndefinedDialogues(fullProfile); + } + + if (pmcProfile.Skills.Common != null) + WarnOnActiveBotReloadSkill(pmcProfile); + + _seasonalEventService.GivePlayerSeasonalGifts(sessionId); + } + } + + private void Migrate39xProfile(SptProfile fullProfile) { throw new NotImplementedException(); } @@ -210,6 +364,6 @@ public class GameController public void Load() { - return; // TODO: actually implement + _postDbLoadService.PerformPostDbLoadActions(); } } diff --git a/Core/Controllers/LauncherController.cs b/Core/Controllers/LauncherController.cs index 2c44cc39..c154717a 100644 --- a/Core/Controllers/LauncherController.cs +++ b/Core/Controllers/LauncherController.cs @@ -106,7 +106,7 @@ public class LauncherController { foreach (var sessionID in _saveServer.GetProfiles()) { var account = _saveServer.GetProfile(sessionID.Key).ProfileInfo; - if (info.Username == account.UserName) { + if (info.Username == account.Username) { return sessionID.Key; } } @@ -117,7 +117,7 @@ public class LauncherController public string Register(RegisterData info) { foreach (var sessionID in _saveServer.GetProfiles()) { - if (info.Username == _saveServer.GetProfile(sessionID.Key).ProfileInfo.UserName) { + if (info.Username == _saveServer.GetProfile(sessionID.Key).ProfileInfo.Username) { return ""; } } @@ -133,7 +133,7 @@ public class LauncherController ProfileId = profileId, ScavengerId = scavId, Aid = _hashUtil.GenerateAccountId(), - UserName = info.Username, + Username = info.Username, Password = info.Password, IsWiped = true, Edition = info.Edition, @@ -167,7 +167,7 @@ public class LauncherController var sessionID = Login(info); if (!string.IsNullOrEmpty(sessionID)) { - _saveServer.GetProfile(sessionID).ProfileInfo.UserName = info.Change; + _saveServer.GetProfile(sessionID).ProfileInfo.Username = info.Change; } return sessionID; diff --git a/Core/Controllers/ProfileController.cs b/Core/Controllers/ProfileController.cs index 0cfbfc2b..8485f208 100644 --- a/Core/Controllers/ProfileController.cs +++ b/Core/Controllers/ProfileController.cs @@ -107,7 +107,7 @@ public class ProfileController { return new MiniProfile() { - Username = profile.ProfileInfo?.UserName ?? "", + Username = profile.ProfileInfo?.Username ?? "", Nickname = "unknown", Side = "unknown", CurrentLevel = 0, @@ -125,7 +125,7 @@ public class ProfileController var nextlvl = _profileHelper.GetExperience((int)(currlvl + 1)); return new MiniProfile() { - Username = profile.ProfileInfo.UserName, + Username = profile.ProfileInfo.Username, Nickname = pmc.Info.Nickname, Side = pmc.Info.Side, CurrentLevel = (int)(pmc.Info.Level), @@ -167,7 +167,7 @@ public class ProfileController pmcData.Savage = account.ScavengerId; pmcData.SessionId = sessionID; pmcData.Info.Nickname = info.Nickname; - pmcData.Info.LowerNickname = account.UserName.ToLower(); + pmcData.Info.LowerNickname = account.Username.ToLower(); pmcData.Info.RegistrationDate = _timeUtil.GetTimeStamp(); pmcData.Info.Voice = _databaseService.GetCustomization()[info.VoiceId].Name; pmcData.Stats = _profileHelper.GetDefaultCounters(); diff --git a/Core/Helpers/PresetHelper.cs b/Core/Helpers/PresetHelper.cs index 95b85d8a..08bee62d 100644 --- a/Core/Helpers/PresetHelper.cs +++ b/Core/Helpers/PresetHelper.cs @@ -77,12 +77,12 @@ public class PresetHelper _itemHelper.ArmorItemCanHoldMods(p.Value.Encyclopedia)).ToDictionary(); } - return _defaultWeaponPresets; + return _defaultEquipmentPresets; } public bool IsPreset(string id) { - throw new NotImplementedException(); + return _databaseService.GetGlobals().ItemPresets.ContainsKey(id); } /** diff --git a/Core/Models/Eft/Common/Tables/Item.cs b/Core/Models/Eft/Common/Tables/Item.cs index e018f0ad..f4e885f5 100644 --- a/Core/Models/Eft/Common/Tables/Item.cs +++ b/Core/Models/Eft/Common/Tables/Item.cs @@ -23,7 +23,7 @@ public class Item public string? Desc { get; set; } [JsonPropertyName("upd")] - public Upd? Update { get; set; } + public Upd? Upd { get; set; } } public class ItemLocation diff --git a/Core/Models/Eft/Common/Tables/TemplateItem.cs b/Core/Models/Eft/Common/Tables/TemplateItem.cs index 4b2ec2ed..6b2e2ef7 100644 --- a/Core/Models/Eft/Common/Tables/TemplateItem.cs +++ b/Core/Models/Eft/Common/Tables/TemplateItem.cs @@ -1350,6 +1350,9 @@ public class Props [JsonPropertyName("Hands")] public string? Hands { get; set; } + [JsonPropertyName("Feet")] + public string? Feet { get; set; } + [JsonExtensionData] public Dictionary OtherProperties { get; set; } } diff --git a/Core/Models/Eft/Profile/SptProfile.cs b/Core/Models/Eft/Profile/SptProfile.cs index 265070eb..44ff731e 100644 --- a/Core/Models/Eft/Profile/SptProfile.cs +++ b/Core/Models/Eft/Profile/SptProfile.cs @@ -71,7 +71,7 @@ public class Info public int? Aid { get; set; } [JsonPropertyName("username")] - public string? UserName { get; set; } + public string? Username { get; set; } [JsonPropertyName("password")] public string? Password { get; set; } diff --git a/Core/Models/Enums/GameEditions.cs b/Core/Models/Enums/GameEditions.cs new file mode 100644 index 00000000..a89d3a4e --- /dev/null +++ b/Core/Models/Enums/GameEditions.cs @@ -0,0 +1,11 @@ +namespace Core.Models.Enums; + +public class GameEditions +{ + public const string STANDARD = "standard"; + public const string LEFT_BEHIND = "left_behind"; + public const string PREPARE_FOR_ESCAPE = "prepare_for_escape"; + public const string EDGE_OF_DARKNESS = "edge_of_darkness"; + public const string UNHEARD = "unheard_edition"; + public const string TOURNAMENT = "tournament_live"; +} diff --git a/Core/Routers/Dynamic/CustomizationDynamicRouter.cs b/Core/Routers/Dynamic/CustomizationDynamicRouter.cs index cd91d78b..73f84379 100644 --- a/Core/Routers/Dynamic/CustomizationDynamicRouter.cs +++ b/Core/Routers/Dynamic/CustomizationDynamicRouter.cs @@ -18,7 +18,7 @@ public class CustomizationDynamicRouter : DynamicRouter jsonUtil, [ new RouteAction( - "", + "/client/trading/customization/", ( url, info,