/// <summary> /// Gets additional assets when the original asset file contains asset file paths within it /// </summary> /// <param name="assets">The current asset object</param> private async Task GetAdditionalAssets(HousingAssets assets) { var index = new Index(_gameDirectory); var dat = new Dat(_gameDirectory); foreach (var additionalAsset in assets.AdditionalAssetList.ToList()) { var assetFolder = Path.GetDirectoryName(additionalAsset).Replace("\\", "/"); var assetFile = Path.GetFileName(additionalAsset); var assetOffset = await index.GetDataOffset(HashGenerator.GetHash(assetFolder), HashGenerator.GetHash(assetFile), XivDataFile._01_Bgcommon); var assetData = await dat.GetType2Data(assetOffset, XivDataFile._01_Bgcommon); await Task.Run(() => { using (var br = new BinaryReader(new MemoryStream(assetData))) { br.BaseStream.Seek(20, SeekOrigin.Begin); var skip = br.ReadInt32() + 20; br.BaseStream.Seek(skip + 4, SeekOrigin.Begin); var stringsOffset = br.ReadInt32(); br.BaseStream.Seek(skip + stringsOffset, SeekOrigin.Begin); var pathCounts = 0; while (true) { // Because we don't know the length of the string, we read the data until we reach a 0 value // That 0 value is the space between strings byte a; var pathName = new List <byte>(); while ((a = br.ReadByte()) != 0) { if (a == 0xFF) { break; } pathName.Add(a); } if (a == 0xFF) { break; } // Read the string from the byte array and remove null terminators var path = Encoding.ASCII.GetString(pathName.ToArray()).Replace("\0", ""); if (path.Equals(string.Empty)) { continue; } // Add the attribute to the list if (pathCounts == 0) { assets.Shared = path; } else if (pathCounts == 1) { assets.BaseFileName = path; } else { if (path.Contains(".mdl")) { assets.MdlList.Add(path); } else if (path.Contains(".sgb")) { assets.AdditionalAssetList.Add(path); } else if (!path.Contains(".")) { assets.BaseFolder = path; } else { assets.OthersList.Add(path); } } pathCounts++; } } }); } }
/// <summary> /// Gets the assets for furniture /// </summary> /// <param name="modelID">The model id to get the assets for</param> /// <returns>A HousingAssets object containing the asset info</returns> private async Task <HousingAssets> GetFurnitureAssets(int modelID, string category) { var index = new Index(_gameDirectory); var dat = new Dat(_gameDirectory); var id = modelID.ToString().PadLeft(4, '0'); var assetFolder = ""; var assetFile = ""; if (category.Equals(XivStrings.Furniture_Indoor)) { assetFolder = $"bgcommon/hou/indoor/general/{id}/asset"; assetFile = $"fun_b0_m{id}.sgb"; } else if (category.Equals(XivStrings.Furniture_Outdoor)) { assetFolder = $"bgcommon/hou/outdoor/general/{id}/asset"; assetFile = $"gar_b0_m{id}.sgb"; } var assetOffset = await index.GetDataOffset(HashGenerator.GetHash(assetFolder), HashGenerator.GetHash(assetFile), XivDataFile._01_Bgcommon); var assetData = await dat.GetType2Data(assetOffset, XivDataFile._01_Bgcommon); var housingAssets = new HousingAssets(); await Task.Run(() => { using (var br = new BinaryReader(new MemoryStream(assetData))) { br.BaseStream.Seek(20, SeekOrigin.Begin); var skip = br.ReadInt32() + 20; br.BaseStream.Seek(skip + 4, SeekOrigin.Begin); var stringsOffset = br.ReadInt32(); br.BaseStream.Seek(skip + stringsOffset, SeekOrigin.Begin); var pathCounts = 0; while (true) { // Because we don't know the length of the string, we read the data until we reach a 0 value // That 0 value is the space between strings byte a; var pathName = new List <byte>(); while ((a = br.ReadByte()) != 0) { if (a == 0xFF) { break; } pathName.Add(a); } if (a == 0xFF) { break; } // Read the string from the byte array and remove null terminators var path = Encoding.ASCII.GetString(pathName.ToArray()).Replace("\0", ""); if (path.Equals(string.Empty)) { continue; } // Add the attribute to the list if (pathCounts == 0) { housingAssets.Shared = path; } else if (pathCounts == 1) { housingAssets.BaseFileName = path; } else { if (path.Contains(".mdl")) { housingAssets.MdlList.Add(path); } else if (path.Contains(".sgb")) { housingAssets.AdditionalAssetList.Add(path); } else if (!path.Contains(".")) { housingAssets.BaseFolder = path; } else { housingAssets.OthersList.Add(path); } } pathCounts++; } } }); if (housingAssets.AdditionalAssetList.Count > 0) { await GetAdditionalAssets(housingAssets); } return(housingAssets); }