using AssortGenerator.Common.Helpers; using QuestValidator.Common; using QuestValidator.Common.Helpers; using QuestValidator.Helpers; using QuestValidator.Models; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; namespace GenerateQuestFile { class Program { /// /// Generate a quests.json file in /output/ /// Uses every quest from the live quest dump file /// If any quests are missing, it will use the quests.json file to fill in the blanks /// /// static void Main(string[] args) { var inputPath = DiskHelpers.CreateWorkingFolders(); InputFileHelper.SetInputFiles(inputPath); // Read in quest files var existingQuestData = QuestHelper.GetQuestData(); var liveQuestData = QuestHelper.GetLiveQuestData(); // Find the quests that are missing from the live file from existing quest data var missingQuests = GetMissingQuestsNotInLiveFile(existingQuestData, liveQuestData); // Create a list of quests to output // Use all quests in live file // Use quests from quests.json to fill in missing quests var questsToOutputToFile = new Dictionary(); // Add live quests to collection to return later foreach (var liveQuest in liveQuestData.data) { questsToOutputToFile.Add(liveQuest._id, liveQuest); } // Add missing quests from existing quest data to fill in blanks from live data foreach (var missingQuest in missingQuests) { // Going from a pre-12.7.x version has problems, it doesnt have the new quest data format CheckAndFixMissingProperties(missingQuest); questsToOutputToFile.Add(missingQuest._id, missingQuest); } if (!questsToOutputToFile.ContainsKey("5e383a6386f77465910ce1f3")) // TextileP1Bear { // add textileP1Bear } if (!questsToOutputToFile.ContainsKey("5e4d515e86f77438b2195244")) // TextileP2Bear { // add TextileP2Bear } foreach (var quest in questsToOutputToFile) { AddQuestName(quest); var originalQuest = existingQuestData.FirstOrDefault(x => x.Key == quest.Key).Value; if (originalQuest is null) { LoggingHelpers.LogWarning($"Cant check for original start conditions. Unable to find original quest {quest.Key} {QuestHelper.GetQuestNameById(quest.Key)}, skipping."); continue; } // quest has start conditions, check to ensure they're carried over if (originalQuest.conditions.AvailableForStart.Count > 0) { AddMissingAvailableForStartConditions(originalQuest, quest); } } // Iterate over quest objects a final time and add hard coded quest requirements if they dont already exist foreach (var quest in questsToOutputToFile) { var questRequirements = QuestRequirements.GetQuestRequirements(quest.Key); if (questRequirements is null || questRequirements.Count == 0) { LoggingHelpers.LogWarning($"Quest requirement not found for : {quest.Value.QuestName}, skipping."); continue; } foreach (var requirement in questRequirements) { if (!quest.Value.conditions.AvailableForStart.Any(x => x._parent == "Quest" && x._props.target.ToString() == requirement.Quest.Id)) { LoggingHelpers.LogSuccess($"{quest.Value.QuestName} needs a prereq of quest {requirement.Quest.Name}, adding."); quest.Value.conditions.AvailableForStart.Add(new AvailableFor { _parent = "Quest", _props = new AvailableForProps { id = "", index = quest.Value.conditions.AvailableForStart.Count, parentId = "", status = new[] { requirement.QuestStatus}, target = requirement.Quest.Id } } ); } else { if (questRequirements != null) { LoggingHelpers.LogInfo($"{quest.Value.QuestName} already has prereq of quest {requirement.Quest.Name}, skipping."); } } } } JsonWriter.WriteJson(questsToOutputToFile, "output", Directory.GetCurrentDirectory(), "quests"); } private static void CheckAndFixMissingProperties(Quest missingQuest) { if (missingQuest.description is null) { missingQuest.description = $"{missingQuest._id} description"; } if (missingQuest.failMessageText is null) { missingQuest.failMessageText = $"{missingQuest._id} failMessageText"; } if (missingQuest.name is null) { missingQuest.name = $"{missingQuest._id} name"; } if (missingQuest.note is null) { missingQuest.note = $"{missingQuest._id} note"; } if (missingQuest.startedMessageText is null) { missingQuest.startedMessageText = $"{missingQuest._id} startedMessageText"; } if (missingQuest.successMessageText is null) { missingQuest.successMessageText = $"{missingQuest._id} successMessageText"; } if (missingQuest.templateId is null) { missingQuest.templateId = $"{missingQuest._id} successMessageText"; } } private static void AddMissingAvailableForStartConditions(Quest originalQuest, KeyValuePair questToUpdate) { // Iterate over quest requirements in existing quest file foreach (var questRequirementToAdd in originalQuest.conditions.AvailableForStart.ToList()) { //Exists already, skip if (questToUpdate.Value.conditions.AvailableForStart.Any(x => x._parent == questRequirementToAdd._parent && x._props.target?.ToString() == questRequirementToAdd._props.target?.ToString())) { continue; } questToUpdate.Value.conditions.AvailableForStart.Add(questRequirementToAdd); } } /// /// Look up the quests name by guid and add human readable string to quest object /// /// private static void AddQuestName(KeyValuePair quest) { var questName = QuestHelper.GetQuestNameById(quest.Value._id); // special characters like ", brake the client when it parses it, gotta remove var rgx = new Regex("[^a-zA-Z0-9 -]"); quest.Value.QuestName = rgx.Replace(questName, ""); } /// /// Loop over live quests and use if it exists, otherwise use existing data /// private static List GetMissingQuestsNotInLiveFile(Dictionary existingQuests, QuestRoot liveQuestData) { var missingQuestsToReturn = new List(); foreach (var quest in existingQuests.Values) { var liveQuest = liveQuestData.data.Find(x => x._id == quest._id); if (liveQuest is null) { missingQuestsToReturn.Add(quest); LoggingHelpers.LogError($"ERROR Quest {quest._id} {QuestHelper.GetQuestNameById(quest._id)} missing in live file. Will use fallback quests.json"); } else { LoggingHelpers.LogSuccess($"SUCCESS Quest {quest._id} {QuestHelper.GetQuestNameById(quest._id)} found in live file."); } } return missingQuestsToReturn; } } }