예제 #1
0
        public IGameDataEntry GetEntry(string name)
        {
            var file = m_directory.GetFile(name);

            if (file != null)
            {
                if (file.Name.EndsWith(".rpf"))
                {
                    var binaryFile = (IArchiveBinaryFile)file;

                    return(new ArchiveDirectoryEntry(RageArchiveWrapper7.Open(binaryFile.GetStream(), binaryFile.Name).Root, binaryFile.Name));
                }

                return(new ArchiveFileEntry(file));
            }

            var directory = m_directory.GetDirectory(name);

            if (directory != null)
            {
                return(new ArchiveDirectoryEntry(directory));
            }

            throw new FileNotFoundException();
        }
예제 #2
0
        /// <summary>
        /// Opens an archive.
        /// </summary>
        public void Load(string fileName)
        {
            // close first...
            Close();

            this.archive  = RageArchiveWrapper7.Open(fileName);
            this.fileName = fileName;
        }
예제 #3
0
        /// <summary>
        /// Creates an archive.
        /// </summary>
        public void New(string fileName)
        {
            // close first...
            Close();

            this.archive  = RageArchiveWrapper7.Create(fileName);
            this.fileName = fileName;
        }
예제 #4
0
        private void RebuildArchive(string sourceArchiveFileName, string destinationArchiveFileName)
        {
            var fileInfo           = new FileInfo(sourceArchiveFileName);
            var fileStream         = new FileStream(sourceArchiveFileName, FileMode.Open);
            var sourceArchive      = RageArchiveWrapper7.Open(fileStream, fileInfo.Name);
            var destinationArchive = RageArchiveWrapper7.Create(destinationArchiveFileName);

            RebuildDictionary(sourceArchive.Root, destinationArchive.Root, sourceArchive.archive_.Encryption);
            destinationArchive.FileName            = fileInfo.Name;
            destinationArchive.archive_.Encryption = sourceArchive.archive_.Encryption;
            destinationArchive.Flush();
        }
예제 #5
0
        public static ArchiveDirectoryEntry GetFromCache(string path)
        {
            if (ms_archiveCache.TryGetValue(path, out var value))
            {
                return(value);
            }

            var entry = new ArchiveDirectoryEntry(RageArchiveWrapper7.Open(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read), Path.GetFileName(path)).Root, Path.GetFileName(path));

            ms_archiveCache.Add(path, entry);

            return(entry);
        }
예제 #6
0
        public static void ForEachFile(string gameDirectoryName, ProcessFileDelegate processDelegate)
        {
            var archiveFileNames = Directory.GetFiles(gameDirectoryName, "*.rpf", SearchOption.AllDirectories);

            for (int i = 0; i < archiveFileNames.Length; i++)
            {
                var fileName     = archiveFileNames[i];
                var fileInfo     = new FileInfo(fileName);
                var fileStream   = new FileStream(fileName, FileMode.Open);
                var inputArchive = RageArchiveWrapper7.Open(fileStream, fileInfo.Name);
                ForEachFile(fileName.Replace(gameDirectoryName, ""), inputArchive.Root, inputArchive.archive_.Encryption, processDelegate);
                inputArchive.Dispose();
            }
        }
예제 #7
0
        private void RebuildArchiveFile(IArchiveBinaryFile sourceFile, IArchiveDirectory destinationDirectory)
        {
            var fileStream   = sourceFile.GetStream();
            var inputArchive = RageArchiveWrapper7.Open(fileStream, sourceFile.Name);
            var newF         = destinationDirectory.CreateBinaryFile();

            newF.Name = sourceFile.Name;
            var outStream     = newF.GetStream();
            var outputArchive = RageArchiveWrapper7.Create(outStream, sourceFile.Name);

            RebuildDictionary(inputArchive.Root, outputArchive.Root, inputArchive.archive_.Encryption);
            outputArchive.FileName            = sourceFile.Name;
            outputArchive.archive_.Encryption = inputArchive.archive_.Encryption;
            outputArchive.Flush();
        }
예제 #8
0
 private static void ForEachFile(string fullPathName, IArchiveDirectory directory, RageArchiveEncryption7 encryption, ProcessFileDelegate processDelegate)
 {
     foreach (var file in directory.GetFiles())
     {
         processDelegate(fullPathName + "\\" + file.Name, file, encryption);
         if ((file is IArchiveBinaryFile) && file.Name.EndsWith(".rpf", StringComparison.OrdinalIgnoreCase))
         {
             var fileStream   = ((IArchiveBinaryFile)file).GetStream();
             var inputArchive = RageArchiveWrapper7.Open(fileStream, file.Name);
             ForEachFile(fullPathName + "\\" + file.Name, inputArchive.Root, inputArchive.archive_.Encryption, processDelegate);
         }
     }
     foreach (var subDirectory in directory.GetDirectories())
     {
         ForEachFile(fullPathName + "\\" + subDirectory.Name, subDirectory, encryption, processDelegate);
     }
 }
예제 #9
0
        public static void ForEachFile(string gameDirectoryName, ProcessFileDelegate processDelegate, ErrorDelegate errorDelegate = null)
        {
            var archiveFileNames = Directory.GetFiles(gameDirectoryName, "*.rpf", SearchOption.AllDirectories);

            for (int i = 0; i < archiveFileNames.Length; i++)
            {
                try
                {
                    var fileName     = archiveFileNames[i];
                    var inputArchive = RageArchiveWrapper7.Open(fileName);
                    ForEachFile(fileName.Replace(gameDirectoryName, ""), inputArchive.Root, inputArchive.archive_.Encryption, processDelegate);
                    inputArchive.Dispose();
                }
                catch (Exception e)
                {
                    errorDelegate?.Invoke(e);
                }
            }
        }
예제 #10
0
        public static void ForFile(string fullFileName, Action <IArchiveFile, RageArchiveEncryption7> cb)
        {
            fullFileName = fullFileName.Replace('/', '\\').Replace(Settings.Default.GTAFolder + "\\", "");
            string[] split = fullFileName.Split(new string[] { ".rpf" }, StringSplitOptions.None);

            for (int i = 0; i < split.Length - 1; i++)
            {
                split[i] = split[i] + ".rpf";
            }

            var baseRpf = Settings.Default.GTAFolder + "\\" + split[0];

            try
            {
                var fileInfo   = new FileInfo(baseRpf);
                var fileStream = new FileStream(baseRpf, FileMode.Open);

                var inputArchive = RageArchiveWrapper7.Open(fileStream, fileInfo.Name);

                ArchiveUtilities.ForEachFile(split[0], inputArchive.Root, inputArchive.archive_.Encryption, (string currFullFileName, IArchiveFile file, RageArchiveEncryption7 encryption) =>
                {
                    currFullFileName = currFullFileName.Replace('/', '\\');

                    if (currFullFileName == fullFileName)
                    {
                        cb(file, encryption);
                    }
                });

                inputArchive.Dispose();
            }
            catch (Exception e)
            {
                Console.Error.WriteLine(e.Message);
            }
        }
예제 #11
0
        public static string[] GetDLCList()
        {
            Console.Error.WriteLine("Loading DLC list");

            var orderRegex    = new Regex("<order value=\"(\\d*)\"");
            var minOrderRegex = new Regex("<minOrder value=\"(\\d*)\"");
            var pathRegex     = new Regex(@"\\dlcpacks\\([a-z0-9_]*)\\");
            var pathRegex2    = new Regex(@"\\dlc_patch\\([a-z0-9_]*)\\");

            var dlclist   = new List <string>();
            var dlcOrders = new Dictionary <string, Tuple <int, int> >()
            {
                { "default", new Tuple <int, int>(0, 0) }
            };
            var fileName     = Settings.Default.GTAFolder + "\\update\\update.rpf";
            var fileInfo     = new FileInfo(fileName);
            var fileStream   = new FileStream(fileName, FileMode.Open);
            var inputArchive = RageArchiveWrapper7.Open(fileStream, fileInfo.Name);
            var doc          = new XmlDocument();

            ArchiveUtilities.ForEachFile(fileName.Replace(Settings.Default.GTAFolder, ""), inputArchive.Root, inputArchive.archive_.Encryption, (string fullFileName, IArchiveFile file, RageArchiveEncryption7 encryption) =>
            {
                if (fullFileName.EndsWith("dlclist.xml"))
                {
                    byte[] data = Utils.GetBinaryFileData((IArchiveBinaryFile)file, encryption);
                    string xml;

                    if (data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF)  // Detect BOM
                    {
                        xml = Encoding.UTF8.GetString(data, 3, data.Length - 3);
                    }
                    else
                    {
                        xml = Encoding.UTF8.GetString(data);
                    }

                    doc.LoadXml(xml);
                }
            });

            inputArchive.Dispose();


            ArchiveUtilities.ForEachFile(Settings.Default.GTAFolder, (string fullFileName, IArchiveFile file, RageArchiveEncryption7 encryption) =>
            {
                if (fullFileName.EndsWith("setup2.xml") && !fullFileName.StartsWith("\\mods"))
                {
                    byte[] data = Utils.GetBinaryFileData((IArchiveBinaryFile)file, encryption);
                    string xml;

                    if (data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF)  // Detect BOM
                    {
                        xml = Encoding.UTF8.GetString(data, 3, data.Length - 3);
                    }
                    else
                    {
                        xml = Encoding.UTF8.GetString(data);
                    }

                    var matchOrder    = orderRegex.Match(xml);
                    var matchMinOrder = minOrderRegex.Match(xml);
                    var matchPath     = pathRegex.Match(fullFileName);
                    var matchPath2    = pathRegex2.Match(fullFileName);

                    var dlcName = matchPath.Success ? matchPath.Groups[1].Value : matchPath2.Groups[1].Value;

                    dlcOrders[dlcName] = new Tuple <int, int>(matchOrder.Success ? int.Parse(matchOrder.Groups[1].Value) : 0, matchMinOrder.Success ? int.Parse(matchMinOrder.Groups[1].Value) : 0);
                }
            });

            foreach (XmlNode pathsnode in doc.DocumentElement)
            {
                foreach (XmlNode itemnode in pathsnode.ChildNodes)
                {
                    string   p    = itemnode.InnerText.ToLowerInvariant();
                    string[] path = p.Split('/');

                    if (path.Length - 2 < 0)
                    {
                        Console.Error.WriteLine("Ignoring " + p);
                    }
                    else
                    {
                        dlclist.Add(path[path.Length - 2]);
                    }
                }
            }

            var kvp  = new List <KeyValuePair <string, Tuple <int, int> > >(); // dlc name => order, minOrder
            var list = new List <string>();

            foreach (var entry in dlcOrders)
            {
                kvp.Add(entry);
            }

            kvp.Sort((a, b) => {
                int test = a.Value.Item1 - b.Value.Item1;

                if (test == 0)
                {
                    return(dlclist.IndexOf(a.Key) - dlclist.IndexOf(b.Key));
                }
                else
                {
                    return(test);
                }
            });

            for (int i = 0; i < kvp.Count; i++)
            {
                list.Add(kvp[i].Key);
            }

            return(list.ToArray());
        }
예제 #12
0
 internal RageArchiveResourceFileWrapper7(RageArchiveWrapper7 archiveWrapper, RageArchiveResourceFile7 file)
 {
     this.archiveWrapper = archiveWrapper;
     this.file           = file;
 }
예제 #13
0
        public static void BuildResourceSingle(string outputFolder, string collectionName)
        {
            Utils.EnsureKeys();

            using (RageArchiveWrapper7 rpf = RageArchiveWrapper7.Create(outputFolder + @"\dlc.rpf"))
            {
                rpf.archive_.Encryption = RageArchiveEncryption7.NG;

                var dir = rpf.Root.CreateDirectory();
                dir.Name = "common";

                var dataDir = dir.CreateDirectory();
                dataDir.Name = "data";

                dir      = rpf.Root.CreateDirectory();
                dir.Name = "x64";

                dir      = dir.CreateDirectory();
                dir.Name = "models";

                var cdimagesDir = dir.CreateDirectory();
                cdimagesDir.Name = "cdimages";

                RageArchiveWrapper7 currComponentRpf = null;
                IArchiveDirectory   currComponentDir = null;

                RageArchiveWrapper7 currPropRpf = null;
                IArchiveDirectory   currPropDir = null;

                bool hasMale        = false;
                bool hasFemale      = false;
                bool hasMaleProps   = false;
                bool hasFemaleProps = false;

                for (int sexNr = 0; sexNr < 2; ++sexNr)
                {
                    //Male YMT generating
                    YmtPedDefinitionFile ymt = new YmtPedDefinitionFile
                    {
                        metaYmtName   = Prefixes[sexNr] + collectionName,
                        Unk_376833625 = { DlcName = RageLib.Hash.Jenkins.Hash(Prefixes[sexNr] + collectionName) }
                    };

                    MUnk_3538495220[] componentTextureBindings = { null, null, null, null, null, null, null, null, null, null, null, null };
                    int[]             componentIndexes         = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                    int[]             propIndexes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

                    //ymt.Unk_376833625.Unk_1235281004 = 0;
                    //ymt.Unk_376833625.Unk_4086467184 = 0;
                    //ymt.Unk_376833625.Unk_911147899 = 0;
                    //ymt.Unk_376833625.Unk_315291935 = 0;
                    //ymt.Unk_376833625.Unk_2996560424 = ;

                    bool isAnyClothAdded = false;
                    bool isAnyPropAdded  = false;

                    foreach (ClothData clothData in MainWindow.Clothes)
                    {
                        if (clothData.IsComponent())
                        {
                            if (clothData.Textures.Count <= 0 || (int)clothData.TargetSex != sexNr)
                            {
                                continue;
                            }

                            var componentItemInfo = GenerateYmtPedComponentItem(clothData, ref componentTextureBindings);
                            ymt.Unk_376833625.CompInfos.Add(componentItemInfo);

                            var componentTypeId = componentItemInfo.Unk_3509540765;
                            GetClothPostfixes(clothData, out var ytdPostfix, out var yddPostfix);

                            if (!isAnyClothAdded)
                            {
                                isAnyClothAdded = true;

                                var ms = new MemoryStream();

                                currComponentRpf = RageArchiveWrapper7.Create(ms, FolderNames[sexNr].Replace("ped_", collectionName + "_") + ".rpf");
                                currComponentRpf.archive_.Encryption = RageArchiveEncryption7.NG;
                                currComponentDir      = currComponentRpf.Root.CreateDirectory();
                                currComponentDir.Name = Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName;
                            }

                            int currentComponentIndex = componentIndexes[componentTypeId]++;

                            string componentNumerics = currentComponentIndex.ToString().PadLeft(3, '0');
                            string prefix            = clothData.GetPrefix();

                            clothData.SetComponentNumerics(componentNumerics, currentComponentIndex);

                            var resource = currComponentDir.CreateResourceFile();
                            resource.Name = prefix + "_" + componentNumerics + "_" + yddPostfix + ".ydd";
                            resource.Import(clothData.MainPath);

                            char offsetLetter = 'a';

                            for (int i = 0; i < clothData.Textures.Count; ++i)
                            {
                                resource      = currComponentDir.CreateResourceFile();
                                resource.Name = prefix + "_diff_" + componentNumerics + "_" + (char)(offsetLetter + i) + "_" + ytdPostfix + ".ytd";
                                resource.Import(clothData.Textures[i]);
                            }

                            if (clothData.FirstPersonModelPath != "")
                            {
                                resource      = currComponentDir.CreateResourceFile();
                                resource.Name = prefix + "_" + componentNumerics + "_" + yddPostfix + "_1.ydd";
                                resource.Import(clothData.FirstPersonModelPath);
                            }
                        }
                        else
                        {
                            if (clothData.Textures.Count <= 0 || (int)clothData.TargetSex != sexNr)
                            {
                                continue;
                            }

                            Unk_2834549053 anchor = (Unk_2834549053)clothData.GetPedPropTypeId();
                            var            defs   = ymt.Unk_376833625.PropInfo.Props[anchor] ?? new List <MUnk_94549140>();
                            var            item   = GenerateYmtPedPropItem(ymt, anchor, clothData);
                            defs.Add(item);

                            if (!isAnyPropAdded)
                            {
                                isAnyPropAdded = true;

                                var ms = new MemoryStream();

                                currPropRpf = RageArchiveWrapper7.Create(ms, FolderNames[sexNr].Replace("ped_", collectionName + "_") + "_p.rpf");
                                currPropRpf.archive_.Encryption = RageArchiveEncryption7.NG;
                                currPropDir      = currPropRpf.Root.CreateDirectory();
                                currPropDir.Name = Prefixes[sexNr] + "freemode_01_p_" + Prefixes[sexNr] + collectionName;
                            }

                            int currentPropIndex = propIndexes[(byte)anchor]++;

                            string componentNumerics = currentPropIndex.ToString().PadLeft(3, '0');
                            string prefix            = clothData.GetPrefix();

                            clothData.SetComponentNumerics(componentNumerics, currentPropIndex);

                            var resource = currPropDir.CreateResourceFile();
                            resource.Name = prefix + "_" + componentNumerics + ".ydd";
                            resource.Import(clothData.MainPath);

                            char offsetLetter = 'a';
                            for (int i = 0; i < clothData.Textures.Count; ++i)
                            {
                                resource      = currPropDir.CreateResourceFile();
                                resource.Name = prefix + "_diff_" + componentNumerics + "_" + (char)(offsetLetter + i) + ".ytd";
                                resource.Import(clothData.Textures[i]);
                            }
                        }
                    }

                    if (isAnyClothAdded)
                    {
                        if (sexNr == 0)
                        {
                            hasMale = true;
                        }
                        else if (sexNr == 1)
                        {
                            hasFemale = true;
                        }

                        UpdateYmtComponentTextureBindings(componentTextureBindings, ymt);
                    }

                    if (isAnyClothAdded || isAnyPropAdded)
                    {
                        using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(GenerateShopMeta((Sex)sexNr, collectionName))))
                        {
                            var binFile = dataDir.CreateBinaryFile();
                            binFile.Name = Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName + ".meta";
                            binFile.Import(stream);
                        }
                        currComponentRpf.Flush();

                        var binRpfFile = cdimagesDir.CreateBinaryFile();
                        binRpfFile.Name = FolderNames[sexNr].Replace("ped_", collectionName + "_") + ".rpf";
                        binRpfFile.Import(currComponentRpf.archive_.BaseStream);

                        currComponentRpf.Dispose();
                    }

                    if (isAnyPropAdded)
                    {
                        if (sexNr == 0)
                        {
                            hasMaleProps = true;
                        }
                        else if (sexNr == 1)
                        {
                            hasFemaleProps = true;
                        }

                        currPropRpf.Flush();

                        var binRpfFile = cdimagesDir.CreateBinaryFile();
                        binRpfFile.Name = FolderNames[sexNr].Replace("ped_", collectionName + "_") + "_p.rpf";
                        binRpfFile.Import(currPropRpf.archive_.BaseStream);

                        currPropRpf.Dispose();
                    }
                }

                using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(GenerateSingleplayerContentXml(collectionName, hasMale, hasFemale, hasMaleProps, hasFemaleProps))))
                {
                    var binFile = rpf.Root.CreateBinaryFile();
                    binFile.Name = "content.xml";
                    binFile.Import(stream);
                }

                using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(GenerateSingleplayerSetup2Xml(collectionName))))
                {
                    var binFile = rpf.Root.CreateBinaryFile();
                    binFile.Name = "setup2.xml";
                    binFile.Import(stream);
                }

                rpf.Flush();
                rpf.Dispose();
            }
        }
예제 #14
0
        static void HandleFixArchiveOptions(string[] args)
        {
            CommandLine.Parse <FixArchiveOptions>(args, (opts, gOpts) =>
            {
                EnsurePath();
                EnsureKeys();

                if (opts.InputFiles != null)
                {
                    var inputFiles = Utils.Expand(opts.InputFiles);

                    for (int i = 0; i < inputFiles.Length; i++)
                    {
                        var fileInfo = inputFiles[i];

                        Console.WriteLine(fileInfo.FullName);

                        using (RageArchiveWrapper7 inputArchive = RageArchiveWrapper7.Open(fileInfo.FullName))
                        {
                            var rpfs = new List <Tuple <string, RageArchiveWrapper7> >();

                            if (opts.Recursive)
                            {
                                ArchiveUtilities.ForEachFile(fileInfo.FullName.Replace(Settings.Default.GTAFolder, ""), inputArchive.Root, inputArchive.archive_.Encryption, (string fullFileName, IArchiveFile file, RageArchiveEncryption7 encryption) =>
                                {
                                    if (fullFileName.EndsWith(".rpf", StringComparison.OrdinalIgnoreCase))
                                    {
                                        try
                                        {
                                            var binFile   = (RageArchiveBinaryFileWrapper7)file;
                                            var tmpStream = new FileStream(Path.GetTempFileName(), FileMode.Open);

                                            binFile.Export(tmpStream);
                                            RageArchiveWrapper7 archive = RageArchiveWrapper7.Open(tmpStream, file.Name);

                                            var wrapper = RageArchiveWrapper7.Open(tmpStream, binFile.Name);

                                            rpfs.Add(new Tuple <string, RageArchiveWrapper7>(fullFileName, wrapper));
                                        }
                                        catch (Exception e)
                                        {
                                            Console.Error.WriteLine(e.Message);
                                        }
                                    }
                                });

                                rpfs.Sort((a, b) =>
                                {
                                    return(b.Item1.Replace('\\', '/').Split('/').Length - a.Item1.Replace('\\', '/').Split('/').Length);
                                });
                            }

                            bool found = false;

                            if (opts.Recursive)
                            {
                                for (int j = 0; j < rpfs.Count; j++)
                                {
                                    var fullName = rpfs[j].Item1;
                                    var wrapper  = rpfs[j].Item2;

                                    if (wrapper.archive_.Encryption != RageArchiveEncryption7.None)
                                    {
                                        Console.WriteLine("SKIP " + fullName);
                                        continue;
                                    }

                                    found = true;

                                    wrapper.archive_.Encryption = RageArchiveEncryption7.NG;
                                    wrapper.Flush();
                                    wrapper.Dispose();

                                    Console.WriteLine("ENCRYPT " + fullName);
                                }
                            }

                            if (inputArchive.archive_.Encryption != RageArchiveEncryption7.None && !found)
                            {
                                Console.WriteLine("SKIP " + fileInfo.Name);
                                continue;
                            }

                            inputArchive.archive_.Encryption = RageArchiveEncryption7.NG;
                            inputArchive.Flush();
                            inputArchive.Dispose();

                            Console.WriteLine("ENCRYPT " + fileInfo.Name);

                            rpfs.Reverse();

                            for (int j = 0; j < rpfs.Count; j++)
                            {
                                rpfs[j].Item2.Dispose();
                            }
                        }
                    }
                }
            });
        }
예제 #15
0
        static void HandleExtractArchiveOptions(string[] args)
        {
            CommandLine.Parse <ExtractArchiveOptions>(args, (opts, gOpts) =>
            {
                EnsurePath();
                EnsureKeys();

                if (opts.InputFile == null)
                {
                    Console.WriteLine("Please provide input archive with -i --input");
                    return;
                }

                if (opts.OutputFolder == null)
                {
                    Console.WriteLine("Please provide output folder with -o --output");
                    return;
                }

                var fileInfo   = new FileInfo(opts.InputFile);
                var fileStream = new FileStream(opts.InputFile, FileMode.Open);

                var inputArchive = RageArchiveWrapper7.Open(fileStream, fileInfo.Name);

                var queue = new List <Tuple <string, RageArchiveWrapper7, bool> >()
                {
                    new Tuple <string, RageArchiveWrapper7, bool>(fileInfo.FullName, inputArchive, false)
                };

                while (queue.Count > 0)
                {
                    var fullPath    = queue[0].Item1;
                    var rpf         = queue[0].Item2;
                    var isTmpStream = queue[0].Item3;

                    queue.RemoveAt(0);

                    ArchiveUtilities.ForEachFile(fullPath.Replace(fileInfo.FullName, ""), rpf.Root, rpf.archive_.Encryption, (string fullFileName, IArchiveFile file, RageArchiveEncryption7 encryption) =>
                    {
                        string path = opts.OutputFolder + fullFileName;
                        string dir  = Path.GetDirectoryName(path);

                        if (!Directory.Exists(dir))
                        {
                            Directory.CreateDirectory(dir);
                        }

                        Console.WriteLine(fullFileName);

                        if (file.Name.EndsWith(".rpf"))
                        {
                            try
                            {
                                var tmpStream = new FileStream(Path.GetTempFileName(), FileMode.Open);

                                file.Export(tmpStream);
                                RageArchiveWrapper7 archive = RageArchiveWrapper7.Open(tmpStream, file.Name);
                                queue.Add(new Tuple <string, RageArchiveWrapper7, bool>(fullFileName, archive, true));
                            }
                            catch (Exception e)
                            {
                                Console.Error.WriteLine(e.Message);
                            }
                        }
                        else
                        {
                            if (file.Name.EndsWith(".xml") || file.Name.EndsWith(".meta"))
                            {
                                byte[] data = Utils.GetBinaryFileData((IArchiveBinaryFile)file, encryption);
                                string xml;

                                if (data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF)  // Detect BOM
                                {
                                    xml = Encoding.UTF8.GetString(data, 3, data.Length - 3);
                                }
                                else
                                {
                                    xml = Encoding.UTF8.GetString(data);
                                }

                                File.WriteAllText(path, xml, Encoding.UTF8);
                            }
                            else
                            {
                                file.Export(path);
                            }
                        }
                    });

                    var stream      = (FileStream)rpf.archive_.BaseStream;
                    string fileName = stream.Name;

                    rpf.Dispose();

                    if (isTmpStream)
                    {
                        File.Delete(fileName);
                    }
                }
            });
        }
예제 #16
0
        public static void BuildResourceSingle(string outputFolder, string collectionName)
        {
            Utils.EnsureKeys();

            using (RageArchiveWrapper7 rpf = RageArchiveWrapper7.Create(outputFolder + @"\dlc.rpf"))
            {
                rpf.archive_.Encryption = RageArchiveEncryption7.NG;

                var dir = rpf.Root.CreateDirectory();
                dir.Name = "common";

                var dataDir = dir.CreateDirectory();
                dataDir.Name = "data";

                dir      = rpf.Root.CreateDirectory();
                dir.Name = "x64";

                dir      = dir.CreateDirectory();
                dir.Name = "models";

                var cdimagesDir = dir.CreateDirectory();
                cdimagesDir.Name = "cdimages";

                RageArchiveWrapper7 currComponentRpf = null;
                IArchiveDirectory   currComponentDir = null;

                RageArchiveWrapper7 currPropRpf = null;
                IArchiveDirectory   currPropDir = null;

                bool hasMale        = false;
                bool hasFemale      = false;
                bool hasMaleProps   = false;
                bool hasFemaleProps = false;

                for (int sexNr = 0; sexNr < 2; ++sexNr)
                {
                    //Male YMT generating
                    YmtPedDefinitionFile ymt = new YmtPedDefinitionFile();

                    ymt.metaYmtName           = prefixes[sexNr] + collectionName;
                    ymt.Unk_376833625.DlcName = RageLib.Hash.Jenkins.Hash(prefixes[sexNr] + collectionName);

                    MUnk_3538495220[] componentTextureBindings = { null, null, null, null, null, null, null, null, null, null, null, null };
                    int[]             componentIndexes         = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                    int[]             propIndexes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

                    //ymt.Unk_376833625.Unk_1235281004 = 0;
                    //ymt.Unk_376833625.Unk_4086467184 = 0;
                    //ymt.Unk_376833625.Unk_911147899 = 0;
                    //ymt.Unk_376833625.Unk_315291935 = 0;
                    //ymt.Unk_376833625.Unk_2996560424 = ;

                    bool isAnyClothAdded = false;
                    bool isAnyPropAdded  = false;

                    foreach (ClothData cd in MainWindow.clothes)
                    {
                        if (cd.IsComponent())
                        {
                            byte componentTypeID = cd.GetComponentTypeID();

                            if (cd.textures.Count > 0 && (int)cd.targetSex == sexNr)
                            {
                                YmtPedDefinitionFile targetYmt = ymt;

                                if (componentTextureBindings[componentTypeID] == null)
                                {
                                    componentTextureBindings[componentTypeID] = new MUnk_3538495220();
                                }

                                MUnk_1535046754 textureDescription = new MUnk_1535046754();

                                byte nextPropMask = 17;

                                switch (componentTypeID)
                                {
                                case 2:
                                case 7:
                                    nextPropMask = 11; break;

                                case 5:
                                case 8:
                                    nextPropMask = 65; break;

                                case 9:
                                    nextPropMask = 1; break;

                                case 10:
                                    nextPropMask = 5; break;

                                case 11:
                                    nextPropMask = 1; break;

                                default:
                                    break;
                                }

                                textureDescription.PropMask       = nextPropMask;
                                textureDescription.Unk_2806194106 = (byte)(cd.fpModelPath != "" ? 1 : 0);

                                byte   texId      = (byte)(cd.mainPath.EndsWith("_u.ydd") ? 0 : 1);
                                string postfix    = cd.mainPath.EndsWith("_u.ydd") ? "u" : "r";
                                string ytdPostfix = cd.mainPath.EndsWith("_u.ydd") ? "uni" : "whi";

                                foreach (string texPath in cd.textures)
                                {
                                    MUnk_1036962405 texInfo = new MUnk_1036962405();
                                    texInfo.Distribution = 255;
                                    texInfo.TexId        = texId;
                                    textureDescription.ATexData.Add(texInfo);
                                }

                                textureDescription.ClothData.Unk_2828247905 = 0;

                                componentTextureBindings[componentTypeID].Unk_1756136273.Add(textureDescription);

                                byte componentTextureLocalId = (byte)(componentTextureBindings[componentTypeID].Unk_1756136273.Count - 1);

                                MCComponentInfo componentInfo = new MCComponentInfo();
                                componentInfo.Unk_802196719    = 0;
                                componentInfo.Unk_4233133352   = 0;
                                componentInfo.Unk_128864925.b0 = (byte)(cd.componentFlags.unkFlag1 ? 1 : 0);
                                componentInfo.Unk_128864925.b1 = (byte)(cd.componentFlags.unkFlag2 ? 1 : 0);
                                componentInfo.Unk_128864925.b2 = (byte)(cd.componentFlags.unkFlag3 ? 1 : 0);
                                componentInfo.Unk_128864925.b3 = (byte)(cd.componentFlags.unkFlag4 ? 1 : 0);
                                componentInfo.Unk_128864925.b4 = (byte)(cd.componentFlags.isHighHeels ? 1 : 0);
                                componentInfo.Flags            = 0;
                                componentInfo.Inclusions       = 0;
                                componentInfo.Exclusions       = 0;
                                componentInfo.Unk_1613922652   = 0;
                                componentInfo.Unk_2114993291   = 0;
                                componentInfo.Unk_3509540765   = componentTypeID;
                                componentInfo.Unk_4196345791   = componentTextureLocalId;

                                targetYmt.Unk_376833625.CompInfos.Add(componentInfo);

                                if (!isAnyClothAdded)
                                {
                                    isAnyClothAdded = true;

                                    var ms = new MemoryStream();

                                    currComponentRpf = RageArchiveWrapper7.Create(ms, folderNames[sexNr].Replace("ped_", collectionName + "_") + ".rpf");
                                    currComponentRpf.archive_.Encryption = RageArchiveEncryption7.NG;
                                    currComponentDir      = currComponentRpf.Root.CreateDirectory();
                                    currComponentDir.Name = prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName;
                                }

                                int currentComponentIndex = componentIndexes[componentTypeID]++;

                                string componentNumerics = currentComponentIndex.ToString().PadLeft(3, '0');
                                string prefix            = cd.GetPrefix();

                                var resource = currComponentDir.CreateResourceFile();
                                resource.Name = prefix + "_" + componentNumerics + "_" + postfix + ".ydd";
                                resource.Import(cd.mainPath);

                                char offsetLetter = 'a';

                                for (int i = 0; i < cd.textures.Count; ++i)
                                {
                                    resource      = currComponentDir.CreateResourceFile();
                                    resource.Name = prefix + "_diff_" + componentNumerics + "_" + (char)(offsetLetter + i) + "_" + ytdPostfix + ".ytd";
                                    resource.Import(cd.textures[i]);
                                }

                                if (cd.fpModelPath != "")
                                {
                                    resource      = currComponentDir.CreateResourceFile();
                                    resource.Name = prefix + "_" + componentNumerics + "_" + postfix + "_1.ydd";
                                    resource.Import(cd.fpModelPath);
                                }
                            }
                        }
                        else
                        {
                            Unk_2834549053 anchor = (Unk_2834549053)cd.GetPedPropTypeID();

                            if (cd.textures.Count > 0 && (int)cd.targetSex == sexNr)
                            {
                                YmtPedDefinitionFile targetYmt = ymt;

                                var defs = ymt.Unk_376833625.PropInfo.Props[anchor] ?? new List <MUnk_94549140>();
                                var item = new MUnk_94549140(ymt.Unk_376833625.PropInfo);

                                item.AnchorId = (byte)anchor;

                                for (int i = 0; i < cd.textures.Count; i++)
                                {
                                    var texture = new MUnk_254518642();
                                    texture.TexId = (byte)i;
                                    item.TexData.Add(texture);
                                }

                                // Get or create linked anchor
                                var aanchor = ymt.Unk_376833625.PropInfo.AAnchors.Find(e => e.Anchor == anchor);

                                if (aanchor == null)
                                {
                                    aanchor = new MCAnchorProps(ymt.Unk_376833625.PropInfo)
                                    {
                                        Anchor = anchor
                                    };

                                    aanchor.PropsMap[item] = (byte)item.TexData.Count;

                                    ymt.Unk_376833625.PropInfo.AAnchors.Add(aanchor);
                                }
                                else
                                {
                                    aanchor.PropsMap[item] = (byte)item.TexData.Count;
                                }

                                defs.Add(item);

                                if (!isAnyPropAdded)
                                {
                                    isAnyPropAdded = true;

                                    var ms = new MemoryStream();

                                    currPropRpf = RageArchiveWrapper7.Create(ms, folderNames[sexNr].Replace("ped_", collectionName + "_") + "_p.rpf");
                                    currPropRpf.archive_.Encryption = RageArchiveEncryption7.NG;
                                    currPropDir      = currPropRpf.Root.CreateDirectory();
                                    currPropDir.Name = prefixes[sexNr] + "freemode_01_p_" + prefixes[sexNr] + collectionName;
                                }

                                int currentPropIndex = propIndexes[(byte)anchor]++;

                                string componentNumerics = currentPropIndex.ToString().PadLeft(3, '0');
                                string prefix            = cd.GetPrefix();

                                var resource = currPropDir.CreateResourceFile();
                                resource.Name = prefix + "_" + componentNumerics + ".ydd";
                                resource.Import(cd.mainPath);

                                char offsetLetter = 'a';
                                for (int i = 0; i < cd.textures.Count; ++i)
                                {
                                    resource      = currPropDir.CreateResourceFile();
                                    resource.Name = prefix + "_diff_" + componentNumerics + "_" + (char)(offsetLetter + i) + ".ytd";
                                    resource.Import(cd.textures[i]);
                                }
                            }
                        }
                    }

                    if (isAnyClothAdded)
                    {
                        if (sexNr == 0)
                        {
                            hasMale = true;
                        }
                        else if (sexNr == 1)
                        {
                            hasFemale = true;
                        }

                        int arrIndex = 0;
                        for (int i = 0; i < componentTextureBindings.Length; ++i)
                        {
                            if (componentTextureBindings[i] != null)
                            {
                                byte id = (byte)(arrIndex++);
                                ymt.Unk_376833625.Unk_2996560424.SetByte(i, id);
                            }

                            ymt.Unk_376833625.Components[(Unk_884254308)i] = componentTextureBindings[i];
                        }
                    }

                    if (isAnyClothAdded || isAnyPropAdded)
                    {
                        using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(GenerateShopMeta((Sex)sexNr, collectionName))))
                        {
                            var binFile = dataDir.CreateBinaryFile();
                            binFile.Name = prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName + ".meta";
                            binFile.Import(stream);
                        }
                        currComponentRpf.Flush();

                        var binRpfFile = cdimagesDir.CreateBinaryFile();
                        binRpfFile.Name = folderNames[sexNr].Replace("ped_", collectionName + "_") + ".rpf";
                        binRpfFile.Import(currComponentRpf.archive_.BaseStream);

                        currComponentRpf.Dispose();
                    }

                    if (isAnyPropAdded)
                    {
                        if (sexNr == 0)
                        {
                            hasMaleProps = true;
                        }
                        else if (sexNr == 1)
                        {
                            hasFemaleProps = true;
                        }

                        currPropRpf.Flush();

                        var binRpfFile = cdimagesDir.CreateBinaryFile();
                        binRpfFile.Name = folderNames[sexNr].Replace("ped_", collectionName + "_") + "_p.rpf";
                        binRpfFile.Import(currPropRpf.archive_.BaseStream);

                        currPropRpf.Dispose();
                    }
                }

                using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(GenerateContentXML(collectionName, hasMale, hasFemale, hasMaleProps, hasFemaleProps))))
                {
                    var binFile = rpf.Root.CreateBinaryFile();
                    binFile.Name = "content.xml";
                    binFile.Import(stream);
                }

                using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(GenerateSetup2XML(collectionName))))
                {
                    var binFile = rpf.Root.CreateBinaryFile();
                    binFile.Name = "setup2.xml";
                    binFile.Import(stream);
                }

                rpf.Flush();
                rpf.Dispose();

                MessageBox.Show("Resource built!");
            }
        }
예제 #17
0
        static void HandleCreateArchiveOptions(string[] args)
        {
            CommandLine.Parse <CreateArchiveOptions>(args, (opts, gOpts) =>
            {
                EnsurePath();
                EnsureKeys();

                if (opts.InputFolder == null)
                {
                    Console.WriteLine("Please provide input folder with -i --input");
                    return;
                }

                if (opts.OutputFolder == null)
                {
                    Console.WriteLine("Please provide output folder with -o --output");
                    return;
                }

                if (opts.Name == null)
                {
                    Console.WriteLine("Please provide rpf name with -n --name");
                    return;
                }

                string rpfPath = opts.OutputFolder + "\\" + opts.Name + ".rpf";

                using (RageArchiveWrapper7 rpf = RageArchiveWrapper7.Create(rpfPath))
                {
                    var queue = new List <Tuple <string, IArchiveDirectory, RageArchiveWrapper7> >()
                    {
                        new Tuple <string, IArchiveDirectory, RageArchiveWrapper7>(opts.InputFolder, rpf.Root, rpf)
                    };

                    var subRpfs = new List <Tuple <DirectoryInfo, IArchiveDirectory, RageArchiveWrapper7> >();

                    rpf.archive_.Encryption = RageArchiveEncryption7.NG;

                    var rpfs = new List <RageArchiveWrapper7>();

                    while (queue.Count > 0)
                    {
                        var folder  = queue[0].Item1;
                        var curr    = queue[0].Item2;
                        var currRpf = queue[0].Item3;

                        if (rpfs.IndexOf(currRpf) == -1)
                        {
                            rpfs.Add(currRpf);
                        }

                        Console.WriteLine(folder);

                        queue.RemoveAt(0);

                        string newFolder               = null;
                        IArchiveDirectory newCurr      = null;
                        RageArchiveWrapper7 newCurrRpf = null;

                        string[] folders = Directory.GetDirectories(folder);
                        string[] files   = Directory.GetFiles(folder);

                        for (int i = 0; i < folders.Length; i++)
                        {
                            var folderInfo = new DirectoryInfo(folders[i]);

                            newFolder = folders[i];

                            if (folders[i].EndsWith(".rpf"))
                            {
                                var tmpStream = new FileStream(Path.GetTempFileName(), FileMode.Open);
                                var subRpf    = RageArchiveWrapper7.Create(tmpStream, folderInfo.Name);

                                subRpf.archive_.Encryption = RageArchiveEncryption7.NG;

                                subRpfs.Add(new Tuple <DirectoryInfo, IArchiveDirectory, RageArchiveWrapper7>(folderInfo, curr, subRpf));

                                newCurr    = subRpf.Root;
                                newCurrRpf = subRpf;
                            }
                            else
                            {
                                var directory  = curr.CreateDirectory();
                                directory.Name = folderInfo.Name;

                                newCurr    = directory;
                                newCurrRpf = currRpf;
                            }

                            queue.Add(new Tuple <string, IArchiveDirectory, RageArchiveWrapper7>(newFolder, newCurr, newCurrRpf));
                        }

                        if (folders.Length + files.Length == 0)
                        {
                            Console.WriteLine("  .\\.empty");
                            var binFile  = curr.CreateBinaryFile();
                            binFile.Name = ".empty";

                            var ms = new MemoryStream(1);

                            ms.WriteByte(0);

                            ms.Flush();

                            binFile.Import(ms);
                        }

                        for (int i = 0; i < files.Length; i++)
                        {
                            string file  = files[i];
                            var fileInfo = new FileInfo(file);

                            bool isResource = false;

                            for (int j = 0; j < ResourceFileTypes_GTA5_pc.AllTypes.Count; j++)
                            {
                                var type = ResourceFileTypes_GTA5_pc.AllTypes[j];

                                if (file.EndsWith(type.Extension))
                                {
                                    Console.WriteLine("  " + file);

                                    isResource = true;

                                    var resource  = curr.CreateResourceFile();
                                    resource.Name = fileInfo.Name;
                                    resource.Import(file);

                                    break;
                                }
                            }

                            if (!isResource)
                            {
                                Console.WriteLine("  " + file);
                                var binFile  = curr.CreateBinaryFile();
                                binFile.Name = fileInfo.Name;
                                binFile.Import(file);
                            }
                        }
                    }

                    rpfs.Reverse();

                    for (int i = 0; i < subRpfs.Count; i++)
                    {
                        var subRpf = subRpfs[i];

                        var file  = subRpf.Item2.CreateBinaryFile();
                        file.Name = subRpf.Item1.Name;

                        subRpf.Item3.Flush();

                        file.Import(subRpf.Item3.archive_.BaseStream);
                    }

                    for (int i = 0; i < rpfs.Count; i++)
                    {
                        rpfs[i].Flush();

                        if (i + 1 < rpfs.Count)
                        {
                            var stream      = (FileStream)rpfs[i].archive_.BaseStream;
                            string fileName = stream.Name;

                            rpfs[i].Dispose();

                            File.Delete(fileName);
                        }
                    }
                }
            });
        }