/// <summary> /// Reads the visual banks for a list of id/filepath references for quick lookup. /// </summary> /// <returns>Whether the visual bank lists were created.</returns> private bool ReadVisualBanks() { var deserializedCharacterVisualBanks = FileHelper.DeserializeObject <Dictionary <string, string> >("CharacterVisualBanks"); var deserializedVisualBanks = FileHelper.DeserializeObject <Dictionary <string, string> >("VisualBanks"); var deserializedBodySetVisuals = FileHelper.DeserializeObject <Dictionary <string, string> >("BodySetVisuals"); var deserializedMaterialBanks = FileHelper.DeserializeObject <Dictionary <string, string> >("MaterialBanks"); var deserializedTextureBanks = FileHelper.DeserializeObject <Dictionary <string, string> >("TextureBanks"); if (deserializedVisualBanks != null && deserializedCharacterVisualBanks != null && deserializedBodySetVisuals != null && deserializedMaterialBanks != null && deserializedTextureBanks != null) { CharacterVisualBanks = deserializedCharacterVisualBanks; VisualBanks = deserializedVisualBanks; BodySetVisuals = deserializedBodySetVisuals; MaterialBanks = deserializedMaterialBanks; TextureBanks = deserializedTextureBanks; return(true); } // Lookup CharacterVisualBank file from CharacterVisualResourceID var characterVisualBanks = new ConcurrentDictionary <string, string>(); var visualBanks = new ConcurrentDictionary <string, string>(); var bodySetVisuals = new ConcurrentDictionary <string, string>(); var materialBanks = new ConcurrentDictionary <string, string>(); var textureBanks = new ConcurrentDictionary <string, string>(); var visualBankFiles = GetFileList("VisualBank"); var materialBankFiles = GetFileList("MaterialBank"); var textureBankFiles = GetFileList("TextureBank"); visualBankFiles.AddRange(materialBankFiles); visualBankFiles.AddRange(textureBankFiles); visualBankFiles = visualBankFiles.Distinct().ToList(); Parallel.ForEach(visualBankFiles, visualBankFile => { if (File.Exists(visualBankFile)) { var visualBankFilePath = FileHelper.Convert(visualBankFile, "lsx", visualBankFile.Replace(".lsf", ".lsx")); var filePath = visualBankFilePath.Replace($"\\\\?\\{Directory.GetCurrentDirectory()}\\UnpackedData", string.Empty); var stream = File.OpenText(visualBankFilePath); using (var fileStream = stream) using (var reader = new XmlTextReader(fileStream)) { reader.Read(); while (!reader.EOF) { try { var sectionId = reader.GetAttribute("id"); var isNode = reader.NodeType == XmlNodeType.Element && reader.IsStartElement() && reader.Name == "node"; if (isNode && (sectionId == "CharacterVisualBank" || sectionId == "VisualBank")) { // read children for resource nodes var xml = (XElement)XNode.ReadFrom(reader); var children = xml.Element("children"); if (children != null) { var nodes = children.Elements("node"); foreach (XElement node in nodes) { var id = node.Elements("attribute").Single(a => a.Attribute("id").Value == "ID").Attribute("value").Value; if (sectionId == "CharacterVisualBank") { characterVisualBanks.TryAdd(id, filePath); var bodySetVisual = node.Elements("attribute").Single(a => a.Attribute("id").Value == "BodySetVisual").Attribute("value").Value; if (bodySetVisual != null) { bodySetVisuals.TryAdd(bodySetVisual, filePath); } } else { visualBanks.TryAdd(id, filePath); } } } reader.Skip(); } else if (isNode && sectionId == "MaterialBank") { var xml = (XElement)XNode.ReadFrom(reader); var children = xml.Element("children"); if (children != null) { var nodes = children.Elements("node"); foreach (XElement node in nodes) { var id = node.Elements("attribute").Single(a => a.Attribute("id").Value == "ID").Attribute("value").Value; materialBanks.TryAdd(id, filePath); } } reader.Skip(); } else if (isNode && sectionId == "TextureBank") { var xml = (XElement)XNode.ReadFrom(reader); var children = xml.Element("children"); if (children != null) { var nodes = children.Elements("node"); foreach (XElement node in nodes) { var id = node.Elements("attribute").Single(a => a.Attribute("id").Value == "ID").Attribute("value").Value; textureBanks.TryAdd(id, filePath); } } reader.Skip(); } else { reader.Read(); } } catch (Exception ex) { GeneralHelper.WriteToConsole($"Failed to load {filePath}.\n"); break; } } reader.Close(); } } }); CharacterVisualBanks = characterVisualBanks.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); VisualBanks = visualBanks.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); BodySetVisuals = bodySetVisuals.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); MaterialBanks = materialBanks.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); TextureBanks = textureBanks.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); FileHelper.SerializeObject(CharacterVisualBanks, "CharacterVisualBanks"); FileHelper.SerializeObject(VisualBanks, "VisualBanks"); FileHelper.SerializeObject(BodySetVisuals, "BodySetVisuals"); FileHelper.SerializeObject(MaterialBanks, "MaterialBanks"); FileHelper.SerializeObject(TextureBanks, "TextureBanks"); return(true); }
/// <summary> /// Reads the root template and converts it into a GameObject list. /// </summary> /// <returns>Whether the root template was read.</returns> private bool ReadRootTemplate() { var deserializedGameObjects = FileHelper.DeserializeObject <List <GameObject> >("GameObjects"); if (deserializedGameObjects != null) { GameObjects = deserializedGameObjects; GameObjectsCached = true; return(true); } var rootTemplates = GetFileList("GameObjects"); var typeBag = new ConcurrentBag <string>(); #if DEBUG var idBag = new ConcurrentBag <string>(); var classBag = new ConcurrentBag <Tuple <string, string> >(); #endif Parallel.ForEach(rootTemplates, rootTemplate => { if (File.Exists(rootTemplate)) { var rootTemplatePath = FileHelper.Convert(rootTemplate, "lsx", rootTemplate.Replace(".lsf", ".lsx")); var pak = Regex.Match(rootTemplatePath, @"(?<=UnpackedData\\).*?(?=\\)").Value; var stream = File.OpenText(rootTemplatePath); using (var fileStream = stream) using (var reader = new XmlTextReader(fileStream)) { reader.Read(); while (!reader.EOF) { if (reader.NodeType == XmlNodeType.Element && reader.IsStartElement() && reader.GetAttribute("id") == "GameObjects") { var xml = (XElement)XNode.ReadFrom(reader); var gameObject = new GameObject { Pak = pak, Children = new List <GameObject>(), FileLocation = rootTemplatePath.Replace($"\\\\?\\{Directory.GetCurrentDirectory()}\\UnpackedData", string.Empty) }; var attributes = xml.Elements("attribute"); foreach (XElement attribute in attributes) { var id = attribute.Attribute("id").Value; var handle = attribute.Attribute("handle")?.Value; var value = handle ?? attribute.Attribute("value").Value; var type = attribute.Attribute("type").Value; if (int.TryParse(type, out int typeInt)) { type = GeneralHelper.LarianTypeEnumConvert(type); } #if DEBUG typeBag.Add(type); idBag.Add(id); classBag.Add(new Tuple <string, string>(id, type)); #endif if (string.IsNullOrEmpty(handle)) { gameObject.LoadProperty(id, type, value); } else { gameObject.LoadProperty($"{id}Handle", type, value); var translationText = TranslationLookup.FirstOrDefault(tl => tl.Key.Equals(value)).Value?.Value; gameObject.LoadProperty(id, type, translationText); } } if (string.IsNullOrEmpty(gameObject.ParentTemplateId)) { gameObject.ParentTemplateId = gameObject.TemplateName; } if (string.IsNullOrEmpty(gameObject.Name)) { gameObject.Name = gameObject.DisplayName; } if (string.IsNullOrEmpty(gameObject.Name)) { gameObject.Name = gameObject.Stats; } GameObjectBag.Add(gameObject); reader.Skip(); } else { reader.Read(); } } reader.Close(); } } }); #if DEBUG FileHelper.SerializeObject(typeBag.ToList().Distinct().ToList(), "GameObjectTypes"); FileHelper.SerializeObject(idBag.ToList().Distinct().ToList(), "GameObjectAttributeIds"); GeneralHelper.ClassBuilder(classBag.ToList().Distinct().ToList()); #endif return(true); }