Ejemplo n.º 1
0
 public static void Set(this PakPropertiesViewModel vm, FFileIoStoreReader ioReader)
 {
     Application.Current.Dispatcher.Invoke(delegate
     {
         vm.PakName    = ioReader.FileName;
         vm.Version    = ((int)ioReader.TocResource.Header.Version).ToString();
         vm.MountPoint = ioReader.MountPoint;
         vm.AesKey     = ioReader.AesKey?.ToStringKey();
         vm.Guid       = ioReader.EncryptionKeyGuid.Hex;
         vm.FileCount  = ioReader.Count.ToString();
     });
 }
Ejemplo n.º 2
0
        /// <summary>
        /// USER SELECTION ARRAY WILL BREAK AT THE FIRST ERROR
        /// This won't happen for other type of extraction like in diff mode where we have to skip errors
        /// </summary>
        /// <param name="selection"></param>
        /// <returns></returns>
        public static async Task GetUserSelection(IList selection)
        {
            _timer = Stopwatch.StartNew();
            ImageBoxVm.imageBoxViewModel.Reset();
            AvalonEditVm.avalonEditViewModel.Reset();
            ExtractStopVm.stopViewModel.IsEnabled    = true;
            ExtractStopVm.extractViewModel.IsEnabled = false;
            StatusBarVm.statusBarViewModel.Set(string.Empty, Properties.Resources.Loading);
            Tasks.TokenSource = new CancellationTokenSource();

            await Task.Run(() =>
            {
                foreach (var item in selection)
                {
                    if (Tasks.TokenSource.IsCancellationRequested)
                    {
                        throw new TaskCanceledException(Properties.Resources.Canceled);
                    }

                    Thread.Sleep(10); // this is actually useful because it smh unfreeze the ui so the user can cancel even tho it's a Task so...
                    if (item is ListBoxViewModel selected)
                    {
                        FFileIoStoreReader io = null;
                        if (Globals.CachedPakFiles.TryGetValue(selected.ReaderEntry.ContainerName, out var r) || Globals.CachedIoStores.TryGetValue(selected.ReaderEntry.ContainerName, out io))
                        {
                            string mount = r != null ? r.MountPoint : io !.MountPoint;
                            string ext   = selected.ReaderEntry.GetExtension();
                            switch (ext)
                            {
                            case ".ini":
                            case ".txt":
                            case ".bat":
                            case ".xml":
                            case ".h":
                            case ".uproject":
                            case ".uplugin":
                            case ".upluginmanifest":
                            case ".csv":
                            case ".json":
                                {
                                    IHighlightingDefinition syntax = ext switch
                                    {
                                        ".ini" => AvalonEditVm.IniHighlighter,
                                        ".txt" => AvalonEditVm.IniHighlighter,
                                        ".bat" => AvalonEditVm.IniHighlighter,
                                        ".csv" => AvalonEditVm.IniHighlighter,
                                        ".xml" => AvalonEditVm.XmlHighlighter,
                                        ".h" => AvalonEditVm.CppHighlighter,
                                        _ => AvalonEditVm.JsonHighlighter
                                    };
                                    using var asset  = GetMemoryStream(selected.ReaderEntry.ContainerName, mount + selected.ReaderEntry.GetPathWithoutExtension());
                                    asset.Position   = 0;
                                    using var reader = new StreamReader(asset);
                                    AvalonEditVm.avalonEditViewModel.Set(reader.ReadToEnd(), mount + selected.ReaderEntry.Name, syntax);
                                    break;
                                }

                            case ".locmeta":
                                {
                                    using var asset = GetMemoryStream(selected.ReaderEntry.ContainerName, mount + selected.ReaderEntry.GetPathWithoutExtension());
                                    asset.Position  = 0;
                                    AvalonEditVm.avalonEditViewModel.Set(JsonConvert.SerializeObject(new LocMetaReader(asset), Formatting.Indented), mount + selected.ReaderEntry.Name);
                                    break;
                                }

                            case ".locres":
                                {
                                    using var asset = GetMemoryStream(selected.ReaderEntry.ContainerName, mount + selected.ReaderEntry.GetPathWithoutExtension());
                                    asset.Position  = 0;
                                    AvalonEditVm.avalonEditViewModel.Set(JsonConvert.SerializeObject(new LocResReader(asset).Entries, Formatting.Indented), mount + selected.ReaderEntry.Name);
                                    break;
                                }

                            case ".udic":
                                {
                                    using var asset = GetMemoryStream(selected.ReaderEntry.ContainerName, mount + selected.ReaderEntry.GetPathWithoutExtension());
                                    asset.Position  = 0;
                                    AvalonEditVm.avalonEditViewModel.Set(JsonConvert.SerializeObject(new FOodleDictionaryArchive(asset).Header, Formatting.Indented), mount + selected.ReaderEntry.Name);
                                    break;
                                }

                            case ".bin":
                                {
                                    if (
                                        !selected.ReaderEntry.Name.Equals("FortniteGame/AssetRegistry.bin") && // this file is 85mb...
                                        selected.ReaderEntry.Name.Contains("AssetRegistry"))                   // only parse AssetRegistry (basically the ones in dynamic paks)
                                    {
                                        using var asset = GetMemoryStream(selected.ReaderEntry.ContainerName, mount + selected.ReaderEntry.GetPathWithoutExtension());
                                        asset.Position  = 0;
                                        AvalonEditVm.avalonEditViewModel.Set(JsonConvert.SerializeObject(new FAssetRegistryState(asset), Formatting.Indented), mount + selected.ReaderEntry.Name);
                                    }
                                    break;
                                }

                            case ".bnk":
                            case ".pck":
                                {
                                    using var asset = GetMemoryStream(selected.ReaderEntry.ContainerName, mount + selected.ReaderEntry.GetPathWithoutExtension());
                                    asset.Position  = 0;
                                    WwiseReader bnk = new WwiseReader(new BinaryReader(asset));
                                    Application.Current.Dispatcher.Invoke(delegate
                                    {
                                        DebugHelper.WriteLine("{0} {1} {2}", "[FModel]", "[Window]", $"Opening Audio Player for {selected.ReaderEntry.GetNameWithExtension()}");
                                        if (!FWindows.IsWindowOpen <Window>(Properties.Resources.AudioPlayer))
                                        {
                                            new AudioPlayer().LoadFiles(bnk.AudioFiles, mount + selected.ReaderEntry.GetPathWithoutFile());
                                        }
                                        else
                                        {
                                            ((AudioPlayer)FWindows.GetOpenedWindow <Window>(Properties.Resources.AudioPlayer)).LoadFiles(bnk.AudioFiles, mount + selected.ReaderEntry.GetPathWithoutFile());
                                        }
                                    });
                                    break;
                                }

                            case ".png":
                                {
                                    using var asset = GetMemoryStream(selected.ReaderEntry.ContainerName, mount + selected.ReaderEntry.GetPathWithoutExtension());
                                    asset.Position  = 0;
                                    ImageBoxVm.imageBoxViewModel.Set(SKBitmap.Decode(asset), mount + selected.ReaderEntry.Name);
                                    break;
                                }

                            case ".ushaderbytecode":
                                break;

                            default:
                                AvalonEditVm.avalonEditViewModel.Set(GetJsonProperties(selected.ReaderEntry, mount, true), mount + selected.ReaderEntry.Name);
                                break;
                            }

                            if (Properties.Settings.Default.AutoExport)
                            {
                                Export(selected.ReaderEntry, true);
                            }
                        }
                    }
                }
            }).ContinueWith(t =>
            {
                _timer.Stop();
                ExtractStopVm.stopViewModel.IsEnabled    = false;
                ExtractStopVm.extractViewModel.IsEnabled = true;

                if (t.Exception != null)
                {
                    Tasks.TaskCompleted(t.Exception);
                }
                else
                {
                    StatusBarVm.statusBarViewModel.Set(string.Format(Properties.Resources.TimeElapsed, _timer.ElapsedMilliseconds), Properties.Resources.Success);
                }
            },
                            TaskScheduler.FromCurrentSynchronizationContext());
        }
Ejemplo n.º 3
0
        public static async Task PopulateMenu()
        {
            PopulateBase();

            await Task.Run(async() =>
            {
                if (string.IsNullOrEmpty(Properties.Settings.Default.PakPath))
                {
                    await Application.Current.Dispatcher.InvokeAsync(delegate
                    {
                        var launcher = new FLauncher();
                        bool?result  = launcher.ShowDialog();
                        if (result.HasValue && result.Value)
                        {
                            Properties.Settings.Default.PakPath = launcher.Path;
                            Properties.Settings.Default.Save();
                        }
                    });
                }

                // Add Pak Files
                if (Properties.Settings.Default.PakPath.EndsWith("-fn.manifest"))
                {
                    ManifestInfo manifestInfo = await ManifestGrabber.TryGetLatestManifestInfo().ConfigureAwait(false);

                    if (manifestInfo == null)
                    {
                        throw new Exception("Failed to load latest manifest.");
                    }

                    DirectoryInfo chunksDir = Directory.CreateDirectory(Path.Combine(Properties.Settings.Default.OutputPath, "PakChunks"));
                    string manifestPath     = Path.Combine(chunksDir.FullName, manifestInfo.Filename);
                    byte[] manifestData;

                    if (File.Exists(manifestPath))
                    {
                        manifestData = await File.ReadAllBytesAsync(manifestPath);
                    }
                    else
                    {
                        manifestData = await manifestInfo.DownloadManifestDataAsync().ConfigureAwait(false);
                        await File.WriteAllBytesAsync(manifestPath, manifestData).ConfigureAwait(false);
                    }

                    Manifest manifest = new Manifest(manifestData, new ManifestOptions
                    {
                        ChunkBaseUri        = new Uri("http://download.epicgames.com/Builds/Fortnite/CloudDir/ChunksV3/", UriKind.Absolute),
                        ChunkCacheDirectory = Directory.CreateDirectory(Path.Combine(Properties.Settings.Default.OutputPath, "PakChunks"))
                    });
                    int pakFiles = 0;

                    foreach (FileManifest fileManifest in manifest.FileManifests)
                    {
                        if (!_pakFileRegex.IsMatch(fileManifest.Name))
                        {
                            continue;
                        }

                        var pakStream = fileManifest.GetStream();
                        if (pakStream.Length == 365)
                        {
                            continue;
                        }

                        var pakFileName = fileManifest.Name.Replace('/', '\\');
                        if (pakFileName.EndsWith(".pak"))
                        {
                            PakFileReader pakFile = new PakFileReader(pakFileName, pakStream);
                            if (pakFiles++ == 0)
                            {
                                // define the current game thank to the pak path
                                Folders.SetGameName(pakFileName);

                                Globals.Game.Version    = pakFile.Info.Version;
                                Globals.Game.SubVersion = pakFile.Info.SubVersion;
                            }

                            await Application.Current.Dispatcher.InvokeAsync(delegate
                            {
                                MenuItems.pakFiles.Add(new PakMenuItemViewModel
                                {
                                    PakFile   = pakFile,
                                    IsEnabled = false
                                });
                            });
                        }
                        else if (pakFileName.EndsWith(".ucas"))
                        {
                            var utocStream = manifest.FileManifests.FirstOrDefault(x => x.Name.Equals(fileManifest.Name.Replace(".ucas", ".utoc")));
                            var ioStore    = new FFileIoStoreReader(pakFileName.SubstringAfterLast('\\'), pakFileName.SubstringBeforeLast('\\'), utocStream.GetStream(), pakStream);
                            await Application.Current.Dispatcher.InvokeAsync(delegate
                            {
                                MenuItems.pakFiles.Add(new PakMenuItemViewModel
                                {
                                    IoStore   = ioStore,
                                    IsEnabled = false
                                });
                            });
                        }
                    }
                }
                else if (Properties.Settings.Default.PakPath.EndsWith("-val.manifest"))
                {
                    ValorantAPIManifest manifest = await ValorantAPIManifest.DownloadAndParse(Directory.CreateDirectory(Path.Combine(Properties.Settings.Default.OutputPath, "PakChunks"))).ConfigureAwait(false);

                    if (manifest == null)
                    {
                        throw new Exception("Failed to load latest manifest.");
                    }

                    for (int i = 0; i < manifest.Paks.Length; i++)
                    {
                        ValorantPak pak = manifest.Paks[i];

                        var pakFileName       = @$ "ShooterGame\Content\Paks\{pak.Name}";
                        PakFileReader pakFile = new PakFileReader(pakFileName, manifest.GetPakStream(i));

                        if (i == 0)
                        {
                            // define the current game thank to the pak path
                            Folders.SetGameName(pakFileName);

                            Globals.Game.Version    = pakFile.Info.Version;
                            Globals.Game.SubVersion = pakFile.Info.SubVersion;
                        }

                        await Application.Current.Dispatcher.InvokeAsync(delegate
                        {
                            MenuItems.pakFiles.Add(new PakMenuItemViewModel
                            {
                                PakFile   = pakFile,
                                IsEnabled = false
                            });
                        });
                    }
                }
Ejemplo n.º 4
0
        public IoPackageReader(BinaryReader uasset, Stream ubulk, FIoGlobalData globalData, FFileIoStoreReader reader, bool onlyInfo = false)
        {
            Loader     = uasset;
            _ubulk     = ubulk;
            GlobalData = globalData;
            Summary    = new FPackageSummary(this);

            var nameMap    = new List <FNameEntrySerialized>();
            var nameHashes = new List <ulong>();

            if (Summary.NameMapNamesSize > 0)
            {
                Loader.BaseStream.Position = Summary.NameMapNamesOffset;
                var nameMapNames = Loader.ReadBytes(Summary.NameMapNamesSize);
                Loader.BaseStream.Position = Summary.NameMapHashesOffset;
                var nameMapHashes = Loader.ReadBytes(Summary.NameMapHashesSize);

                FNameEntrySerialized.LoadNameBatch(nameMap, nameHashes, nameMapNames, nameMapHashes);
            }

            NameMap = nameMap.ToArray();

            Loader.BaseStream.Position = Summary.ImportMapOffset;
            var importMapCount = (Summary.ExportMapOffset - Summary.ImportMapOffset) / /*sizeof(FPackageObjectIndex)*/ sizeof(ulong);

            ImportMap = new FPackageObjectIndex[importMapCount];
            for (int i = 0; i < importMapCount; i++)
            {
                ImportMap[i] = new FPackageObjectIndex(Loader);
            }

            Loader.BaseStream.Position = Summary.ExportMapOffset;
            var exportMapCount = (Summary.ExportBundlesOffset - Summary.ExportMapOffset) / FExportMapEntry.SIZE;

            ExportMap = new FExportMapEntry[exportMapCount];
            for (int i = 0; i < exportMapCount; i++)
            {
                ExportMap[i] = new FExportMapEntry(this);
            }

            if (!onlyInfo)
            {
                ReadContent();
            }
        }
Ejemplo n.º 5
0
 public IoPackageReader(Stream uasset, Stream ubulk, FIoGlobalData globalData, FFileIoStoreReader reader, bool onlyInfo = false) : this(new BinaryReader(uasset),
                                                                                                                                        ubulk, globalData, reader, onlyInfo)
 {
 }
Ejemplo n.º 6
0
        private async Task Backup()
        {
            StatusBarVm.statusBarViewModel.Reset();
            await Task.Run(() =>
            {
                DebugHelper.WriteLine("{0} {1} {2} {3}", "[FModel]", "[BackupMenuItemViewModel]", "[Create]", $"{_backupFileName} is about to be created");
                StatusBarVm.statusBarViewModel.Set($"{Properties.Settings.Default.PakPath}", Properties.Resources.Loading);

                using FileStream fileStream = new FileStream(_backupFilePath, FileMode.Create);
                using LZ4EncoderStream compressionStream = LZ4Stream.Encode(fileStream, LZ4Level.L00_FAST);
                using BinaryWriter writer = new BinaryWriter(compressionStream);
                foreach (PakFileReader pakFile in MenuItems.pakFiles.GetPakFileReaders())
                {
                    if (pakFile.Info.bEncryptedIndex && pakFile.AesKey == null)
                    {
                        continue;
                    }

                    if (!Globals.CachedPakFiles.ContainsKey(pakFile.FileName))
                    {
                        pakFile.ReadIndex(pakFile.AesKey);
                        Globals.CachedPakFiles[pakFile.FileName] = pakFile;
                        StatusBarVm.statusBarViewModel.Set(string.Format(Properties.Resources.MountedPakTo, pakFile.FileName, pakFile.MountPoint), Properties.Resources.Loading);
                    }

                    foreach (var(_, entry) in pakFile)
                    {
                        // uasset or umap or idk
                        writer.Write(entry.Offset);
                        writer.Write(entry.Size);
                        writer.Write(entry.UncompressedSize);
                        writer.Write(entry.Encrypted);
                        writer.Write(entry.StructSize);
                        writer.Write(pakFile.MountPoint + entry.Name);
                        writer.Write(entry.CompressionMethodIndex);

                        // uexp
                        if (entry.Uexp != null && entry.Uexp is FPakEntry uexp)
                        {
                            writer.Write(uexp.Offset);
                            writer.Write(uexp.Size);
                            writer.Write(uexp.UncompressedSize);
                            writer.Write(uexp.Encrypted);
                            writer.Write(uexp.StructSize);
                            writer.Write(pakFile.MountPoint + entry.Uexp.Name);
                            writer.Write(uexp.CompressionMethodIndex);
                        }
                        // ubulk
                        if (entry.Ubulk != null && entry.Ubulk is FPakEntry ubulk)
                        {
                            writer.Write(ubulk.Offset);
                            writer.Write(ubulk.Size);
                            writer.Write(ubulk.UncompressedSize);
                            writer.Write(ubulk.Encrypted);
                            writer.Write(ubulk.StructSize);
                            writer.Write(pakFile.MountPoint + entry.Ubulk.Name);
                            writer.Write(ubulk.CompressionMethodIndex);
                        }
                    }
                }
                FFileIoStoreReader globalReader = null;
                foreach (FFileIoStoreReader ioStore in MenuItems.pakFiles.GetIoStoreReaders())
                {
                    if (ioStore.IsEncrypted && ioStore.AesKey == null)
                    {
                        continue;
                    }

                    if (!Globals.CachedIoStores.ContainsKey(ioStore.FileName))
                    {
                        if (ioStore.FileName.Contains("global.ucas", StringComparison.OrdinalIgnoreCase))
                        {
                            globalReader = ioStore;
                            continue;
                        }
                        if (!ioStore.ReadDirectoryIndex())
                        {
                            continue;
                        }
                        Globals.CachedIoStores[ioStore.FileName] = ioStore;
                        StatusBarVm.statusBarViewModel.Set(string.Format(Properties.Resources.MountedPakTo, ioStore.FileName, ioStore.MountPoint), Properties.Resources.Loading);
                    }

                    foreach (var(_, entry) in ioStore)
                    {
                        // uasset or umap or idk
                        writer.Write(entry.Offset);
                        writer.Write(entry.Length);
                        writer.Write(entry.UncompressedSize);
                        writer.Write(entry.Encrypted);
                        writer.Write(entry.StructSize);
                        writer.Write(ioStore.MountPoint + entry.Name);
                        writer.Write(entry.CompressionMethodIndex);

                        // uexp
                        if (entry.Uexp != null && entry.Uexp is FIoStoreEntry uexp)
                        {
                            writer.Write(uexp.Offset);
                            writer.Write(uexp.Length);
                            writer.Write(uexp.UncompressedSize);
                            writer.Write(uexp.Encrypted);
                            writer.Write(uexp.StructSize);
                            writer.Write(ioStore.MountPoint + entry.Uexp.Name);
                            writer.Write(uexp.CompressionMethodIndex);
                        }
                        // ubulk
                        if (entry.Ubulk != null && entry.Ubulk is FIoStoreEntry ubulk)
                        {
                            writer.Write(ubulk.Offset);
                            writer.Write(ubulk.Length);
                            writer.Write(ubulk.UncompressedSize);
                            writer.Write(ubulk.Encrypted);
                            writer.Write(ubulk.StructSize);
                            writer.Write(ioStore.MountPoint + entry.Ubulk.Name);
                            writer.Write(ubulk.CompressionMethodIndex);
                        }
                    }
                }
            }).ContinueWith(t =>
            {
                if (t.Exception != null)
                {
                    Tasks.TaskCompleted(t.Exception);
                }
                else if (new FileInfo(_backupFilePath).Length > 0)
                {
                    DebugHelper.WriteLine("{0} {1} {2} {3}", "[FModel]", "[BackupMenuItemViewModel]", "[Create]", $"{_backupFileName} successfully created");
                    StatusBarVm.statusBarViewModel.Set(string.Format(Properties.Resources.CreateSuccess, _backupFileName), Properties.Resources.Success);
                    Globals.gNotifier.ShowCustomMessage(Properties.Resources.Success, string.Format(Properties.Resources.CreateSuccess, _backupFileName), "/FModel;component/Resources/check-circle.ico", _backupFilePath);
                }
                else
                {
                    File.Delete(_backupFilePath);
                    DebugHelper.WriteLine("{0} {1} {2} {3}", "[FModel]", "[BackupMenuItemViewModel]", "[Create]", $"{_backupFileName} is empty, hence deleted");
                    StatusBarVm.statusBarViewModel.Set(string.Format(Properties.Resources.CreateError, _backupFileName), Properties.Resources.Error);
                    Globals.gNotifier.ShowCustomMessage(Properties.Resources.Error, string.Format(Properties.Resources.CreateError, _backupFileName), "/FModel;component/Resources/alert.ico");
                }
            },
                            TaskScheduler.FromCurrentSynchronizationContext());
        }