public void Load(byte[] data) { filename = string.Empty; trainConfigName = string.Empty; RpfFileEntry = new RpfBinaryFileEntry(); string str = Encoding.UTF8.GetString(data); Load(str); BuildVertices(); BuildBVH(); Loaded = true; }
public void BuildBaseJenkIndex() { JenkIndex.Clear(); StringBuilder sb = new StringBuilder(); foreach (RpfFile file in AllRpfs) { try { JenkIndex.Ensure(file.Name); foreach (RpfEntry entry in file.AllEntries) { var nlow = entry.NameLower; if (string.IsNullOrEmpty(nlow)) { continue; } //JenkIndex.Ensure(entry.Name); //JenkIndex.Ensure(nlow); int ind = nlow.LastIndexOf('.'); if (ind > 0) { JenkIndex.Ensure(entry.Name.Substring(0, ind)); JenkIndex.Ensure(nlow.Substring(0, ind)); //if (ind < entry.Name.Length - 2) //{ // JenkIndex.Ensure(entry.Name.Substring(0, ind) + ".#" + entry.Name.Substring(ind + 2)); // JenkIndex.Ensure(entry.NameLower.Substring(0, ind) + ".#" + entry.NameLower.Substring(ind + 2)); //} } else { JenkIndex.Ensure(entry.Name); JenkIndex.Ensure(nlow); } if (BuildExtendedJenkIndex) { if (nlow.EndsWith(".ydr"))// || nlow.EndsWith(".yft")) //do yft's get lods? { var sname = nlow.Substring(0, nlow.Length - 4); JenkIndex.Ensure(sname + "_lod"); JenkIndex.Ensure(sname + "_loda"); JenkIndex.Ensure(sname + "_lodb"); } if (nlow.EndsWith(".ydd")) { if (nlow.EndsWith("_children.ydd")) { var strn = nlow.Substring(0, nlow.Length - 13); JenkIndex.Ensure(strn); JenkIndex.Ensure(strn + "_lod"); JenkIndex.Ensure(strn + "_loda"); JenkIndex.Ensure(strn + "_lodb"); } var idx = nlow.LastIndexOf('_'); if (idx > 0) { var str1 = nlow.Substring(0, idx); var idx2 = str1.LastIndexOf('_'); if (idx2 > 0) { var str2 = str1.Substring(0, idx2); JenkIndex.Ensure(str2 + "_lod"); var maxi = 100; for (int i = 1; i <= maxi; i++) { var str3 = str2 + "_" + i.ToString().PadLeft(2, '0'); //JenkIndex.Ensure(str3); JenkIndex.Ensure(str3 + "_lod"); } } } } if (nlow.EndsWith(".sps")) { JenkIndex.Ensure(nlow); //for shader preset filename hashes! } if (nlow.EndsWith(".awc")) //create audio container path hashes... { string[] parts = entry.Path.Split('\\'); int pl = parts.Length; if (pl > 2) { string fn = parts[pl - 1]; string fd = parts[pl - 2]; string hpath = fn.Substring(0, fn.Length - 4); if (fd.EndsWith(".rpf")) { fd = fd.Substring(0, fd.Length - 4); } hpath = fd + "/" + hpath; if (parts[pl - 3] != "sfx") { } //no hit JenkIndex.Ensure(hpath); } } if (nlow.EndsWith(".nametable")) { RpfBinaryFileEntry binfe = entry as RpfBinaryFileEntry; if (binfe != null) { byte[] data = file.ExtractFile(binfe); if (data != null) { sb.Clear(); for (int i = 0; i < data.Length; i++) { byte c = data[i]; if (c == 0) { string str = sb.ToString(); if (!string.IsNullOrEmpty(str)) { string strl = str.ToLowerInvariant(); //JenkIndex.Ensure(str); JenkIndex.Ensure(strl); ////DirMod_Sounds_ entries apparently can be used to infer SP audio strings ////no luck here yet though //if (strl.StartsWith("dirmod_sounds_") && (strl.Length > 14)) //{ // strl = strl.Substring(14); // JenkIndex.Ensure(strl); //} } sb.Clear(); } else { sb.Append((char)c); } } } } else { } } } } } catch { //failing silently!! not so good really } } }
static void ExtractFilesInRPF(RpfFile rpf, string directoryOffset) { try { using (BinaryReader br = new BinaryReader(File.OpenRead(rpf.GetPhysicalFilePath()))) { foreach (RpfEntry entry in rpf.AllEntries) { if (!entry.NameLower.EndsWith(".rpf")) //don't try to extract rpf's, they will be done separately.. { if (entry is RpfBinaryFileEntry) { RpfBinaryFileEntry binentry = entry as RpfBinaryFileEntry; byte[] data = rpf.ExtractFileBinary(binentry, br); if (data == null) { if (binentry.FileSize == 0) { Console.WriteLine("Invalid binary file size!"); } else { Console.WriteLine("data is null!"); } } else if (data.Length == 0) { Console.WriteLine("{0} : Decompressed output was empty.", entry.Path); } else { Console.WriteLine("binary meme -> " + entry.NameLower); File.WriteAllBytes(directoryOffset + entry.NameLower, data); } } else if (entry is RpfResourceFileEntry) { RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; byte[] data = rpf.ExtractFileResource(resentry, br); data = ResourceBuilder.Compress(data); //not completely ideal to recompress it... data = ResourceBuilder.AddResourceHeader(resentry, data); if (data == null) { if (resentry.FileSize == 0) { Console.WriteLine("{0} : Resource FileSize is 0.", entry.Path); } else { Console.WriteLine("{0} : {1}", entry.Path); } } else if (data.Length == 0) { Console.WriteLine("{0} : Decompressed output was empty.", entry.Path); } else { Console.WriteLine("Potential meme -> " + entry.NameLower); foreach (KeyValuePair <string, string[]> extentionMap in extensions) { foreach (string extention in extentionMap.Value) { if (entry.NameLower.EndsWith(extention)) { Console.WriteLine("Resource meme -> " + entry.NameLower); if (extention.Equals(".ytd")) { RpfFileEntry rpfent = entry as RpfFileEntry; byte[] ytddata = rpfent.File.ExtractFile(rpfent); bool needsResized = ytddata.Length > 5242880; // 5MB YtdFile ytd = new YtdFile(); ytd.Load(ytddata, rpfent); Dictionary <uint, Texture> Dicts = new Dictionary <uint, Texture>(); bool somethingResized = false; foreach (KeyValuePair <uint, Texture> texture in ytd.TextureDict.Dict) { if (texture.Value.Width > 1440 || needsResized && texture.Value.Width > 550) // Only resize if it is greater than 1440p or 550p if vehicle is oversized { byte[] dds = DDSIO.GetDDSFile(texture.Value); string fileName = $"{texture.Value.Name}.dds"; fileName = String.Concat(fileName.Where(c => !Char.IsWhiteSpace(c))); File.WriteAllBytes("./NConvert/" + fileName, dds); Process p = new Process(); p.StartInfo.FileName = @"./NConvert/nconvert.exe"; p.StartInfo.Arguments = @"-out dds -resize 50% 50% -overwrite ./NConvert/" + fileName; p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.Start(); //Wait for the process to end. p.WaitForExit(); // Move file back File.Move("./NConvert/" + fileName, directoryOffset + fileName); byte[] resizedData = File.ReadAllBytes(directoryOffset + fileName); Texture resizedTex = DDSIO.GetTexture(resizedData); resizedTex.Name = texture.Value.Name; Console.WriteLine(resizedData.Length.ToString()); Dicts.Add(texture.Key, resizedTex); // Yeet the file, we are done with it File.Delete(directoryOffset + fileName); somethingResized = true; } else { Dicts.Add(texture.Key, texture.Value); } } // No point rebuilding the ytd when nothing was resized if (!somethingResized) { break; } TextureDictionary dic = new TextureDictionary(); dic.Textures = new ResourcePointerList64 <Texture>(); dic.TextureNameHashes = new ResourceSimpleList64_uint(); dic.Textures.data_items = Dicts.Values.ToArray(); dic.TextureNameHashes.data_items = Dicts.Keys.ToArray(); dic.BuildDict(); ytd.TextureDict = dic; byte[] resizedYtdData = ytd.Save(); File.WriteAllBytes(directoryOffset + entry.NameLower, resizedYtdData); Console.WriteLine("Done some ytd resize memes -> " + entry.NameLower); break; } File.WriteAllBytes(directoryOffset + entry.NameLower, data); break; } } } if (entry.NameLower.EndsWith(".ytd")) { latestModelName = entry.NameLower.Remove(entry.NameLower.Length - 4); } } } } else { // Write file first RpfBinaryFileEntry binentry = entry as RpfBinaryFileEntry; byte[] data = rpf.ExtractFileBinary(binentry, br); File.WriteAllBytes(directoryOffset + entry.NameLower, data); RpfFile subRPF = new RpfFile(directoryOffset + entry.NameLower, directoryOffset + entry.NameLower); if (subRPF.ScanStructure(null, null)) { //recursive memes ExtractFilesInRPF(subRPF, directoryOffset); } //yeet File.Delete(directoryOffset + entry.NameLower); } } } } catch (Exception e) { Console.WriteLine("Exception memes!"); Console.WriteLine(e.Message); } }