mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-13 20:24:17 +01:00
Make extracting mods cancelable, some fixes.
This commit is contained in:
parent
cf54bc7f57
commit
5e46f43d7d
9 changed files with 182 additions and 108 deletions
2
OtterGui
2
OtterGui
|
|
@ -1 +1 @@
|
||||||
Subproject commit 627e313232a2e602432dcc4d090dccd5e27993a1
|
Subproject commit a1ff5ca207080786225f716a0e2487e206923a52
|
||||||
|
|
@ -30,6 +30,11 @@ public partial class Configuration
|
||||||
|
|
||||||
public static void Migrate( Configuration config )
|
public static void Migrate( Configuration config )
|
||||||
{
|
{
|
||||||
|
if( !File.Exists( Dalamud.PluginInterface.ConfigFile.FullName ) )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var m = new Migration
|
var m = new Migration
|
||||||
{
|
{
|
||||||
_config = config,
|
_config = config,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Dalamud.Logging;
|
using Dalamud.Logging;
|
||||||
using ICSharpCode.SharpZipLib.Zip;
|
using ICSharpCode.SharpZipLib.Zip;
|
||||||
|
|
@ -11,7 +13,7 @@ using FileMode = System.IO.FileMode;
|
||||||
|
|
||||||
namespace Penumbra.Import;
|
namespace Penumbra.Import;
|
||||||
|
|
||||||
public partial class TexToolsImporter
|
public partial class TexToolsImporter : IDisposable
|
||||||
{
|
{
|
||||||
private const string TempFileName = "textools-import";
|
private const string TempFileName = "textools-import";
|
||||||
private static readonly JsonSerializerSettings JsonSettings = new() { NullValueHandling = NullValueHandling.Ignore };
|
private static readonly JsonSerializerSettings JsonSettings = new() { NullValueHandling = NullValueHandling.Ignore };
|
||||||
|
|
@ -21,22 +23,59 @@ public partial class TexToolsImporter
|
||||||
|
|
||||||
private readonly IEnumerable< FileInfo > _modPackFiles;
|
private readonly IEnumerable< FileInfo > _modPackFiles;
|
||||||
private readonly int _modPackCount;
|
private readonly int _modPackCount;
|
||||||
|
private FileStream? _tmpFileStream;
|
||||||
|
private StreamDisposer? _streamDisposer;
|
||||||
|
private readonly CancellationTokenSource _cancellation = new();
|
||||||
|
private readonly CancellationToken _token;
|
||||||
|
|
||||||
public ImporterState State { get; private set; }
|
public ImporterState State { get; private set; }
|
||||||
public readonly List< (FileInfo File, DirectoryInfo? Mod, Exception? Error) > ExtractedMods;
|
public readonly List< (FileInfo File, DirectoryInfo? Mod, Exception? Error) > ExtractedMods;
|
||||||
|
|
||||||
public TexToolsImporter( DirectoryInfo baseDirectory, ICollection< FileInfo > files )
|
public TexToolsImporter( DirectoryInfo baseDirectory, ICollection< FileInfo > files,
|
||||||
: this( baseDirectory, files.Count, files )
|
Action< FileInfo, DirectoryInfo?, Exception? > handler )
|
||||||
|
: this( baseDirectory, files.Count, files, handler )
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public TexToolsImporter( DirectoryInfo baseDirectory, int count, IEnumerable< FileInfo > modPackFiles )
|
public TexToolsImporter( DirectoryInfo baseDirectory, int count, IEnumerable< FileInfo > modPackFiles,
|
||||||
|
Action< FileInfo, DirectoryInfo?, Exception? > handler )
|
||||||
{
|
{
|
||||||
_baseDirectory = baseDirectory;
|
_baseDirectory = baseDirectory;
|
||||||
_tmpFile = Path.Combine( _baseDirectory.FullName, TempFileName );
|
_tmpFile = Path.Combine( _baseDirectory.FullName, TempFileName );
|
||||||
_modPackFiles = modPackFiles;
|
_modPackFiles = modPackFiles;
|
||||||
_modPackCount = count;
|
_modPackCount = count;
|
||||||
ExtractedMods = new List< (FileInfo, DirectoryInfo?, Exception?) >( count );
|
ExtractedMods = new List< (FileInfo, DirectoryInfo?, Exception?) >( count );
|
||||||
Task.Run( ImportFiles );
|
_token = _cancellation.Token;
|
||||||
|
Task.Run( ImportFiles, _token )
|
||||||
|
.ContinueWith( _ => CloseStreams() )
|
||||||
|
.ContinueWith( _ =>
|
||||||
|
{
|
||||||
|
foreach( var (file, dir, error) in ExtractedMods )
|
||||||
|
{
|
||||||
|
handler( file, dir, error );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CloseStreams()
|
||||||
|
{
|
||||||
|
_tmpFileStream?.Dispose();
|
||||||
|
_tmpFileStream = null;
|
||||||
|
ResetStreamDisposer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_cancellation.Cancel( true );
|
||||||
|
if( State != ImporterState.WritingPackToDisk )
|
||||||
|
{
|
||||||
|
_tmpFileStream?.Dispose();
|
||||||
|
_tmpFileStream = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( State != ImporterState.ExtractingModFiles )
|
||||||
|
{
|
||||||
|
ResetStreamDisposer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ImportFiles()
|
private void ImportFiles()
|
||||||
|
|
@ -45,6 +84,13 @@ public partial class TexToolsImporter
|
||||||
_currentModPackIdx = 0;
|
_currentModPackIdx = 0;
|
||||||
foreach( var file in _modPackFiles )
|
foreach( var file in _modPackFiles )
|
||||||
{
|
{
|
||||||
|
_currentModDirectory = null;
|
||||||
|
if( _token.IsCancellationRequested )
|
||||||
|
{
|
||||||
|
ExtractedMods.Add( ( file, null, new TaskCanceledException( "Task canceled by user." ) ) );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var directory = VerifyVersionAndImport( file );
|
var directory = VerifyVersionAndImport( file );
|
||||||
|
|
@ -52,7 +98,7 @@ public partial class TexToolsImporter
|
||||||
}
|
}
|
||||||
catch( Exception e )
|
catch( Exception e )
|
||||||
{
|
{
|
||||||
ExtractedMods.Add( ( file, null, e ) );
|
ExtractedMods.Add( ( file, _currentModDirectory, e ) );
|
||||||
_currentNumOptions = 0;
|
_currentNumOptions = 0;
|
||||||
_currentOptionIdx = 0;
|
_currentOptionIdx = 0;
|
||||||
_currentFileIdx = 0;
|
_currentFileIdx = 0;
|
||||||
|
|
@ -88,7 +134,7 @@ public partial class TexToolsImporter
|
||||||
PluginLog.Warning( $"File {modPackFile.FullName} seems to be a V2 TTMP, but has the wrong extension." );
|
PluginLog.Warning( $"File {modPackFile.FullName} seems to be a V2 TTMP, but has the wrong extension." );
|
||||||
}
|
}
|
||||||
|
|
||||||
return ImportV2ModPack( _: modPackFile, extractedModPack, modRaw );
|
return ImportV2ModPack( modPackFile, extractedModPack, modRaw );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( modPackFile.Extension != ".ttmp" )
|
if( modPackFile.Extension != ".ttmp" )
|
||||||
|
|
@ -129,11 +175,19 @@ public partial class TexToolsImporter
|
||||||
|
|
||||||
private void WriteZipEntryToTempFile( Stream s )
|
private void WriteZipEntryToTempFile( Stream s )
|
||||||
{
|
{
|
||||||
using var fs = new FileStream( _tmpFile, FileMode.Create );
|
_tmpFileStream?.Dispose(); // should not happen
|
||||||
s.CopyTo( fs );
|
_tmpFileStream = new FileStream( _tmpFile, FileMode.Create );
|
||||||
|
if( _token.IsCancellationRequested )
|
||||||
|
{
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PenumbraSqPackStream GetSqPackStreamStream( ZipFile file, string entryName )
|
s.CopyTo( _tmpFileStream );
|
||||||
|
_tmpFileStream.Dispose();
|
||||||
|
_tmpFileStream = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private StreamDisposer GetSqPackStreamStream( ZipFile file, string entryName )
|
||||||
{
|
{
|
||||||
State = ImporterState.WritingPackToDisk;
|
State = ImporterState.WritingPackToDisk;
|
||||||
|
|
||||||
|
|
@ -148,7 +202,14 @@ public partial class TexToolsImporter
|
||||||
|
|
||||||
WriteZipEntryToTempFile( s );
|
WriteZipEntryToTempFile( s );
|
||||||
|
|
||||||
|
_streamDisposer?.Dispose(); // Should not happen.
|
||||||
var fs = new FileStream( _tmpFile, FileMode.Open );
|
var fs = new FileStream( _tmpFile, FileMode.Open );
|
||||||
return new StreamDisposer( fs );
|
return new StreamDisposer( fs );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ResetStreamDisposer()
|
||||||
|
{
|
||||||
|
_streamDisposer?.Dispose();
|
||||||
|
_streamDisposer = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -91,4 +91,7 @@ public partial class TexToolsImporter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool DrawCancelButton( Vector2 size )
|
||||||
|
=> ImGuiUtil.DrawDisabledButton( "Cancel", size, string.Empty, _token.IsCancellationRequested );
|
||||||
}
|
}
|
||||||
|
|
@ -13,6 +13,8 @@ namespace Penumbra.Import;
|
||||||
|
|
||||||
public partial class TexToolsImporter
|
public partial class TexToolsImporter
|
||||||
{
|
{
|
||||||
|
private DirectoryInfo? _currentModDirectory;
|
||||||
|
|
||||||
// Version 1 mod packs are a simple collection of files without much information.
|
// Version 1 mod packs are a simple collection of files without much information.
|
||||||
private DirectoryInfo ImportV1ModPack( FileInfo modPackFile, ZipFile extractedModPack, string modRaw )
|
private DirectoryInfo ImportV1ModPack( FileInfo modPackFile, ZipFile extractedModPack, string modRaw )
|
||||||
{
|
{
|
||||||
|
|
@ -31,16 +33,16 @@ public partial class TexToolsImporter
|
||||||
|
|
||||||
var modList = modListRaw.Select( m => JsonConvert.DeserializeObject< SimpleMod >( m, JsonSettings )! ).ToList();
|
var modList = modListRaw.Select( m => JsonConvert.DeserializeObject< SimpleMod >( m, JsonSettings )! ).ToList();
|
||||||
|
|
||||||
// Open the mod data file from the mod pack as a SqPackStream
|
_currentModDirectory = Mod.CreateModFolder( _baseDirectory, Path.GetFileNameWithoutExtension( modPackFile.Name ) );
|
||||||
using var modData = GetSqPackStreamStream( extractedModPack, "TTMPD.mpd" );
|
|
||||||
|
|
||||||
var ret = Mod.CreateModFolder( _baseDirectory, Path.GetFileNameWithoutExtension( modPackFile.Name ) );
|
|
||||||
// Create a new ModMeta from the TTMP mod list info
|
// Create a new ModMeta from the TTMP mod list info
|
||||||
Mod.CreateMeta( ret, _currentModName, DefaultTexToolsData.Author, DefaultTexToolsData.Description, null, null );
|
Mod.CreateMeta( _currentModDirectory, _currentModName, DefaultTexToolsData.Author, DefaultTexToolsData.Description, null, null );
|
||||||
|
|
||||||
ExtractSimpleModList( ret, modList, modData );
|
// Open the mod data file from the mod pack as a SqPackStream
|
||||||
Mod.CreateDefaultFiles( ret );
|
_streamDisposer = GetSqPackStreamStream( extractedModPack, "TTMPD.mpd" );
|
||||||
return ret;
|
ExtractSimpleModList( _currentModDirectory, modList );
|
||||||
|
Mod.CreateDefaultFiles( _currentModDirectory );
|
||||||
|
ResetStreamDisposer();
|
||||||
|
return _currentModDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version 2 mod packs can either be simple or extended, import accordingly.
|
// Version 2 mod packs can either be simple or extended, import accordingly.
|
||||||
|
|
@ -87,17 +89,17 @@ public partial class TexToolsImporter
|
||||||
_currentOptionName = DefaultTexToolsData.DefaultOption;
|
_currentOptionName = DefaultTexToolsData.DefaultOption;
|
||||||
PluginLog.Log( " -> Importing Simple V2 ModPack" );
|
PluginLog.Log( " -> Importing Simple V2 ModPack" );
|
||||||
|
|
||||||
// Open the mod data file from the mod pack as a SqPackStream
|
_currentModDirectory = Mod.CreateModFolder( _baseDirectory, _currentModName );
|
||||||
using var modData = GetSqPackStreamStream( extractedModPack, "TTMPD.mpd" );
|
Mod.CreateMeta( _currentModDirectory, _currentModName, modList.Author, string.IsNullOrEmpty( modList.Description )
|
||||||
|
|
||||||
var ret = Mod.CreateModFolder( _baseDirectory, _currentModName );
|
|
||||||
Mod.CreateMeta( ret, _currentModName, modList.Author, string.IsNullOrEmpty( modList.Description )
|
|
||||||
? "Mod imported from TexTools mod pack"
|
? "Mod imported from TexTools mod pack"
|
||||||
: modList.Description, null, null );
|
: modList.Description, null, null );
|
||||||
|
|
||||||
ExtractSimpleModList( ret, modList.SimpleModsList, modData );
|
// Open the mod data file from the mod pack as a SqPackStream
|
||||||
Mod.CreateDefaultFiles( ret );
|
_streamDisposer = GetSqPackStreamStream( extractedModPack, "TTMPD.mpd" );
|
||||||
return ret;
|
ExtractSimpleModList( _currentModDirectory, modList.SimpleModsList );
|
||||||
|
Mod.CreateDefaultFiles( _currentModDirectory );
|
||||||
|
ResetStreamDisposer();
|
||||||
|
return _currentModDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtain the number of relevant options to extract.
|
// Obtain the number of relevant options to extract.
|
||||||
|
|
@ -118,23 +120,24 @@ public partial class TexToolsImporter
|
||||||
var modList = JsonConvert.DeserializeObject< ExtendedModPack >( modRaw, JsonSettings )!;
|
var modList = JsonConvert.DeserializeObject< ExtendedModPack >( modRaw, JsonSettings )!;
|
||||||
_currentNumOptions = GetOptionCount( modList );
|
_currentNumOptions = GetOptionCount( modList );
|
||||||
_currentModName = modList.Name;
|
_currentModName = modList.Name;
|
||||||
// Open the mod data file from the mod pack as a SqPackStream
|
|
||||||
using var modData = GetSqPackStreamStream( extractedModPack, "TTMPD.mpd" );
|
|
||||||
|
|
||||||
var ret = Mod.CreateModFolder( _baseDirectory, _currentModName );
|
_currentModDirectory = Mod.CreateModFolder( _baseDirectory, _currentModName );
|
||||||
Mod.CreateMeta( ret, _currentModName, modList.Author, modList.Description, modList.Version, null );
|
Mod.CreateMeta( _currentModDirectory, _currentModName, modList.Author, modList.Description, modList.Version, null );
|
||||||
|
|
||||||
if( _currentNumOptions == 0 )
|
if( _currentNumOptions == 0 )
|
||||||
{
|
{
|
||||||
return ret;
|
return _currentModDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Open the mod data file from the mod pack as a SqPackStream
|
||||||
|
_streamDisposer = GetSqPackStreamStream( extractedModPack, "TTMPD.mpd" );
|
||||||
|
|
||||||
// It can contain a simple list, still.
|
// It can contain a simple list, still.
|
||||||
if( modList.SimpleModsList.Length > 0 )
|
if( modList.SimpleModsList.Length > 0 )
|
||||||
{
|
{
|
||||||
_currentGroupName = string.Empty;
|
_currentGroupName = string.Empty;
|
||||||
_currentOptionName = "Default";
|
_currentOptionName = "Default";
|
||||||
ExtractSimpleModList( ret, modList.SimpleModsList, modData );
|
ExtractSimpleModList( _currentModDirectory, modList.SimpleModsList );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate through all pages
|
// Iterate through all pages
|
||||||
|
|
@ -147,18 +150,19 @@ public partial class TexToolsImporter
|
||||||
_currentGroupName = group.GroupName;
|
_currentGroupName = group.GroupName;
|
||||||
options.Clear();
|
options.Clear();
|
||||||
var description = new StringBuilder();
|
var description = new StringBuilder();
|
||||||
var groupFolder = Mod.NewSubFolderName( ret, group.GroupName )
|
var groupFolder = Mod.NewSubFolderName( _currentModDirectory, group.GroupName )
|
||||||
?? new DirectoryInfo( Path.Combine( ret.FullName, $"Group {groupPriority + 1}" ) );
|
?? new DirectoryInfo( Path.Combine( _currentModDirectory.FullName, $"Group {groupPriority + 1}" ) );
|
||||||
|
|
||||||
var optionIdx = 1;
|
var optionIdx = 1;
|
||||||
|
|
||||||
foreach( var option in group.OptionList.Where( option => option.Name.Length > 0 && option.ModsJsons.Length > 0 ) )
|
foreach( var option in group.OptionList.Where( option => option.Name.Length > 0 && option.ModsJsons.Length > 0 ) )
|
||||||
{
|
{
|
||||||
|
_token.ThrowIfCancellationRequested();
|
||||||
_currentOptionName = option.Name;
|
_currentOptionName = option.Name;
|
||||||
var optionFolder = Mod.NewSubFolderName( groupFolder, option.Name )
|
var optionFolder = Mod.NewSubFolderName( groupFolder, option.Name )
|
||||||
?? new DirectoryInfo( Path.Combine( groupFolder.FullName, $"Option {optionIdx}" ) );
|
?? new DirectoryInfo( Path.Combine( groupFolder.FullName, $"Option {optionIdx}" ) );
|
||||||
ExtractSimpleModList( optionFolder, option.ModsJsons, modData );
|
ExtractSimpleModList( optionFolder, option.ModsJsons );
|
||||||
options.Add( Mod.CreateSubMod( ret, optionFolder, option ) );
|
options.Add( Mod.CreateSubMod( _currentModDirectory, optionFolder, option ) );
|
||||||
description.Append( option.Description );
|
description.Append( option.Description );
|
||||||
if( !string.IsNullOrEmpty( option.Description ) )
|
if( !string.IsNullOrEmpty( option.Description ) )
|
||||||
{
|
{
|
||||||
|
|
@ -169,15 +173,16 @@ public partial class TexToolsImporter
|
||||||
++_currentOptionIdx;
|
++_currentOptionIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mod.CreateOptionGroup( ret, group, groupPriority++, description.ToString(), options );
|
Mod.CreateOptionGroup( _currentModDirectory, group, groupPriority++, description.ToString(), options );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Mod.CreateDefaultFiles( ret );
|
ResetStreamDisposer();
|
||||||
return ret;
|
Mod.CreateDefaultFiles( _currentModDirectory );
|
||||||
|
return _currentModDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExtractSimpleModList( DirectoryInfo outDirectory, ICollection< SimpleMod > mods, PenumbraSqPackStream dataStream )
|
private void ExtractSimpleModList( DirectoryInfo outDirectory, ICollection< SimpleMod > mods )
|
||||||
{
|
{
|
||||||
State = ImporterState.ExtractingModFiles;
|
State = ImporterState.ExtractingModFiles;
|
||||||
|
|
||||||
|
|
@ -187,18 +192,22 @@ public partial class TexToolsImporter
|
||||||
// Extract each SimpleMod into the new mod folder
|
// Extract each SimpleMod into the new mod folder
|
||||||
foreach( var simpleMod in mods )
|
foreach( var simpleMod in mods )
|
||||||
{
|
{
|
||||||
ExtractMod( outDirectory, simpleMod, dataStream );
|
ExtractMod( outDirectory, simpleMod );
|
||||||
++_currentFileIdx;
|
++_currentFileIdx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExtractMod( DirectoryInfo outDirectory, SimpleMod mod, PenumbraSqPackStream dataStream )
|
private void ExtractMod( DirectoryInfo outDirectory, SimpleMod mod )
|
||||||
{
|
{
|
||||||
|
if( _streamDisposer is not PenumbraSqPackStream stream )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
PluginLog.Log( " -> Extracting {0} at {1}", mod.FullPath, mod.ModOffset.ToString( "X" ) );
|
PluginLog.Log( " -> Extracting {0} at {1}", mod.FullPath, mod.ModOffset.ToString( "X" ) );
|
||||||
|
|
||||||
try
|
_token.ThrowIfCancellationRequested();
|
||||||
{
|
var data = stream.ReadFile< PenumbraSqPackStream.PenumbraFileResource >( mod.ModOffset );
|
||||||
var data = dataStream.ReadFile< PenumbraSqPackStream.PenumbraFileResource >( mod.ModOffset );
|
|
||||||
|
|
||||||
_currentFileName = mod.FullPath;
|
_currentFileName = mod.FullPath;
|
||||||
var extractedFile = new FileInfo( Path.Combine( outDirectory.FullName, mod.FullPath ) );
|
var extractedFile = new FileInfo( Path.Combine( outDirectory.FullName, mod.FullPath ) );
|
||||||
|
|
@ -212,11 +221,6 @@ public partial class TexToolsImporter
|
||||||
|
|
||||||
File.WriteAllBytes( extractedFile.FullName, data.Data );
|
File.WriteAllBytes( extractedFile.FullName, data.Data );
|
||||||
}
|
}
|
||||||
catch( Exception ex )
|
|
||||||
{
|
|
||||||
PluginLog.LogError( ex, "Could not extract mod." );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ProcessMdl( byte[] mdl )
|
private static void ProcessMdl( byte[] mdl )
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ public unsafe partial class ResourceLoader
|
||||||
return ReadSqPackHook.Original( resourceManager, fileDescriptor, priority, isSync );
|
return ReadSqPackHook.Original( resourceManager, fileDescriptor, priority, isSync );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !Utf8GamePath.FromSpan( fileDescriptor->ResourceHandle->FileNameSpan(), out var gamePath, false ) )
|
if( !Utf8GamePath.FromSpan( fileDescriptor->ResourceHandle->FileNameSpan(), out var gamePath, false ) || gamePath.Length == 0 )
|
||||||
{
|
{
|
||||||
return ReadSqPackHook.Original( resourceManager, fileDescriptor, priority, isSync );
|
return ReadSqPackHook.Original( resourceManager, fileDescriptor, priority, isSync );
|
||||||
}
|
}
|
||||||
|
|
@ -164,17 +164,13 @@ public unsafe partial class ResourceLoader
|
||||||
fileDescriptor->ResourceHandle->FileNameData = split[ 2 ].Path;
|
fileDescriptor->ResourceHandle->FileNameData = split[ 2 ].Path;
|
||||||
fileDescriptor->ResourceHandle->FileNameLength = split[ 2 ].Length;
|
fileDescriptor->ResourceHandle->FileNameLength = split[ 2 ].Length;
|
||||||
|
|
||||||
// Force isSync = true for these calls. I don't really understand why,
|
|
||||||
// or where the difference even comes from.
|
|
||||||
// Was called with True on my client and with false on other peoples clients,
|
|
||||||
// which caused problems.
|
|
||||||
var funcFound = ResourceLoadCustomization.GetInvocationList()
|
var funcFound = ResourceLoadCustomization.GetInvocationList()
|
||||||
.Any( f => ( ( ResourceLoadCustomizationDelegate )f )
|
.Any( f => ( ( ResourceLoadCustomizationDelegate )f )
|
||||||
.Invoke( split[ 1 ], split[ 2 ], resourceManager, fileDescriptor, priority, true, out ret ) );
|
.Invoke( split[ 1 ], split[ 2 ], resourceManager, fileDescriptor, priority, isSync, out ret ) );
|
||||||
|
|
||||||
if( !funcFound )
|
if( !funcFound )
|
||||||
{
|
{
|
||||||
ret = DefaultLoadResource( split[ 2 ], resourceManager, fileDescriptor, priority, true );
|
ret = DefaultLoadResource( split[ 2 ], resourceManager, fileDescriptor, priority, isSync );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return original resource handle path so that they can be loaded separately.
|
// Return original resource handle path so that they can be loaded separately.
|
||||||
|
|
|
||||||
|
|
@ -90,8 +90,11 @@ public unsafe partial class PathResolver
|
||||||
PluginLog.Verbose( "Using MtrlLoadHandler with no collection for path {$Path:l}.", path );
|
PluginLog.Verbose( "Using MtrlLoadHandler with no collection for path {$Path:l}.", path );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Force isSync = true for this call. I don't really understand why,
|
||||||
ret = Penumbra.ResourceLoader.DefaultLoadResource( path, resourceManager, fileDescriptor, priority, isSync );
|
// or where the difference even comes from.
|
||||||
|
// Was called with True on my client and with false on other peoples clients,
|
||||||
|
// which caused problems.
|
||||||
|
ret = Penumbra.ResourceLoader.DefaultLoadResource( path, resourceManager, fileDescriptor, priority, true );
|
||||||
PathCollections.TryRemove( path, out _ );
|
PathCollections.TryRemove( path, out _ );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -365,7 +365,7 @@ public class Penumbra : IDalamudPlugin
|
||||||
private static IReadOnlyList< FileInfo > PenumbraBackupFiles()
|
private static IReadOnlyList< FileInfo > PenumbraBackupFiles()
|
||||||
{
|
{
|
||||||
var collectionDir = ModCollection.CollectionDirectory;
|
var collectionDir = ModCollection.CollectionDirectory;
|
||||||
var list = Directory.Exists(collectionDir)
|
var list = Directory.Exists( collectionDir )
|
||||||
? new DirectoryInfo( collectionDir ).EnumerateFiles( "*.json" ).ToList()
|
? new DirectoryInfo( collectionDir ).EnumerateFiles( "*.json" ).ToList()
|
||||||
: new List< FileInfo >();
|
: new List< FileInfo >();
|
||||||
list.Add( Dalamud.PluginInterface.ConfigFile );
|
list.Add( Dalamud.PluginInterface.ConfigFile );
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Interface.ImGuiFileDialog;
|
using Dalamud.Interface.ImGuiFileDialog;
|
||||||
using Dalamud.Logging;
|
using Dalamud.Logging;
|
||||||
|
|
@ -55,6 +56,8 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
|
||||||
Penumbra.CollectionManager.Current.ModSettingChanged -= OnSettingChange;
|
Penumbra.CollectionManager.Current.ModSettingChanged -= OnSettingChange;
|
||||||
Penumbra.CollectionManager.Current.InheritanceChanged -= OnInheritanceChange;
|
Penumbra.CollectionManager.Current.InheritanceChanged -= OnInheritanceChange;
|
||||||
Penumbra.CollectionManager.CollectionChanged -= OnCollectionChange;
|
Penumbra.CollectionManager.CollectionChanged -= OnCollectionChange;
|
||||||
|
_import?.Dispose();
|
||||||
|
_import = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public new ModFileSystem.Leaf? SelectedLeaf
|
public new ModFileSystem.Leaf? SelectedLeaf
|
||||||
|
|
@ -160,7 +163,8 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
|
||||||
{
|
{
|
||||||
if( s )
|
if( s )
|
||||||
{
|
{
|
||||||
_import = new TexToolsImporter( Penumbra.ModManager.BasePath, f.Count, f.Select( file => new FileInfo( file ) ) );
|
_import = new TexToolsImporter( Penumbra.ModManager.BasePath, f.Count, f.Select( file => new FileInfo( file ) ),
|
||||||
|
AddNewMod );
|
||||||
ImGui.OpenPopup( "Import Status" );
|
ImGui.OpenPopup( "Import Status" );
|
||||||
}
|
}
|
||||||
}, 0, modPath );
|
}, 0, modPath );
|
||||||
|
|
@ -177,27 +181,25 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
|
||||||
ImGui.SetNextWindowSize( display / 4 );
|
ImGui.SetNextWindowSize( display / 4 );
|
||||||
ImGui.SetNextWindowPos( 3 * display / 8 );
|
ImGui.SetNextWindowPos( 3 * display / 8 );
|
||||||
using var popup = ImRaii.Popup( "Import Status", ImGuiWindowFlags.Modal );
|
using var popup = ImRaii.Popup( "Import Status", ImGuiWindowFlags.Modal );
|
||||||
if( _import != null && popup.Success )
|
if( _import == null || !popup.Success )
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_import.DrawProgressInfo( new Vector2( -1, ImGui.GetFrameHeight() ) );
|
_import.DrawProgressInfo( new Vector2( -1, ImGui.GetFrameHeight() ) );
|
||||||
if( _import.State == ImporterState.Done )
|
|
||||||
{
|
|
||||||
ImGui.SetCursorPosY( ImGui.GetWindowHeight() - ImGui.GetFrameHeight() * 2 );
|
ImGui.SetCursorPosY( ImGui.GetWindowHeight() - ImGui.GetFrameHeight() * 2 );
|
||||||
if( ImGui.Button( "Close", -Vector2.UnitX ) )
|
if( _import.State == ImporterState.Done && ImGui.Button( "Close", -Vector2.UnitX )
|
||||||
|
|| _import.State != ImporterState.Done && _import.DrawCancelButton( -Vector2.UnitX ) )
|
||||||
{
|
{
|
||||||
AddNewMods( _import.ExtractedMods );
|
_import?.Dispose();
|
||||||
_import = null;
|
_import = null;
|
||||||
ImGui.CloseCurrentPopup();
|
ImGui.CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up invalid directories if necessary.
|
// Clean up invalid directory if necessary.
|
||||||
// Add all successfully extracted mods.
|
// Add successfully extracted mods.
|
||||||
private static void AddNewMods( IEnumerable< (FileInfo File, DirectoryInfo? Mod, Exception? Error) > list )
|
private static void AddNewMod( FileInfo file, DirectoryInfo? dir, Exception? error )
|
||||||
{
|
|
||||||
foreach( var (file, dir, error) in list )
|
|
||||||
{
|
{
|
||||||
if( error != null )
|
if( error != null )
|
||||||
{
|
{
|
||||||
|
|
@ -205,7 +207,7 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Directory.Delete( dir.FullName );
|
Directory.Delete( dir.FullName, true );
|
||||||
}
|
}
|
||||||
catch( Exception e )
|
catch( Exception e )
|
||||||
{
|
{
|
||||||
|
|
@ -213,16 +215,16 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( error is not OperationCanceledException )
|
||||||
|
{
|
||||||
PluginLog.Error( $"Error extracting {file.FullName}, mod skipped:\n{error}" );
|
PluginLog.Error( $"Error extracting {file.FullName}, mod skipped:\n{error}" );
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if( dir != null )
|
else if( dir != null )
|
||||||
{
|
{
|
||||||
Penumbra.ModManager.AddMod( dir );
|
Penumbra.ModManager.AddMod( dir );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void DeleteModButton( Vector2 size )
|
private void DeleteModButton( Vector2 size )
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue