mirror of
https://github.com/4sval/FModel.git
synced 2026-03-21 17:24:26 -05:00
event triggered game directory
This commit is contained in:
parent
ed575429b1
commit
11bad8687e
|
|
@ -1 +1 @@
|
|||
Subproject commit 0c12be3c624d0e75b18b0a03915442610de54672
|
||||
Subproject commit 4e955153559be8dc156d15fc93ff8c1016d3ebfe
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ using FModel.Framework;
|
|||
using FModel.Services;
|
||||
using FModel.Settings;
|
||||
using FModel.ViewModels.ApiEndpoints.Models;
|
||||
using Serilog;
|
||||
|
||||
namespace FModel.ViewModels;
|
||||
|
||||
|
|
|
|||
|
|
@ -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<FGuid, FAesKey>(x.Guid, new FAesKey(k));
|
||||
});
|
||||
|
||||
CUE4Parse.LoadVfs(aes);
|
||||
AesManager.SetAesKeys();
|
||||
});
|
||||
RaisePropertyChanged(nameof(GameDisplayName));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public void LoadVfs(CancellationToken token, IEnumerable<FileItem> aesKeys)
|
||||
public void LoadVfs(IEnumerable<KeyValuePair<FGuid, FAesKey>> 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;
|
||||
|
|
|
|||
|
|
@ -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<FileItem> 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<FileItem>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user