/// <summary> /// Reads the texture atlas for icon displays. /// </summary> /// <param name="pak">The pak to load texture atlas for.</param> /// <returns>Whether the texture atlas was created.</returns> private bool ReadIcons(string pak) { var metaLoc = FileHelper.GetPath($"{pak}\\Mods\\{pak}\\meta.lsx"); if (File.Exists(@"\\?\" + metaLoc)) { var meta = DragAndDropHelper.ReadMeta(metaLoc); var characterIconAtlas = FileHelper.GetPath($"{pak}\\Public\\{pak}\\GUI\\Generated_{meta.UUID}_Icons.lsx"); if (File.Exists(@"\\?\" + characterIconAtlas)) { TextureAtlases.Add(TextureAtlas.Read(characterIconAtlas, pak)); } var objectIconAtlas = FileHelper.GetPath($"{pak}\\Public\\{pak}\\GUI\\Icons_Items.lsx"); if (File.Exists(@"\\?\" + objectIconAtlas)) { TextureAtlases.Add(TextureAtlas.Read(objectIconAtlas, pak)); } var objectIconAtlas2 = FileHelper.GetPath($"{pak}\\Public\\{pak}\\GUI\\Icons_Items_2.lsx"); if (File.Exists(@"\\?\" + objectIconAtlas2)) { TextureAtlases.Add(TextureAtlas.Read(objectIconAtlas2, pak)); } return(true); } return(false); }
/// <summary> /// Finds the materials used for each LOD level of an object's components. /// </summary> /// <param name="id">The id to match.</param> /// <param name="visualBanks">The visualbanks to lookup.</param> /// <returns>The list of material/lod relationships.</returns> private static Dictionary <string, Tuple <string, string> > LoadMaterials(string id, Dictionary <string, string> visualBanks) { var materialIds = new Dictionary <string, Tuple <string, string> >(); if (id != null) { visualBanks.TryGetValue(id, out string visualResourceFile); if (visualResourceFile != null) { var xml = XDocument.Load(FileHelper.GetPath(visualResourceFile)); var visualResourceNode = xml.Descendants().Where(x => x.Name.LocalName == "node" && x.Attribute("id").Value == "Resource" && x.Elements("attribute").Single(a => a.Attribute("id").Value == "ID").Attribute("value").Value == id).First(); var children = visualResourceNode.Element("children"); if (children != null) { var nodes = children.Elements("node"); foreach (XElement node in nodes.Where(node => node.Attribute("id").Value == "Objects")) { var materialId = node.Elements("attribute").Single(a => a.Attribute("id").Value == "MaterialID").Attribute("value").Value; var objectId = node.Elements("attribute").Single(a => a.Attribute("id").Value == "ObjectID").Attribute("value").Value; if (materialId != null) { materialIds.Add(objectId.Split('.')[1], new Tuple <string, string>(materialId, id)); } } } } } return(materialIds); }
/// <summary> /// Reads translation file into translation list. /// </summary> /// <returns>Whether the translation file was read.</returns> private bool ReadTranslations() { TranslationLookup = new Dictionary <string, Translation>(); var translationFile = FileHelper.GetPath(@"English\Localization\English\english.xml"); if (File.Exists(translationFile)) { using (XmlReader reader = XmlReader.Create(translationFile)) { while (reader.Read()) { if (reader.Name == "content") { var id = reader.GetAttribute("contentuid"); var text = reader.ReadInnerXml(); Translations.Add(new Translation { ContentUid = id, Value = text }); } } TranslationLookup = Translations.ToDictionary(go => go.ContentUid); return(true); } } GeneralHelper.WriteToConsole($"Failed to load english.xml. Please unpack English.pak to generate translations. Skipping...\n"); return(false); }
/// <summary> /// Finds the charactervisualresources for a given character. /// </summary> /// <param name="id">The character visualresource id.</param> /// <param name="characterVisualBanks">The character visualbanks lookup.</param> /// <param name="visualBanks">The visualbanks lookup.</param> /// <returns>The list of character visual resources found.</returns> private static Tuple <List <string>, Dictionary <string, Tuple <string, string> >, Dictionary <string, string> > LoadCharacterVisualResources(string id, Dictionary <string, string> characterVisualBanks, Dictionary <string, string> visualBanks) { var characterVisualResources = new List <string>(); var materials = new Dictionary <string, Tuple <string, string> >(); var slotTypes = new Dictionary <string, string>(); if (id != null) { characterVisualBanks.TryGetValue(id, out string file); if (string.IsNullOrEmpty(file)) { visualBanks.TryGetValue(id, out file); } if (file != null) { var xml = XDocument.Load(FileHelper.GetPath(file)); var characterVisualResource = xml.Descendants().Where(x => x.Name.LocalName == "node" && x.Attribute("id").Value == "Resource" && x.Elements("attribute").Single(a => a.Attribute("id").Value == "ID").Attribute("value").Value == id).First(); var bodySetVisualId = characterVisualResource.Elements("attribute").SingleOrDefault(x => x.Attribute("id").Value == "BodySetVisual")?.Attribute("value").Value; var bodySetVisual = LoadVisualResource(bodySetVisualId, visualBanks); foreach (var material in LoadMaterials(bodySetVisualId, visualBanks)) { materials.Add(material.Key, new Tuple <string, string>(material.Value.Item1, id)); } if (bodySetVisual != null) { characterVisualResources.Add(bodySetVisual); } var slots = characterVisualResource.Descendants().Where(x => x.Name.LocalName == "node" && x.Attribute("id").Value == "Slots").ToList(); foreach (var slot in slots) { var visualResourceId = slot.Elements("attribute").SingleOrDefault(a => a.Attribute("id").Value == "VisualResource").Attribute("value").Value; var slotType = slot.Elements("attribute").SingleOrDefault(a => a.Attribute("id").Value == "Slot").Attribute("value").Value; slotTypes.Add(visualResourceId, slotType); foreach (var material in LoadMaterials(visualResourceId, visualBanks)) { if (!materials.ContainsKey(material.Key)) { materials.Add(material.Key, new Tuple <string, string>(material.Value.Item1, visualResourceId)); } } var visualResource = LoadVisualResource(visualResourceId, visualBanks); if (visualResource != null) { characterVisualResources.Add(visualResource); } } } } return(new Tuple <List <string>, Dictionary <string, Tuple <string, string> >, Dictionary <string, string> >(characterVisualResources, materials, slotTypes)); }
/// <summary> /// Finds the base material id from the material banks. /// </summary> /// <param name="id">The material id to match.</param> /// <param name="type">The map type.</param> /// <param name="materialBanks">The materialbanks lookup.</param> /// <returns>The base material id.</returns> private static string LoadMaterial(string id, string type, Dictionary <string, string> materialBanks) { if (id != null) { materialBanks.TryGetValue(id, out string materialBankFile); if (materialBankFile != null) { var xml = XDocument.Load(FileHelper.GetPath(materialBankFile)); var materialNode = xml.Descendants().Where(x => x.Name.LocalName == "node" && x.Attribute("id").Value == "Resource" && x.Elements("attribute") .Single(a => a.Attribute("id").Value == "ID").Attribute("value").Value == id).First(); var texture2DParams = materialNode.Descendants().Where(x => x.Name.LocalName == "attribute" && x.Attribute("id").Value == "ParameterName").SingleOrDefault(x => x.Attribute("value").Value == type)?.Parent; if (texture2DParams != null) { return(texture2DParams.Elements("attribute").SingleOrDefault(a => a.Attribute("id").Value == "ID")?.Attribute("value").Value); } } } return(null); }
/// <summary> /// Finds the given texture file by id from the texture banks. /// </summary> /// <param name="id">The texture id to match.</param> /// <param name="textureBanks">The texturebanks lookup.</param> /// <returns>The texture filepath.</returns> private static string LoadTexture(string id, Dictionary <string, string> textureBanks) { if (id != null) { textureBanks.TryGetValue(id, out string textureBankFile); if (textureBankFile != null) { var xml = XDocument.Load(FileHelper.GetPath(textureBankFile)); var textureResourceNode = xml.Descendants().Where(x => x.Name.LocalName == "node" && x.Attribute("id").Value == "Resource" && x.Elements("attribute").Single(a => a.Attribute("id").Value == "ID").Attribute("value").Value == id).First(); var ddsFile = textureResourceNode.Elements("attribute").SingleOrDefault(a => a.Attribute("id").Value == "SourceFile")?.Attribute("value").Value; if (ddsFile == null) { return(null); } return(FileHelper.GetPath($"Textures\\{ddsFile}")); } } return(null); }
/// <summary> /// Finds the visualresource sourcefile for an object. /// </summary> /// <param name="id">The id to match.</param> /// <param name="visualBanks">The visualbanks lookup.</param> /// <returns>The .GR2 sourcefile.</returns> private static string LoadVisualResource(string id, Dictionary <string, string> visualBanks) { if (id != null) { visualBanks.TryGetValue(id, out string visualResourceFile); if (visualResourceFile != null) { var xml = XDocument.Load(FileHelper.GetPath(visualResourceFile)); var visualResourceNode = xml.Descendants().Where(x => x.Name.LocalName == "node" && x.Attribute("id").Value == "Resource" && x.Elements("attribute").Single(a => a.Attribute("id").Value == "ID").Attribute("value").Value == id).First(); var gr2File = visualResourceNode.Elements("attribute").SingleOrDefault(a => a.Attribute("id").Value == "SourceFile")?.Attribute("value").Value; if (gr2File == null) { return(null); } gr2File = gr2File.Replace(".GR2", string.Empty); return(FileHelper.GetPath($"Models\\{gr2File}")); } } return(null); }
/// <summary> /// Reads the stats and converts them into a StatStructure list. /// Uses reflection to dynamically generate data. /// </summary> /// <param name="pak">The pak to search in.</param> /// <returns>Whether the stats were read.</returns> private bool ReadData(string pak) { var dataDir = FileHelper.GetPath($"{pak}\\Public\\{pak}\\Stats\\Generated\\Data"); if (Directory.Exists(dataDir)) { var dataFiles = Directory.EnumerateFiles(dataDir, "*.txt").Where(file => !ExcludedData.Contains(Path.GetFileNameWithoutExtension(file))).ToList(); foreach (var file in dataFiles) { var fileType = Models.StatStructures.StatStructure.FileType(file); var line = string.Empty; using (var fileStream = new System.IO.StreamReader(file)) { while ((line = fileStream.ReadLine()) != null) { if (line.Contains("new entry")) { StatStructures.Add(Models.StatStructures.StatStructure.New(fileType, line.Substring(10))); } else if (line.IndexOf("type") == 0) { StatStructures.Last().Type = fileType; } else if (line.IndexOf("using") == 0) { StatStructures.Last().InheritProperties(line, StatStructures); } else if (!string.IsNullOrEmpty(line)) { StatStructures.Last().LoadProperty(line); } } } } return(true); } return(false); }
/// <summary> /// Decompresses all decompressable files recursively. /// </summary> /// <returns>The task with the list of all decompressable files.</returns> public static Task <List <string> > DecompressAllConvertableFiles() { return(Task.Run(() => { GeneralHelper.WriteToConsole($"Retrieving file list for decompression.\n"); var fileList = FileHelper.DirectorySearch(@"\\?\" + Path.GetFullPath("UnpackedData")); GeneralHelper.WriteToConsole($"Retrived file list. Starting decompression; this could take awhile.\n"); var defaultPath = @"\\?\" + FileHelper.GetPath(""); var lsxFiles = new List <string>(); Parallel.ForEach(fileList, file => { if (!string.IsNullOrEmpty(Path.GetExtension(file))) { var convertedFile = FileHelper.Convert(file.Replace(defaultPath, ""), "lsx"); if (Path.GetExtension(convertedFile) == ".lsx") { lsxFiles.Add(convertedFile); } } }); fileList.Clear(); GeneralHelper.WriteToConsole($"Decompression complete.\n"); return lsxFiles; })); }
/// <summary> /// Reads the Races.lsx file and converts it into a Race list. /// </summary> /// <param name="pak">The pak to search in.</param> /// <returns>Whether the root template was read.</returns> private bool ReadRaces(string pak) { var raceFile = FileHelper.GetPath($"{pak}\\Public\\{pak}\\Races\\Races.lsx"); if (File.Exists(raceFile)) { using (XmlReader reader = XmlReader.Create(raceFile)) { Race race = null; while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: var id = reader.GetAttribute("id"); if (id == "Race") { race = new Race { Components = new List <Component>() }; } var value = reader.GetAttribute("value"); if (reader.Depth == 5) // top level { switch (id) { case "Description": race.DescriptionHandle = value; // TODO load description break; case "DisplayName": race.DisplayNameHandle = value; // TODO load display name break; case "Name": race.Name = value; break; case "ParentGuid": race.ParentGuid = value; break; case "ProgressionTableUUID": race.ProgressionTableUUID = value; break; case "UUID": race.UUID = new Guid(value); break; } } if (reader.Depth == 6) // eye colors, hair colors, tags, makeup colors, skin colors, tattoo colors, visuals { race.Components.Add(new Component { Type = id }); } if (reader.Depth == 7) // previous level values { race.Components.Last().Guid = value; } break; case XmlNodeType.EndElement: if (reader.Depth == 4) { Races.Add(race); } break; } } } return(true); } GeneralHelper.WriteToConsole($"Failed to load Races.lsx for {pak}.pak.\n"); return(false); }