From 11bad8687e174b6c42347e5ae28e7f314cdbf31d Mon Sep 17 00:00:00 2001 From: Asval Date: Sat, 25 May 2024 19:51:43 +0200 Subject: [PATCH] event triggered game directory --- CUE4Parse | 2 +- FModel/Framework/FStatus.cs | 4 +- FModel/ViewModels/AesManagerViewModel.cs | 1 - FModel/ViewModels/ApplicationViewModel.cs | 36 ++++++++++++- FModel/ViewModels/CUE4ParseViewModel.cs | 59 ++++----------------- FModel/ViewModels/GameDirectoryViewModel.cs | 54 ++++++++++++------- 6 files changed, 83 insertions(+), 73 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index 0c12be3c..4e955153 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 0c12be3c624d0e75b18b0a03915442610de54672 +Subproject commit 4e955153559be8dc156d15fc93ff8c1016d3ebfe diff --git a/FModel/Framework/FStatus.cs b/FModel/Framework/FStatus.cs index 28421deb..a702dccb 100644 --- a/FModel/Framework/FStatus.cs +++ b/FModel/Framework/FStatus.cs @@ -38,8 +38,8 @@ public class FStatus : ViewModel UpdateStatusLabel(label); } - public void UpdateStatusLabel(string label) + public void UpdateStatusLabel(string label, string prefix = null) { - Label = Kind == EStatusKind.Loading ? $"{Kind} {label}".Trim() : Kind.ToString(); + Label = Kind == EStatusKind.Loading ? $"{prefix ?? Kind.ToString()} {label}".Trim() : Kind.ToString(); } } diff --git a/FModel/ViewModels/AesManagerViewModel.cs b/FModel/ViewModels/AesManagerViewModel.cs index a3fa522d..c581d3cd 100644 --- a/FModel/ViewModels/AesManagerViewModel.cs +++ b/FModel/ViewModels/AesManagerViewModel.cs @@ -8,7 +8,6 @@ using FModel.Framework; using FModel.Services; using FModel.Settings; using FModel.ViewModels.ApiEndpoints.Models; -using Serilog; namespace FModel.ViewModels; diff --git a/FModel/ViewModels/ApplicationViewModel.cs b/FModel/ViewModels/ApplicationViewModel.cs index bb9bdb4e..3e5bef8f 100644 --- a/FModel/ViewModels/ApplicationViewModel.cs +++ b/FModel/ViewModels/ApplicationViewModel.cs @@ -1,10 +1,15 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; +using System.Linq; using System.Threading.Tasks; using System.Windows; using CUE4Parse.Compression; +using CUE4Parse.Encryption.Aes; +using CUE4Parse.UE4.Objects.Core.Misc; +using CUE4Parse.UE4.VirtualFileSystem; using FModel.Extensions; using FModel.Framework; using FModel.Services; @@ -12,7 +17,6 @@ using FModel.Settings; using FModel.ViewModels.Commands; using FModel.Views; using FModel.Views.Resources.Controls; - using MessageBox = AdonisUI.Controls.MessageBox; using MessageBoxButton = AdonisUI.Controls.MessageBoxButton; using MessageBoxImage = AdonisUI.Controls.MessageBoxImage; @@ -78,6 +82,24 @@ public class ApplicationViewModel : ViewModel } CUE4Parse = new CUE4ParseViewModel(); + CUE4Parse.Provider.VfsRegistered += (sender, count) => + { + if (sender is not IAesVfsReader reader) return; + Status.UpdateStatusLabel($"{count} Archives ({reader.Name})", "Registered"); + CUE4Parse.GameDirectory.Add(reader); + }; + CUE4Parse.Provider.VfsMounted += (sender, count) => + { + if (sender is not IAesVfsReader reader) return; + Status.UpdateStatusLabel($"{count:N0} Packages ({reader.Name})", "Mounted"); + CUE4Parse.GameDirectory.Verify(reader); + }; + CUE4Parse.Provider.VfsUnmounted += (sender, _) => + { + if (sender is not IAesVfsReader reader) return; + CUE4Parse.GameDirectory.Disable(reader); + }; + CustomDirectories = new CustomDirectoriesViewModel(); SettingsView = new SettingsViewModel(); AesManager = new AesManagerViewModel(CUE4Parse); @@ -155,7 +177,17 @@ public class ApplicationViewModel : ViewModel CUE4Parse.ClearProvider(); await ApplicationService.ThreadWorkerView.Begin(cancellationToken => { - CUE4Parse.LoadVfs(cancellationToken, AesManager.AesKeys); + // TODO: refactor after release, select updated keys only + var aes = AesManager.AesKeys.Select(x => + { + cancellationToken.ThrowIfCancellationRequested(); // cancel if needed + + var k = x.Key.Trim(); + if (k.Length != 66) k = Constants.ZERO_64_CHAR; + return new KeyValuePair(x.Guid, new FAesKey(k)); + }); + + CUE4Parse.LoadVfs(aes); AesManager.SetAesKeys(); }); RaisePropertyChanged(nameof(GameDisplayName)); diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 109ade2d..18ebeb30 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -41,6 +41,7 @@ using CUE4Parse.GameTypes.DreamStar.Encryption.Aes; using CUE4Parse.GameTypes.PAXDEI.Encryption.Aes; using CUE4Parse.GameTypes.NetEase.MAR.Encryption.Aes; using CUE4Parse.GameTypes.FSR.Encryption.Aes; +using CUE4Parse.UE4.Objects.Core.Misc; using EpicManifestParser; using FModel.Creator; using FModel.Extensions; @@ -65,8 +66,6 @@ public class CUE4ParseViewModel : ViewModel { private ThreadWorkerViewModel _threadWorkerView => ApplicationService.ThreadWorkerView; private ApiEndpointViewModel _apiEndpointView => ApplicationService.ApiEndpointView; - private readonly Regex _hiddenArchives = new(@"^(?!global|pakchunk.+(optional|ondemand)\-).+(pak|utoc)$", // should be universal - RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); private readonly Regex _fnLive = new(@"^FortniteGame(/|\\)Content(/|\\)Paks(/|\\)", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); @@ -161,16 +160,14 @@ public class CUE4ParseViewModel : ViewModel Provider = InternalGameName switch { "StateOfDecay2" => new DefaultFileProvider(new DirectoryInfo(gameDirectory), - new DirectoryInfo[] - { - new(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\StateOfDecay2\\Saved\\Paks"), - new(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\StateOfDecay2\\Saved\\DisabledPaks") - }, SearchOption.AllDirectories, true, versionContainer), + [ + new(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\StateOfDecay2\\Saved\\Paks"), + new(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\StateOfDecay2\\Saved\\DisabledPaks") + ], SearchOption.AllDirectories, true, versionContainer), "eFootball" => new DefaultFileProvider(new DirectoryInfo(gameDirectory), - new DirectoryInfo[] - { - new(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\KONAMI\\eFootball\\ST\\Download") - }, SearchOption.AllDirectories, true, versionContainer), + [ + new(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\KONAMI\\eFootball\\ST\\Download") + ], SearchOption.AllDirectories, true, versionContainer), _ => new DefaultFileProvider(gameDirectory, SearchOption.AllDirectories, true, versionContainer) }; @@ -279,14 +276,6 @@ public class CUE4ParseViewModel : ViewModel Provider.Initialize(); Log.Information($"{Provider.Versions.Game} ({Provider.Versions.Platform}) | Archives: x{Provider.UnloadedVfs.Count} | AES: x{Provider.RequiredKeys.Count}"); - - foreach (var vfs in Provider.UnloadedVfs) // push files from the provider to the ui - { - cancellationToken.ThrowIfCancellationRequested(); - if (!_hiddenArchives.IsMatch(vfs.Name)) continue; - - GameDirectory.Add(vfs); - } }); } @@ -294,38 +283,10 @@ public class CUE4ParseViewModel : ViewModel /// load virtual files system from GameDirectory /// /// - public void LoadVfs(CancellationToken token, IEnumerable aesKeys) + public void LoadVfs(IEnumerable> aesKeys) { - GameDirectory.DeactivateAll(); - - // load files using UnloadedVfs to include non-encrypted vfs - foreach (var key in aesKeys) - { - token.ThrowIfCancellationRequested(); // cancel if needed - - var k = key.Key.Trim(); - if (k.Length != 66) k = Constants.ZERO_64_CHAR; - Provider.SubmitKey(key.Guid, new FAesKey(k)); - } + Provider.SubmitKeys(aesKeys); Provider.PostMount(); - - // files in MountedVfs will be enabled - foreach (var file in GameDirectory.DirectoryFiles) - { - token.ThrowIfCancellationRequested(); - if (Provider.MountedVfs.FirstOrDefault(x => x.Name == file.Name) is not { } vfs) - { - if (Provider.UnloadedVfs.FirstOrDefault(x => x.Name == file.Name) is IoStoreReader store) - file.FileCount = (int) store.TocResource.Header.TocEntryCount - 1; - - continue; - } - - file.IsEnabled = true; - file.MountPoint = vfs.MountPoint; - file.FileCount = vfs.FileCount; - } - InternalGameName = Provider.InternalGameName; var aesMax = Provider.RequiredKeys.Count + Provider.Keys.Count; diff --git a/FModel/ViewModels/GameDirectoryViewModel.cs b/FModel/ViewModels/GameDirectoryViewModel.cs index 714318f2..16b11656 100644 --- a/FModel/ViewModels/GameDirectoryViewModel.cs +++ b/FModel/ViewModels/GameDirectoryViewModel.cs @@ -1,8 +1,11 @@ using FModel.Framework; using System.Collections.ObjectModel; using System.ComponentModel; +using System.Linq; +using System.Text.RegularExpressions; using System.Windows; using System.Windows.Data; +using CUE4Parse.UE4.IO; using CUE4Parse.UE4.Objects.Core.Misc; using CUE4Parse.UE4.VirtualFileSystem; @@ -72,6 +75,17 @@ public class FileItem : ViewModel Length = length; } + public FileItem(IAesVfsReader reader) + { + Name = reader.Name; + Length = reader.Length; + Guid = reader.EncryptionKeyGuid; + IsEncrypted = reader.IsEncrypted; + IsEnabled = false; + Key = string.Empty; + FileCount = reader is IoStoreReader storeReader ? (int) storeReader.TocResource.Header.TocEntryCount - 1 : 0; + } + public override string ToString() { return $"{Name} | {Key}"; @@ -84,31 +98,35 @@ public class GameDirectoryViewModel : ViewModel public readonly ObservableCollection DirectoryFiles; public ICollectionView DirectoryFilesView { get; } + private readonly Regex _hiddenArchives = new(@"^(?!global|pakchunk.+(optional|ondemand)\-).+(pak|utoc)$", // should be universal + RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + public GameDirectoryViewModel() { DirectoryFiles = new ObservableCollection(); DirectoryFilesView = new ListCollectionView(DirectoryFiles) { SortDescriptions = { new SortDescription("Name", ListSortDirection.Ascending) } }; } - public void DeactivateAll() - { - foreach (var file in DirectoryFiles) - { - file.IsEnabled = false; - } - } - public void Add(IAesVfsReader reader) { - Application.Current.Dispatcher.Invoke(() => - { - DirectoryFiles.Add(new FileItem(reader.Name, reader.Length) - { - Guid = reader.EncryptionKeyGuid, - IsEncrypted = reader.IsEncrypted, - IsEnabled = false, - Key = string.Empty - }); - }); + if (!_hiddenArchives.IsMatch(reader.Name)) return; + + var fileItem = new FileItem(reader); + Application.Current.Dispatcher.Invoke(() => DirectoryFiles.Add(fileItem)); + } + + public void Verify(IAesVfsReader reader) + { + if (DirectoryFiles.FirstOrDefault(x => x.Name == reader.Name) is not { } file) return; + + file.IsEnabled = true; + file.MountPoint = reader.MountPoint; + file.FileCount = reader.FileCount; + } + + public void Disable(IAesVfsReader reader) + { + if (DirectoryFiles.FirstOrDefault(x => x.Name == reader.Name) is not { } file) return; + file.IsEnabled = false; } }