using AssortGenerator.Common; using AssortGenerator.Common.Helpers; using AssortGenerator.Models.Input; using AssortGenerator.Models.Other; using AssortGenerator.Models.Output; using Common; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.Json; namespace AssortGenerator { public class Program { static void Main(string[] args) { var assortsPath = CreateWorkingFolders(); InputFileHelper.SetInputFiles(assortsPath); // Get trader assort files from assorts input folder var traderAssortFilePaths = InputFileHelper.GetInputFilePaths().Where(x => TraderHelper.GetTraders().Values.Any(x.Contains)).ToList(); foreach (var trader in TraderHelper.GetTraders()) { // Get relevant trader dump var assortDumpPath = traderAssortFilePaths.Find(x => x.Contains(trader.Value)); // convert input dump json into object var json = File.ReadAllText(assortDumpPath); var jsonObject = JsonDocument.Parse(json); // find root data node var data = jsonObject.RootElement.GetProperty("data"); // find items node and parse into object string itemsJson = data.GetProperty("items").ToString(); List items = JsonSerializer.Deserialize>(itemsJson); // fix items that have ran out of stock in the dump and give it some default values foreach (var item in items) { if (item.upd?.StackObjectsCount == 0 && item.slotId == "hideout") { LoggingHelpers.LogError($"item {item._tpl} found with stack count of 0, changing to 100"); item.upd.StackObjectsCount = 100; } } // Find barter scheme node and parse into object var barterSchemeJson = data.GetProperty("barter_scheme").ToString(); var barterSchemeItems = JsonSerializer.Deserialize>(barterSchemeJson); // Find loyalty level node and parse into object var loyaltyLevelItemsJson = data.GetProperty("loyal_level_items").ToString(); var loyaltyLevelItems = JsonSerializer.Deserialize>(loyaltyLevelItemsJson); WriteOutputFilesForTrader(trader, items, barterSchemeItems, loyaltyLevelItems); } } private static string CreateWorkingFolders() { var workingPath = Directory.GetCurrentDirectory(); // create input folder var inputPath = $"{workingPath}//input"; DiskHelpers.CreateDirIfDoesntExist(inputPath); // create sub folder in input called assorts var assortsPath = $"{inputPath}//assorts"; DiskHelpers.CreateDirIfDoesntExist(assortsPath); // create output folder var outputPath = $"{workingPath}//output"; DiskHelpers.CreateDirIfDoesntExist(outputPath); // create traders sub-folder var tradersPath = $"{outputPath}//traders"; DiskHelpers.CreateDirIfDoesntExist(tradersPath); return assortsPath; } private static BaseRoot GetTraderData(IEnumerable filesInAssortsFolder) { var traderDataPath = filesInAssortsFolder.FirstOrDefault(x => x.Contains("resp.client.trading.api.traderSettings")); var traderDataJson = File.ReadAllText(traderDataPath); return JsonSerializer.Deserialize(traderDataJson); } private static void WriteOutputFilesForTrader(KeyValuePair trader, List items, Dictionary barterSchemeItems, Dictionary loyaltyLevelItems) { var workingPath = Directory.GetCurrentDirectory(); var traderData = GetTraderData(InputFileHelper.GetInputFilePaths()); var traderFolderPath = $"traders\\{trader.Value}"; // create assort file, serialise into json and save into output folder var outputAssortFile = new AssortRoot { items = items, barter_scheme = barterSchemeItems, loyal_level_items = loyaltyLevelItems }; JsonWriter.WriteJson(outputAssortFile, traderFolderPath, workingPath, "assort"); // create base file, serialise into json and save into output folder var outputBaseFile = traderData.data.Find(x => x._id == trader.Value); JsonWriter.WriteJson(outputBaseFile, traderFolderPath, workingPath, "base"); QuestAssort questAssort = GenerateQuestAssort(trader.Key, outputAssortFile); JsonWriter.WriteJson(questAssort, traderFolderPath, workingPath, "questassort"); // create suits file for ragman if (trader.Key == Trader.Ragman) { var customisationFilePath = InputFileHelper.GetInputFilePaths().FirstOrDefault(x => x.Contains("resp.client.trading.customization")); var traderDataJson = File.ReadAllText(customisationFilePath); var suitData = JsonSerializer.Deserialize(traderDataJson); var outputSuitData = new List(); outputSuitData.AddRange(suitData.data); JsonWriter.WriteJson(outputSuitData, traderFolderPath, workingPath, "suits"); } } private static QuestAssort GenerateQuestAssort(Trader trader, AssortRoot assortRoot) { var result = new QuestAssort(); var questData = QuestHelper.GetQuestData(); // Find assortunlocks List assortUnlocks = QuestHelper.GetAssortUnlocks(); List assortItemsThatMatchBlackList = new List(); // store items already matched here // TODO: find out how the fuck the assort unlock is associated to the quest foreach (var assortUnlock in assortUnlocks.Where(x => x.TraderType == trader)) { // Get unlock items name var assortItemName = ItemTemplateHelper.Items.FirstOrDefault(x=> x.Key == assortUnlock.ItemUnlockedTemplateId).Value._name; // TODO: handle started // TODO: handle fail // handle quest success for now if (assortUnlock.Criteria == "Success") { //Find assorts that match the quest unlocks item template List assortItemsThatMatch = assortRoot.items.Where(x => x._tpl == assortUnlock.ItemUnlockedTemplateId).ToList(); // no assort found for this unlock, log and skip it if (assortItemsThatMatch == null || assortItemsThatMatch.Count == 0) { LoggingHelpers.LogError($"{trader} item templateId: {assortUnlock.ItemUnlockedTemplateId}. questId: {assortUnlock.QuestId}. no assort item found. ({assortItemName})"); continue; } // Iterate over assorts that match. goal is to find assort that fits the best (traders assort has same loyalty level unlock as quest expects) string assortIdUnlockedByQuest = string.Empty; foreach (var match in assortItemsThatMatch) { // Look up item in Loyalty Level array var associatedLoyaltyLevelItem = assortRoot.loyal_level_items.FirstOrDefault(x => x.Key == match._id); if (associatedLoyaltyLevelItem.Key == null) { // end loop if no record found in loyalty level array LoggingHelpers.LogError($"{trader} item templateId: {assortUnlock.ItemUnlockedTemplateId}. questId: {assortUnlock.QuestId}. no loyalty record found. ({assortItemName})"); break; } if (associatedLoyaltyLevelItem.Value != assortUnlock.LoyaltyLevel) { // loyalty level is different to what was expected, skip and try next LoggingHelpers.LogWarning($"{trader} item templateId: {assortUnlock.ItemUnlockedTemplateId}. questId: {assortUnlock.QuestId}. no match found in LL array. expected LL{associatedLoyaltyLevelItem.Value}. found: LL{assortUnlock.LoyaltyLevel}. ({assortItemName})"); continue; } // LoggingHelpers.LogInfo($"{trader} item templateId: {assortUnlock.ItemUnlockedTemplateId} {assortItemName}. MATCH FOUND. LL{assortUnlock.LoyaltyLevel}"); if (assortItemsThatMatchBlackList.Contains(associatedLoyaltyLevelItem.Key)) { // Not the item we want, its already been matched continue; } // Add assort item id to blacklist so it wont be matched again assortItemsThatMatchBlackList.Add(associatedLoyaltyLevelItem.Key); // assign id and break out of loop, We found the one we want assortIdUnlockedByQuest = associatedLoyaltyLevelItem.Key; break; } if (result.success.ContainsKey(assortIdUnlockedByQuest)) { LoggingHelpers.LogWarning($"{trader} item templateId: {assortUnlock.ItemUnlockedTemplateId}. questId: {assortUnlock.QuestId}. ALREADY EXISTS. SKIPPING. ({assortItemName})"); continue; } if (assortIdUnlockedByQuest == string.Empty) { LoggingHelpers.LogError($"{trader} item templateId: {assortUnlock.ItemUnlockedTemplateId}. questId: {assortUnlock.QuestId}. no assortId found. ({assortItemName})"); continue; } LoggingHelpers.LogSuccess($"{trader} item templateId: {assortUnlock.ItemUnlockedTemplateId}. questId: {assortUnlock.QuestId}. ADDING TO QUEST-ASSORT. ({assortItemName})"); result.success.Add(assortIdUnlockedByQuest, assortUnlock.QuestId); } } return result; } } }