Add separate option for temporary folder, fix cache StructuredMods not updating on root folder change.

This commit is contained in:
Ottermandias 2021-08-14 21:14:11 +02:00
parent 2ebbb227f7
commit 556bff4e46
12 changed files with 207 additions and 49 deletions

View file

@ -25,6 +25,7 @@ namespace Penumbra
public int WaitFrames { get; set; } = 30;
public string ModDirectory { get; set; } = string.Empty;
public string TempDirectory { get; set; } = string.Empty;
public string CurrentCollection { get; set; } = "Default";
public string DefaultCollection { get; set; } = "Default";

View file

@ -116,15 +116,12 @@ namespace Penumbra.Meta
private void ClearDirectory()
=> ClearDirectory( _dir );
public static void ClearBaseDirectory( DirectoryInfo modDir )
=> ClearDirectory( new DirectoryInfo( Path.Combine( modDir.FullName, TmpDirectory ) ) );
public MetaManager( string name, Dictionary< GamePath, FileInfo > resolvedFiles, DirectoryInfo modDir )
public MetaManager( string name, Dictionary< GamePath, FileInfo > resolvedFiles, DirectoryInfo tempDir )
{
_resolvedFiles = resolvedFiles;
_default = Service< MetaDefaults >.Get();
_resourceManagement = Service< GameResourceManagement >.Get();
_dir = new DirectoryInfo( Path.Combine( modDir.FullName, TmpDirectory, name.ReplaceBadXivSymbols() ) );
_dir = new DirectoryInfo( Path.Combine( tempDir.FullName, name.ReplaceBadXivSymbols() ) );
ClearDirectory();
}

View file

@ -36,9 +36,15 @@ namespace Penumbra.Mods
public void RecreateCaches()
{
if( !_manager.TempWritable )
{
PluginLog.Error( "No temporary directory available." );
return;
}
foreach( var collection in Collections.Values.Where( c => c.Cache != null ) )
{
collection.CreateCache( _manager.BasePath, _manager.StructuredMods.AllMods(_manager.Config.SortFoldersFirst) );
collection.CreateCache( _manager.TempPath, _manager.StructuredMods.AllMods( _manager.Config.SortFoldersFirst ) );
}
}
@ -137,9 +143,15 @@ namespace Penumbra.Mods
private void AddCache( ModCollection collection )
{
if( !_manager.TempWritable )
{
PluginLog.Error( "No tmp directory available." );
return;
}
if( collection.Cache == null && collection.Name != string.Empty )
{
collection.CreateCache( _manager.BasePath, _manager.StructuredMods.AllMods(_manager.Config.SortFoldersFirst) );
collection.CreateCache( _manager.TempPath, _manager.StructuredMods.AllMods( _manager.Config.SortFoldersFirst ) );
}
}

View file

@ -19,8 +19,8 @@ namespace Penumbra.Mods
public readonly Dictionary< GamePath, GamePath > SwappedFiles = new();
public readonly MetaManager MetaManipulations;
public ModCollectionCache( string collectionName, DirectoryInfo modDir )
=> MetaManipulations = new MetaManager( collectionName, ResolvedFiles, modDir );
public ModCollectionCache( string collectionName, DirectoryInfo tempDir )
=> MetaManipulations = new MetaManager( collectionName, ResolvedFiles, tempDir );
private void AddFiles( Dictionary< GamePath, Mod.Mod > registeredFiles, Mod.Mod mod )
{

View file

@ -16,6 +16,7 @@ namespace Penumbra.Mods
{
private readonly Plugin _plugin;
public DirectoryInfo BasePath { get; private set; } = null!;
public DirectoryInfo TempPath { get; private set; } = null!;
public Dictionary< string, ModData > Mods { get; } = new();
public ModFolder StructuredMods { get; } = ModFileSystem.Root;
@ -23,39 +24,157 @@ namespace Penumbra.Mods
public CollectionManager Collections { get; }
public bool Valid { get; private set; }
public bool TempWritable { get; private set; }
public Configuration Config
=> _plugin.Configuration;
private void SetBaseDirectory( string basePath )
public void DiscoverMods( string newDir )
{
if( basePath.Any() )
SetBaseDirectory( newDir, false );
DiscoverMods();
}
private void ClearOldTmpDir()
{
TempPath.Refresh();
if( TempWritable && TempPath.Exists )
{
BasePath = new DirectoryInfo( basePath );
Valid = Path.IsPathRooted( basePath );
try
{
TempPath.Delete( true );
}
catch( Exception e )
{
PluginLog.Error( $"Could not delete temporary directory {TempPath.FullName}:\n{e}" );
}
}
}
private static bool CheckTmpDir( string newPath, out DirectoryInfo tmpDir )
{
tmpDir = new DirectoryInfo( Path.Combine( newPath, MetaManager.TmpDirectory ) );
try
{
if( tmpDir.Exists )
{
tmpDir.Delete( true );
tmpDir.Refresh();
}
Directory.CreateDirectory( tmpDir.FullName );
tmpDir.Refresh();
return true;
}
catch( Exception e )
{
PluginLog.Error( $"Could not create temporary directory {tmpDir.FullName}:\n{e}" );
return false;
}
}
private void SetBaseDirectory( string newPath, bool firstTime )
{
if( !firstTime && string.Equals( newPath, Config.ModDirectory, StringComparison.InvariantCultureIgnoreCase ) )
{
return;
}
if( !newPath.Any() )
{
Valid = false;
BasePath = new DirectoryInfo( "." );
}
else
{
BasePath = new DirectoryInfo( "." );
Valid = false;
var newDir = new DirectoryInfo( newPath );
if( !newDir.Exists )
{
try
{
Directory.CreateDirectory( newDir.FullName );
newDir.Refresh();
}
catch( Exception e )
{
PluginLog.Error( $"Could not create specified mod directory {newDir.FullName}:\n{e}" );
}
}
BasePath = newDir;
Valid = true;
if( Config.ModDirectory != BasePath.FullName )
{
Config.ModDirectory = BasePath.FullName;
Config.Save();
}
if( !Config.TempDirectory.Any() )
{
if( CheckTmpDir( BasePath.FullName, out var newTmpDir ) )
{
if( !firstTime )
{
ClearOldTmpDir();
}
TempPath = newTmpDir;
TempWritable = true;
}
else
{
TempWritable = false;
}
}
}
}
private void SetTempDirectory( string newPath, bool firstTime )
{
if( !Valid || !firstTime && string.Equals( newPath, Config.TempDirectory, StringComparison.InvariantCultureIgnoreCase ) )
{
return;
}
if( !newPath.Any() && CheckTmpDir( BasePath.FullName, out var newTmpDir )
|| newPath.Any() && CheckTmpDir( newPath, out newTmpDir ) )
{
if( !firstTime )
{
ClearOldTmpDir();
}
TempPath = newTmpDir;
TempWritable = true;
var newName = newPath.Any() ? TempPath.Parent!.FullName : string.Empty;
if( Config.TempDirectory != newName )
{
Config.TempDirectory = newName;
Config.Save();
}
if( !firstTime )
{
Collections.RecreateCaches();
}
}
else
{
TempWritable = false;
}
}
public void SetTempDirectory( string newPath )
=> SetTempDirectory( newPath, false );
public ModManager( Plugin plugin )
{
_plugin = plugin;
SetBaseDirectory( plugin.Configuration.ModDirectory );
MetaManager.ClearBaseDirectory( BasePath! );
SetBaseDirectory( Config.ModDirectory, true );
SetTempDirectory( Config.TempDirectory, true );
Collections = new CollectionManager( plugin, this );
}
public void DiscoverMods( string basePath )
{
SetBaseDirectory( basePath );
DiscoverMods();
}
private bool SetSortOrderPath( ModData mod, string path )
{
mod.Move( path );
@ -101,21 +220,11 @@ namespace Penumbra.Mods
public void DiscoverMods()
{
Mods.Clear();
if( Valid && !BasePath.Exists )
{
PluginLog.Debug( "The mod directory {Directory} does not exist.", BasePath.FullName );
try
{
Directory.CreateDirectory( BasePath.FullName );
}
catch( Exception e )
{
PluginLog.Error( $"The mod directory {BasePath.FullName} does not exist and could not be created:\n{e}" );
Valid = false;
}
}
BasePath.Refresh();
if( Valid )
StructuredMods.SubFolders.Clear();
StructuredMods.Mods.Clear();
if( Valid && BasePath.Exists )
{
foreach( var modFolder in BasePath.EnumerateDirectories() )
{

View file

@ -206,7 +206,7 @@ namespace Penumbra.Mods
manager.Collections.SaveCollection( collection );
if( collection.Cache != null && settings.Enabled )
{
collection.CalculateEffectiveFileList( manager.BasePath, mod.Resources.MetaManipulations.Count > 0,
collection.CalculateEffectiveFileList( manager.TempPath, mod.Resources.MetaManipulations.Count > 0,
collection == manager.Collections.ActiveCollection );
}
}

View file

@ -85,9 +85,9 @@ namespace Penumbra
CreateWebServer();
}
if( Configuration.EnableActorWatch && Configuration.IsEnabled )
if( !Configuration.EnableActorWatch || !Configuration.IsEnabled )
{
PlayerWatcher.Enable();
PlayerWatcher.Disable();
}
PlayerWatcher.ActorChanged += a =>

View file

@ -144,6 +144,11 @@ namespace Penumbra.UI
PrintValue( "Mod Manager BasePath IsRooted", Path.IsPathRooted( _plugin.Configuration.ModDirectory ).ToString() );
PrintValue( "Mod Manager BasePath Exists", Directory.Exists( manager.BasePath.FullName ).ToString() );
PrintValue( "Mod Manager Valid", manager.Valid.ToString() );
PrintValue( "Mod Manager Temp Path", manager.TempPath.FullName );
PrintValue( "Mod Manager Temp Path IsRooted",
( !_plugin.Configuration.TempDirectory.Any() || Path.IsPathRooted( _plugin.Configuration.TempDirectory ) ).ToString() );
PrintValue( "Mod Manager Temp Path Exists", Directory.Exists( manager.TempPath.FullName ).ToString() );
PrintValue( "Mod Manager Temp Path IsWritable", manager.TempWritable.ToString() );
ImGui.EndTable();
}

View file

@ -435,7 +435,7 @@ namespace Penumbra.UI
foreach( var collection in _modManager.Collections.Collections.Values
.Where( c => c.Cache != null && c.Settings[ Mod!.Data.BasePath.Name ].Enabled ) )
{
collection.CalculateEffectiveFileList( _modManager.BasePath, false,
collection.CalculateEffectiveFileList( _modManager.TempPath, false,
collection == _modManager.Collections.ActiveCollection );
}

View file

@ -539,7 +539,7 @@ namespace Penumbra.UI
var collection = _modManager.Collections.CurrentCollection;
if( collection.Cache != null )
{
collection.CalculateEffectiveFileList( _modManager.BasePath, metaManips,
collection.CalculateEffectiveFileList( _modManager.TempPath, metaManips,
collection == _modManager.Collections.ActiveCollection );
}
@ -563,6 +563,7 @@ namespace Penumbra.UI
{
folder.Merge( folder.Parent! );
}
_newFolderName = string.Empty;
}

View file

@ -17,8 +17,10 @@ namespace Penumbra.UI
{
private const string LabelTab = "Settings";
private const string LabelRootFolder = "Root Folder";
private const string LabelTempFolder = "Temporary Folder";
private const string LabelRediscoverButton = "Rediscover Mods";
private const string LabelOpenFolder = "Open Mods Folder";
private const string LabelOpenTempFolder = "Open Temporary Folder";
private const string LabelEnabled = "Enable Mods";
private const string LabelEnabledPlayerWatch = "Enable automatic Character Redraws";
private const string LabelWaitFrames = "Wait Frames";
@ -47,10 +49,39 @@ namespace Penumbra.UI
if( ImGui.InputText( LabelRootFolder, ref basePath, 255, ImGuiInputTextFlags.EnterReturnsTrue )
&& _config.ModDirectory != basePath )
{
_config.ModDirectory = basePath;
_configChanged = true;
_base.ReloadMods();
_base._menu.InstalledTab.Selector.ClearSelection();
_base._modManager.DiscoverMods( basePath );
_base._menu.InstalledTab.Selector.Cache.TriggerListReset();
}
}
private void DrawTempFolder()
{
var tempPath = _config.TempDirectory;
ImGui.SetNextItemWidth( 400 );
if( ImGui.InputText( LabelTempFolder, ref tempPath, 255, ImGuiInputTextFlags.EnterReturnsTrue )
&& _config.TempDirectory != tempPath )
{
_base._modManager.SetTempDirectory( tempPath );
}
if( ImGui.IsItemHovered() )
{
ImGui.SetTooltip( "The folder used to store temporary meta manipulation files.\n"
+ "Leave this blank if you have no reason not to.\n"
+ "A folder 'penumbrametatmp' will be created as a subdirectory to the specified directory.\n"
+ "If none is specified (i.e. this is blank) this folder will be created in the root folder instead." );
}
ImGui.SameLine();
if( ImGui.Button( LabelOpenTempFolder ) )
{
if( !Directory.Exists( _base._modManager.TempPath.FullName ) || !_base._modManager.TempWritable )
{
return;
}
Process.Start( _base._modManager.TempPath.FullName );
}
}
@ -58,8 +89,9 @@ namespace Penumbra.UI
{
if( ImGui.Button( LabelRediscoverButton ) )
{
_base.ReloadMods();
_base._menu.InstalledTab.Selector.ClearSelection();
_base._modManager.DiscoverMods();
_base._menu.InstalledTab.Selector.Cache.TriggerListReset();
}
}
@ -108,7 +140,7 @@ namespace Penumbra.UI
{
_config.SortFoldersFirst = foldersFirst;
_base._menu.InstalledTab.Selector.Cache.TriggerListReset();
_configChanged = true;
_configChanged = true;
}
}
@ -224,6 +256,7 @@ namespace Penumbra.UI
private void DrawAdvancedSettings()
{
DrawTempFolder();
DrawLogLoadedFilesBox();
DrawDisableNotificationsBox();
DrawEnableHttpApiBox();

View file

@ -74,7 +74,7 @@ namespace Penumbra.UI
var current = _modManager.Collections.CurrentCollection;
if( current.Cache != null )
{
current.CalculateEffectiveFileList( _modManager.BasePath, recalculateMeta,
current.CalculateEffectiveFileList( _modManager.TempPath, recalculateMeta,
current == _modManager.Collections.ActiveCollection );
_menu.InstalledTab.Selector.Cache.TriggerFilterReset();
}