protected override List <ItemSocketScrollMetadata> Parse() { List <ItemSocketScrollMetadata> items = new(); PackFileEntry entry = Resources.XmlReader.Files.FirstOrDefault(x => x.Name.StartsWith("table/itemsocketscroll")); if (entry is null) { return(items); } // Parse XML XmlDocument document = Resources.XmlReader.GetXmlDocument(entry); XmlNodeList nodes = document.SelectNodes("/ms2/scroll"); foreach (XmlNode node in nodes) { List <int> intItemSlots = node.Attributes["slot"].Value.SplitAndParseToInt(',').ToList(); List <ItemType> itemSlots = intItemSlots.Select(itemSlot => (ItemType)itemSlot).ToList(); ItemSocketScrollMetadata metadata = new() { Id = int.Parse(node.Attributes["id"].Value), MinLevel = int.Parse(node.Attributes["minLv"].Value), MaxLevel = int.Parse(node.Attributes["maxLv"].Value), ItemTypes = itemSlots, Rarity = int.Parse(node.Attributes["rank"].Value), MakeUntradeable = node.Attributes["tradableCountDeduction"]?.Value == "1", }; items.Add(metadata); } return(items); }
protected override List <PrestigeLevelMissionMetadata> Parse() { List <PrestigeLevelMissionMetadata> items = new(); PackFileEntry entry = Resources.XmlReader.Files.FirstOrDefault(x => x.Name.StartsWith("table/adventurelevelmission")); if (entry is null) { return(items); } // Parse XML XmlDocument document = Resources.XmlReader.GetXmlDocument(entry); XmlNodeList nodes = document.SelectNodes("/ms2/mission"); foreach (XmlNode node in nodes) { PrestigeLevelMissionMetadata metadata = new() { Id = int.Parse(node.Attributes["missionId"].Value), MissionCount = int.Parse(node.Attributes["missionCount"].Value), RewardItemId = int.Parse(node.Attributes["itemId"].Value), RewardItemRarity = int.Parse(node.Attributes["itemRank"].Value), RewardItemAmount = int.Parse(node.Attributes["itemCount"].Value) }; items.Add(metadata); } return(items); } }
protected override List <MapMetadata> Parse() { MapsList = new(); // Parse map names MapNames = new(); PackFileEntry file = Resources.XmlReader.Files.FirstOrDefault(x => x.Name.StartsWith("string/en/mapname.xml")); XmlDocument document = Resources.XmlReader.GetXmlDocument(file); foreach (XmlNode node in document.DocumentElement.ChildNodes) { int id = int.Parse(node.Attributes["id"].Value); string name = node.Attributes["name"].Value; MapNames[id] = name; } // Parse every block for each map FlatTypeIndex index = new(Resources.ExportedReader); XBlockParser parser = new(Resources.ExportedReader, index); parser.Include(typeof(IMS2CubeProp)); // We only care about cubes here parser.Parse(AddMetadata); return(MapsList); }
protected override List <AdBannerMetadata> Parse() { List <AdBannerMetadata> items = new(); PackFileEntry entry = Resources.XmlReader.Files.FirstOrDefault(x => x.Name.StartsWith("table/na/banner")); if (entry is null) { return(items); } // Parse XML XmlDocument document = Resources.XmlReader.GetXmlDocument(entry); XmlNodeList nodes = document.SelectNodes("/ms2/banner"); foreach (XmlNode node in nodes) { AdBannerMetadata metadata = new() { Id = int.Parse(node.Attributes["id"].Value), MapId = int.Parse(node.Attributes["field"].Value), Prices = node.Attributes["price"].Value.SplitAndParseToInt(',').ToList(), }; items.Add(metadata); } return(items); }
protected override List <FieldWarMetadata> Parse() { List <FieldWarMetadata> fieldWar = new(); PackFileEntry fieldWarData = Resources.XmlReader.Files.FirstOrDefault(x => x.Name.StartsWith("table/fieldwardata")); if (fieldWarData is null) { throw new FileNotFoundException("Could not find table fieldwardata.xml"); } XmlDocument document = Resources.XmlReader.GetXmlDocument(fieldWarData); XmlNodeList nodes = document.SelectNodes("/ms2/fieldWar"); foreach (XmlNode node in nodes) { FieldWarMetadata metadata = new() { FieldWarId = int.Parse(node.Attributes["fieldWarID"].Value), RewardId = int.Parse(node.Attributes["rewardID"].Value), MapId = int.Parse(node.Attributes["fieldID"].Value), GroupId = byte.Parse(node.Attributes["fieldWarGroupID"].Value) }; fieldWar.Add(metadata); } return(fieldWar); } }
protected override List <UgcDesignMetadata> Parse() { List <UgcDesignMetadata> metadatas = new(); PackFileEntry file = Resources.XmlReader.Files.FirstOrDefault(x => x.Name.Contains("table/na/ugcdesign.xml")); if (file is null) { throw new FileNotFoundException("File not found: table/na/ugcdesign.xml"); } XmlDocument document = Resources.XmlReader.GetXmlDocument(file); XmlNodeList nodes = document.SelectNodes("/ms2/list"); foreach (XmlNode node in nodes) { int itemId = int.Parse(node.Attributes["itemID"].Value); bool visible = byte.Parse(node.Attributes["visible"].Value) == 1; byte rarity = byte.Parse(node.Attributes["itemGrade"].Value); byte priceType = byte.Parse(node.Attributes["priceType"].Value); CurrencyType currencyType = priceType switch { 0 => CurrencyType.Meso, 1 => CurrencyType.Meret, _ => throw new NotImplementedException(), }; long price = long.Parse(node.Attributes["price"].Value); long salePrice = long.Parse(node.Attributes["salePrice"].Value); long marketMinPrice = long.Parse(node.Attributes["marketMinPrice"].Value); long marketMaxPrice = long.Parse(node.Attributes["marketMaxPrice"].Value); metadatas.Add(new(itemId, visible, rarity, currencyType, price, salePrice, marketMinPrice, marketMaxPrice)); } return(metadatas); }
protected override List <TitleMetadata> Parse() { List <TitleMetadata> metadatas = new(); PackFileEntry file = Resources.XmlReader.Files.FirstOrDefault(x => x.Name.Contains("string/en/titlename.xml")); if (file is null) { throw new FileNotFoundException("File not found: string/en/titlename.xml"); } XmlDocument document = Resources.XmlReader.GetXmlDocument(file); XmlNodeList nodes = document.SelectNodes("/ms2/key"); foreach (XmlNode node in nodes) { int id = int.Parse(node.Attributes["id"].Value); if (id < 4) { continue; } string name = node.Attributes["name"].Value; string feature = node.Attributes["feature"]?.Value ?? string.Empty; metadatas.Add(new(id, name, feature)); } return(metadatas); }
public LevelRulesEditor(FileManager fileManager, PackFileEntry fileEntry) { InitializeComponent(); DoubleBuffered = true; _fileManager = fileManager; byte[] fileBytes = fileManager.GetFileBytes(fileEntry); _levelRules = new LevelRulesFile(fileEntry.Path, null); _levelRules.ParseFileBytes(fileBytes); foreach (LevelRulesFile.LevelRule levelRule in _levelRules.LevelRules) { if (levelRule.StaticRooms != null) { _LoadRooms(levelRule.StaticRooms, fileEntry.Path); } else { foreach (LevelRulesFile.Room[] levelRules in levelRule.Rules) { _LoadRooms(levelRules, fileEntry.Path); } } } }
public void ParseMap(string xblock, Action <IEnumerable <IMapEntity> > callback) { PackFileEntry file = reader.Files .FirstOrDefault(file => file.Name.Equals($"xblock/{xblock}.xblock")); if (file == default) { return; } callback(ParseEntities(file)); }
public XmlDocument GetXmlDocument(PackFileEntry entry) { var document = new XmlDocument(); byte[] data = CryptoManager.DecryptData(entry.FileHeader, m2dFile); try { document.Load(new MemoryStream(data)); } catch { string xmlText = Encoding.Default.GetString(data); document.LoadXml(xmlText); } return(document); }
protected override List <ItemEnchantTransferMetadata> Parse() { List <ItemEnchantTransferMetadata> items = new(); PackFileEntry entry = Resources.XmlReader.Files.FirstOrDefault(x => x.Name.StartsWith("table/itemenchanttransform")); if (entry is null) { return(items); } // Parse XML XmlDocument document = Resources.XmlReader.GetXmlDocument(entry); XmlNodeList nodes = document.SelectNodes("/ms2/transform"); foreach (XmlNode node in nodes) { string locale = node.Attributes["locale"]?.Value ?? ""; if (locale != "NA" && locale != "") { continue; } List <int> intItemSlots = node.Attributes["inputSlot"].Value.SplitAndParseToInt(',').ToList(); List <ItemType> itemSlots = intItemSlots.Select(itemSlot => (ItemType)itemSlot).ToList(); ItemEnchantTransferMetadata metadata = new() { InputRarity = int.Parse(node.Attributes["inputRank"].Value), InputItemLevel = int.Parse(node.Attributes["inputLimitLevel"].Value), InputEnchantLevel = int.Parse(node.Attributes["inputEnchantLevel"].Value), InputSlots = itemSlots, InputItemIds = node.Attributes["inputItemId"].Value.SplitAndParseToInt(',').ToList(), MesoCost = long.Parse(node.Attributes["needMeso"].Value), OutputItemId = int.Parse(node.Attributes["output1Id"].Value), OutputRarity = int.Parse(node.Attributes["output1Rank"].Value), OutputAmount = int.Parse(node.Attributes["output1Count"].Value) }; items.Add(metadata); } return(items); } }
private IEnumerable <IMapEntity> ParseEntities(PackFileEntry file) { if (serializer.Deserialize(reader.GetXmlReader(file)) is GameXBlock block) { if (keepEntities.Count == 0) { return(block.entitySet.entity.Select(CreateInstance)); } return(block.entitySet.entity .Where(entity => { Type mixinType = lookup.GetMixinType(entity.modelName); return keepEntities.Any(keep => keep.IsAssignableFrom(mixinType)); }) .Select(CreateInstance)); } return(Array.Empty <IMapEntity>()); }
private static List <PackFileEntry> ReadFile(Stream headerFile) { using var headerReader = new BinaryReader(headerFile); var stream = IPackStream.CreateStream(headerReader); string fileString = Encoding.UTF8.GetString(CryptoManager.DecryptFileString(stream, headerReader.BaseStream)); stream.FileList.AddRange(PackFileEntry.CreateFileList(fileString)); stream.FileList.Sort(); // Load the file allocation table and assign each file header to the entry within the list byte[] fileTable = CryptoManager.DecryptFileTable(stream, headerReader.BaseStream); using var tableStream = new MemoryStream(fileTable); using var reader = new BinaryReader(tableStream); stream.InitFileList(reader); return(stream.FileList); }
protected override List <CharacterCreateMetadata> Parse() { List <CharacterCreateMetadata> items = new(); PackFileEntry entry = Resources.XmlReader.Files.FirstOrDefault(x => x.Name.StartsWith("table/charactercreateselect")); if (entry is null) { return(items); } // Parse XML XmlDocument document = Resources.XmlReader.GetXmlDocument(entry); XmlNodeList nodes = document.SelectNodes("/ms2/group"); foreach (XmlNode node in nodes) { if (node.Attributes["name"].Value != "display" || node.Attributes["locale"]?.Value != null) { continue; } foreach (XmlNode subnode in node) { if (subnode.Attributes["feature"].Value != "SoulBinder") // get the latest entry being used { continue; } List <int> disabledJobs = subnode.Attributes["disableJobCode"].Value.SplitAndParseToInt(',').ToList(); CharacterCreateMetadata metadata = new() { DisabledJobs = disabledJobs }; items.Add(metadata); } } return(items); } }
private void ParseMapSpawnTagTable() { SpawnTagMap = new(); PackFileEntry mapSpawnTag = Resources.XmlReader.Files.FirstOrDefault(x => x.Name.StartsWith("table/mapspawntag")); XmlDocument mapSpawnTagXml = Resources.XmlReader.GetXmlDocument(mapSpawnTag); XmlNodeList regionNodes = mapSpawnTagXml.SelectNodes("/ms2/region"); foreach (XmlNode node in regionNodes) { int mapId = int.Parse(node.Attributes["mapCode"].Value); int spawnPointId = int.Parse(node.Attributes["spawnPointID"].Value); int difficulty = int.Parse(node.Attributes["difficulty"].Value); int minDifficulty = int.Parse(node.Attributes["difficultyMin"].Value); string[] spawnTags = node.Attributes["tag"].Value.Split(",").Select(p => p.Trim()).ToArray(); if (!int.TryParse(node.Attributes["coolTime"].Value, out int spawnTime)) { spawnTime = 0; } if (!int.TryParse(node.Attributes["population"].Value, out int population)) { population = 0; } _ = int.TryParse(node.Attributes["petPopulation"]?.Value, out int petPopulation); bool isPetSpawn = petPopulation > 0; SpawnMetadata spawnData = new(spawnTags, population, spawnTime, difficulty, minDifficulty, isPetSpawn); if (!SpawnTagMap.ContainsKey(mapId)) { SpawnTagMap[mapId] = new(); } SpawnTagMap[mapId][spawnPointId] = spawnData; } }
public M2dReader(string path) { m2dFile = MemoryMappedFile.CreateFromFile(path); // Create an index from the header file using var headerReader = new BinaryReader(System.IO.File.OpenRead(path.Replace(".m2d", ".m2h"))); var stream = IPackStream.CreateStream(headerReader); string fileString = Encoding.UTF8.GetString(CryptoManager.DecryptFileString(stream, headerReader.BaseStream)); stream.FileList.AddRange(PackFileEntry.CreateFileList(fileString)); stream.FileList.Sort(); // Load the file allocation table and assign each file header to the entry within the list byte[] fileTable = CryptoManager.DecryptFileTable(stream, headerReader.BaseStream); using var tableStream = new MemoryStream(fileTable); using var reader = new BinaryReader(tableStream); stream.InitFileList(reader); Files = stream.FileList; }
protected override List <EnchantScrollMetadata> Parse() { List <EnchantScrollMetadata> items = new(); PackFileEntry entry = Resources.XmlReader.Files.FirstOrDefault(x => x.Name.StartsWith("table/enchantscroll")); if (entry is null) { return(items); } // Parse XML XmlDocument document = Resources.XmlReader.GetXmlDocument(entry); XmlNodeList nodes = document.SelectNodes("/ms2/scroll"); foreach (XmlNode node in nodes) { List <int> intItemSlots = node.Attributes["slot"].Value.SplitAndParseToInt(',').ToList(); List <ItemType> itemSlots = intItemSlots.Select(itemSlot => (ItemType)itemSlot).ToList(); EnchantScrollMetadata metadata = new() { Id = int.Parse(node.Attributes["id"].Value), MinLevel = short.Parse(node.Attributes["minLv"].Value), MaxLevel = short.Parse(node.Attributes["maxLv"].Value), ItemTypes = itemSlots, ScrollType = (EnchantScrollType)int.Parse(node.Attributes["scrollType"].Value), Rarities = node.Attributes["rank"].Value.SplitAndParseToInt(',').ToList(), EnchantLevels = node.Attributes["grade"].Value.SplitAndParseToInt(',').ToList() }; items.Add(metadata); } return(items); } }
protected override List <EnchantLimitMetadata> Parse() { List <EnchantLimitMetadata> items = new(); PackFileEntry entry = Resources.XmlReader.Files.FirstOrDefault(x => x.Name.StartsWith("table/enchantlimittable")); if (entry is null) { return(items); } // Parse XML XmlDocument document = Resources.XmlReader.GetXmlDocument(entry); XmlNodeList nodes = document.SelectNodes("/ms2/limit"); foreach (XmlNode node in nodes) { string locale = node.Attributes["locale"]?.Value ?? ""; if (locale != "NA" && locale != "") { continue; } EnchantLimitMetadata metadata = new() { ItemType = (ItemType)int.Parse(node.Attributes["slot"].Value), MinLevel = int.Parse(node.Attributes["minLv"].Value), MaxLevel = int.Parse(node.Attributes["maxLv"].Value), MaxEnchantLevel = int.Parse(node.Attributes["maxGrade"].Value) }; items.Add(metadata); } return(items); } }
public XmlReader GetXmlReader(PackFileEntry entry) { return(XmlReader.Create(new MemoryStream(CryptoManager.DecryptData(entry.FileHeader, m2dFile)))); }
public static bool PackDatFile(IEnumerable <String> filesToPack, String outputPath, bool forceCreateNewIndex) { IndexFile indexFile = null; bool isAppend = false; if (!forceCreateNewIndex && File.Exists(outputPath)) { Console.Write("Hellpack has detected an existing index. Append to previous index? [Y/N]: "); char ans = (char)Console.Read(); if (ans == 'y' || ans == 'Y') { indexFile = new IndexFile(outputPath, File.ReadAllBytes(outputPath)); isAppend = true; } } if (indexFile == null) { indexFile = new IndexFile(outputPath); } foreach (String filePath in filesToPack) { DateTime lastModified = File.GetLastWriteTime(filePath); // if we're appending, check if we've already added this file by checking the modified time if (isAppend) { PackFileEntry fileEntry = indexFile.GetFileEntry(filePath); if (fileEntry != null && fileEntry.LastModified == lastModified) { continue; } } String fileName = Path.GetFileName(filePath); String directory = Path.GetDirectoryName(filePath); int dataCursor = directory.IndexOf("data"); directory = directory.Remove(0, dataCursor) + "\\"; byte[] buffer; try { buffer = File.ReadAllBytes(filePath); } catch (Exception ex) { ExceptionLogger.LogException(ex); Console.WriteLine(String.Format("Warning: Could not read file {0}", filePath)); continue; } Console.WriteLine("Packing " + directory + fileName); if (indexFile.AddFile(directory, fileName, buffer, lastModified) == false) { Console.WriteLine("Warning: Failed to add file to index..."); } } foreach (PackFile file in _fileManager.IndexFiles) { file.EndDatAccess(); } string thisPack = Path.GetFileNameWithoutExtension(outputPath); byte[] indexBytes = indexFile.ToByteArray(); Crypt.Encrypt(indexBytes); Console.WriteLine("Writing " + thisPack); try { File.WriteAllBytes(outputPath, indexBytes); } catch (Exception ex) { ExceptionLogger.LogException(ex); Console.WriteLine(String.Format("Fatal error: Could not write index {0}", thisPack)); return(false); } Console.WriteLine(String.Format("{0} generation complete.", thisPack)); return(true); }
public string GetString(PackFileEntry entry) { byte[] data = CryptoManager.DecryptData(entry.FileHeader, m2dFile); return(Encoding.Default.GetString(data)); }
public byte[] GetBytes(PackFileEntry entry) { return(CryptoManager.DecryptData(entry.FileHeader, m2dFile)); }
/// <summary> /// User-friendly uncooking of Tree Node list. /// </summary> /// <param name="progressForm">A progress form to update.</param> /// <param name="param">The Tree Node List.</param> private void _DoUnooking(ProgressForm progressForm, Object param) { List <TreeNode> uncookingNodes = (List <TreeNode>)param; const int progressUpdateFreq = 20; if (progressForm != null) { progressForm.ConfigBar(1, uncookingNodes.Count, progressUpdateFreq); } int i = 0; foreach (TreeNode treeNode in uncookingNodes) { NodeObject nodeObject = (NodeObject)treeNode.Tag; PackFileEntry fileEntry = nodeObject.FileEntry; // update progress if applicable if (i % progressUpdateFreq == 0 && progressForm != null) { progressForm.SetCurrentItemText(fileEntry.Path); } i++; // get the file bytes String relativePath = fileEntry.Path; byte[] fileBytes; try { fileBytes = _fileManager.GetFileBytes(fileEntry, true); if (fileBytes == null) { continue; } } catch (Exception e) { ExceptionLogger.LogException(e); continue; } // determine file type HellgateFile hellgateFile; if (relativePath.EndsWith(XmlCookedFile.Extension)) { hellgateFile = new XmlCookedFile(_fileManager); } else if (relativePath.EndsWith(RoomDefinitionFile.Extension)) { hellgateFile = new RoomDefinitionFile(relativePath); } else if (relativePath.EndsWith(MLIFile.Extension)) { hellgateFile = new MLIFile(); } else { Debug.Assert(false, "wtf"); continue; } // deserialise file DialogResult dr = DialogResult.Retry; bool uncooked = false; while (dr == DialogResult.Retry && !uncooked) { try { hellgateFile.ParseFileBytes(fileBytes); uncooked = true; } catch (Exception e) { ExceptionLogger.LogException(e, true); String errorMsg = String.Format("Failed to uncooked file!\n{0}\n\n{1}", relativePath, e); dr = MessageBox.Show(errorMsg, "Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Exclamation); if (dr == DialogResult.Abort) { return; } if (dr == DialogResult.Ignore) { break; } } } if (!uncooked) { continue; } // save file String relativeSavePath = relativePath.Replace(HellgateFile.Extension, HellgateFile.ExtensionDeserialised); String savePath = Path.Combine(Config.HglDir, relativeSavePath); dr = DialogResult.Retry; bool saved = false; byte[] documentBytes = null; while (dr == DialogResult.Retry && !saved) { try { if (documentBytes == null) { documentBytes = hellgateFile.ExportAsDocument(); } File.WriteAllBytes(savePath, documentBytes); saved = true; } catch (Exception e) { ExceptionLogger.LogException(e, true); String errorMsg = String.Format("Failed to save file!\n{0}\n\n{1}", relativePath, e); dr = MessageBox.Show(errorMsg, "Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Exclamation); if (dr == DialogResult.Abort) { return; } if (dr == DialogResult.Ignore) { break; } } } // update tree view TreeNode newTreeNode = new TreeNode(); NodeObject newNodeObject = new NodeObject { CanEdit = true, IsUncookedVersion = true }; newTreeNode.Tag = newNodeObject; treeNode.Nodes.Add(newTreeNode); } }
/// <summary> /// Singlular file extract and patch worker function. /// </summary> /// <param name="treeNode">The current file/folder tree node.</param> /// <param name="overwrite">A referenced and static file overwrite option.</param> /// <param name="indexToWrite">A Hashtable of IndexFiles that require writing due to patching.</param> /// <param name="extractPatchArgs">The operation arguments to perform.</param> /// <returns>True upon successful extraction and/or patching of the file.</returns> private bool _ExtractPatchFile(TreeNode treeNode, ref DialogResult overwrite, Hashtable indexToWrite, ExtractPackPatchArgs extractPatchArgs) { if (treeNode == null) { return(false); } //if (treeNode.Text == "affixes.txt.cooked") //{ // int bp = 0; //} // loop through for folders, etc NodeObject nodeObject = (NodeObject)treeNode.Tag; if (nodeObject.IsFolder) { foreach (TreeNode childNode in treeNode.Nodes) { if (!_ExtractPatchFile(childNode, ref overwrite, indexToWrite, extractPatchArgs)) { return(false); } } return(true); } // make sure we want to extract this file if (!treeNode.Checked || nodeObject.Index == null || nodeObject.FileEntry == null) { return(true); } PackFileEntry fileEntry = nodeObject.FileEntry; // are we extracting? if (extractPatchArgs.ExtractFiles) { // get path String filePath = extractPatchArgs.KeepStructure ? Path.Combine(extractPatchArgs.RootDir, treeNode.FullPath) : Path.Combine(extractPatchArgs.RootDir, fileEntry.Name); // does it exist? bool fileExists = File.Exists(filePath); if (fileExists && overwrite == DialogResult.None) { overwrite = MessageBox.Show("An extract file already exists, do you wish to overwrite the file, and all following?\nFile: " + filePath, "Question", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); if (overwrite == DialogResult.Cancel) { return(false); } } if (fileExists && overwrite == DialogResult.No) { return(true); } // save file DialogResult extractDialogResult = DialogResult.Retry; while (extractDialogResult == DialogResult.Retry) { byte[] fileBytes = _fileManager.GetFileBytes(fileEntry, extractPatchArgs.PatchFiles); if (fileBytes == null) { extractDialogResult = MessageBox.Show("Failed to read file from .dat! Try again?", "Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Error); if (extractDialogResult == DialogResult.Abort) { overwrite = DialogResult.Cancel; return(false); } continue; } Directory.CreateDirectory(Path.GetDirectoryName(filePath)); File.WriteAllBytes(filePath, fileBytes); File.SetLastWriteTime(filePath, fileEntry.LastModified); break; } } // are we patching? if (!extractPatchArgs.PatchFiles) { return(true); } // don't patch out string files or sound/movie files if (IndexFile.NoPatchExt.Any(ext => fileEntry.Name.EndsWith(ext))) { return(true); } // if we're patching out the file, then change its bgColor and set its nodeObject state to backup treeNode.ForeColor = BackupColor; // is this file located else where? (i.e. does it have Siblings) String indexFileKey; if (fileEntry.Siblings != null && fileEntry.Siblings.Count > 0) { // this file has siblings - loop through foreach (PackFileEntry siblingFileEntry in fileEntry.Siblings.Where(siblingFileEntry => !siblingFileEntry.IsPatchedOut)) { siblingFileEntry.IsPatchedOut = true; indexFileKey = siblingFileEntry.Pack.NameWithoutExtension; if (!indexToWrite.ContainsKey(indexFileKey)) { indexToWrite.Add(indexFileKey, siblingFileEntry.Pack); } } } // now patch the curr file as well // only add index to list if it needs to be PackFile indexFile = nodeObject.Index; if (fileEntry.IsPatchedOut) { return(true); } fileEntry.IsPatchedOut = true; indexFileKey = indexFile.NameWithoutExtension; if (!indexToWrite.ContainsKey(indexFileKey)) { indexToWrite.Add(indexFileKey, fileEntry.Pack); } return(true); }
protected override List <TrophyMetadata> Parse() { List <TrophyMetadata> trophyList = new(); // Parse trophy names Dictionary <int, string> trophyNames = new(); PackFileEntry file = Resources.XmlReader.Files.FirstOrDefault(x => x.Name.StartsWith("string/en/achievename.xml")); XmlDocument stringDoc = Resources.XmlReader.GetXmlDocument(file); foreach (XmlNode node in stringDoc.DocumentElement.ChildNodes) { int id = int.Parse(node.Attributes["id"].Value); string name = node.Attributes["name"].Value; trophyNames[id] = name; } foreach (PackFileEntry entry in Resources.XmlReader.Files) { if (!entry.Name.StartsWith("achieve/")) { continue; } XmlDocument document = Resources.XmlReader.GetXmlDocument(entry); XmlNode trophy = document.SelectSingleNode("/ms2/achieves"); int id = int.Parse(trophy.Attributes["id"].Value); TrophyMetadata newTrophy = new() { Id = id, Categories = trophy.Attributes["categoryTag"]?.Value.Split(","), AccountWide = trophy.Attributes["account"].Value == "1" }; trophyNames.TryGetValue(id, out newTrophy.Name); XmlNodeList grades = trophy.SelectNodes("grade"); foreach (XmlNode grade in grades) { XmlNode condition = grade.SelectSingleNode("condition"); XmlNode reward = grade.SelectSingleNode("reward"); Enum.TryParse(reward.Attributes["type"].Value, true, out RewardType type); if (string.IsNullOrEmpty(newTrophy.ConditionType) || string.IsNullOrEmpty(newTrophy.ConditionCodes)) { newTrophy.ConditionType = condition.Attributes["type"].Value; newTrophy.ConditionCodes = condition.Attributes["code"].Value; } TrophyGradeMetadata newGrade = new() { Grade = int.Parse(grade.Attributes["value"].Value), Condition = long.Parse(condition.Attributes["value"].Value), ConditionTargets = condition.Attributes["target"].Value, RewardType = type, RewardCode = int.Parse(reward.Attributes["code"].Value), RewardValue = int.Parse(reward.Attributes["value"].Value), RewardRank = int.Parse(reward.Attributes["rank"].Value) }; int.TryParse(reward.Attributes["subJobLevel"]?.Value, out newGrade.RewardSubJobLevel); newTrophy.Grades.Add(newGrade); } trophyList.Add(newTrophy); } return(trophyList); } }