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 int WaitFrames { get; set; } = 30;
public string ModDirectory { get; set; } = string.Empty; public string ModDirectory { get; set; } = string.Empty;
public string TempDirectory { get; set; } = string.Empty;
public string CurrentCollection { get; set; } = "Default"; public string CurrentCollection { get; set; } = "Default";
public string DefaultCollection { get; set; } = "Default"; public string DefaultCollection { get; set; } = "Default";

View file

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

View file

@ -36,9 +36,15 @@ namespace Penumbra.Mods
public void RecreateCaches() public void RecreateCaches()
{ {
if( !_manager.TempWritable )
{
PluginLog.Error( "No temporary directory available." );
return;
}
foreach( var collection in Collections.Values.Where( c => c.Cache != null ) ) 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 ) private void AddCache( ModCollection collection )
{ {
if( !_manager.TempWritable )
{
PluginLog.Error( "No tmp directory available." );
return;
}
if( collection.Cache == null && collection.Name != string.Empty ) 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 Dictionary< GamePath, GamePath > SwappedFiles = new();
public readonly MetaManager MetaManipulations; public readonly MetaManager MetaManipulations;
public ModCollectionCache( string collectionName, DirectoryInfo modDir ) public ModCollectionCache( string collectionName, DirectoryInfo tempDir )
=> MetaManipulations = new MetaManager( collectionName, ResolvedFiles, modDir ); => MetaManipulations = new MetaManager( collectionName, ResolvedFiles, tempDir );
private void AddFiles( Dictionary< GamePath, Mod.Mod > registeredFiles, Mod.Mod mod ) private void AddFiles( Dictionary< GamePath, Mod.Mod > registeredFiles, Mod.Mod mod )
{ {

View file

@ -16,6 +16,7 @@ namespace Penumbra.Mods
{ {
private readonly Plugin _plugin; private readonly Plugin _plugin;
public DirectoryInfo BasePath { get; private set; } = null!; public DirectoryInfo BasePath { get; private set; } = null!;
public DirectoryInfo TempPath { get; private set; } = null!;
public Dictionary< string, ModData > Mods { get; } = new(); public Dictionary< string, ModData > Mods { get; } = new();
public ModFolder StructuredMods { get; } = ModFileSystem.Root; public ModFolder StructuredMods { get; } = ModFileSystem.Root;
@ -23,39 +24,157 @@ namespace Penumbra.Mods
public CollectionManager Collections { get; } public CollectionManager Collections { get; }
public bool Valid { get; private set; } public bool Valid { get; private set; }
public bool TempWritable { get; private set; }
public Configuration Config public Configuration Config
=> _plugin.Configuration; => _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 ); try
Valid = Path.IsPathRooted( basePath ); {
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 else
{ {
BasePath = new DirectoryInfo( "." ); var newDir = new DirectoryInfo( newPath );
Valid = false; 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 ) public ModManager( Plugin plugin )
{ {
_plugin = plugin; _plugin = plugin;
SetBaseDirectory( plugin.Configuration.ModDirectory ); SetBaseDirectory( Config.ModDirectory, true );
MetaManager.ClearBaseDirectory( BasePath! ); SetTempDirectory( Config.TempDirectory, true );
Collections = new CollectionManager( plugin, this ); Collections = new CollectionManager( plugin, this );
} }
public void DiscoverMods( string basePath )
{
SetBaseDirectory( basePath );
DiscoverMods();
}
private bool SetSortOrderPath( ModData mod, string path ) private bool SetSortOrderPath( ModData mod, string path )
{ {
mod.Move( path ); mod.Move( path );
@ -101,21 +220,11 @@ namespace Penumbra.Mods
public void DiscoverMods() public void DiscoverMods()
{ {
Mods.Clear(); Mods.Clear();
if( Valid && !BasePath.Exists ) BasePath.Refresh();
{
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;
}
}
if( Valid ) StructuredMods.SubFolders.Clear();
StructuredMods.Mods.Clear();
if( Valid && BasePath.Exists )
{ {
foreach( var modFolder in BasePath.EnumerateDirectories() ) foreach( var modFolder in BasePath.EnumerateDirectories() )
{ {

View file

@ -206,7 +206,7 @@ namespace Penumbra.Mods
manager.Collections.SaveCollection( collection ); manager.Collections.SaveCollection( collection );
if( collection.Cache != null && settings.Enabled ) 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 ); collection == manager.Collections.ActiveCollection );
} }
} }

View file

@ -85,9 +85,9 @@ namespace Penumbra
CreateWebServer(); CreateWebServer();
} }
if( Configuration.EnableActorWatch && Configuration.IsEnabled ) if( !Configuration.EnableActorWatch || !Configuration.IsEnabled )
{ {
PlayerWatcher.Enable(); PlayerWatcher.Disable();
} }
PlayerWatcher.ActorChanged += a => 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 IsRooted", Path.IsPathRooted( _plugin.Configuration.ModDirectory ).ToString() );
PrintValue( "Mod Manager BasePath Exists", Directory.Exists( manager.BasePath.FullName ).ToString() ); PrintValue( "Mod Manager BasePath Exists", Directory.Exists( manager.BasePath.FullName ).ToString() );
PrintValue( "Mod Manager Valid", manager.Valid.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(); ImGui.EndTable();
} }

View file

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

View file

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

View file

@ -17,8 +17,10 @@ namespace Penumbra.UI
{ {
private const string LabelTab = "Settings"; private const string LabelTab = "Settings";
private const string LabelRootFolder = "Root Folder"; private const string LabelRootFolder = "Root Folder";
private const string LabelTempFolder = "Temporary Folder";
private const string LabelRediscoverButton = "Rediscover Mods"; private const string LabelRediscoverButton = "Rediscover Mods";
private const string LabelOpenFolder = "Open Mods Folder"; private const string LabelOpenFolder = "Open Mods Folder";
private const string LabelOpenTempFolder = "Open Temporary Folder";
private const string LabelEnabled = "Enable Mods"; private const string LabelEnabled = "Enable Mods";
private const string LabelEnabledPlayerWatch = "Enable automatic Character Redraws"; private const string LabelEnabledPlayerWatch = "Enable automatic Character Redraws";
private const string LabelWaitFrames = "Wait Frames"; private const string LabelWaitFrames = "Wait Frames";
@ -47,10 +49,39 @@ namespace Penumbra.UI
if( ImGui.InputText( LabelRootFolder, ref basePath, 255, ImGuiInputTextFlags.EnterReturnsTrue ) if( ImGui.InputText( LabelRootFolder, ref basePath, 255, ImGuiInputTextFlags.EnterReturnsTrue )
&& _config.ModDirectory != basePath ) && _config.ModDirectory != basePath )
{ {
_config.ModDirectory = basePath;
_configChanged = true;
_base.ReloadMods();
_base._menu.InstalledTab.Selector.ClearSelection(); _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 ) ) if( ImGui.Button( LabelRediscoverButton ) )
{ {
_base.ReloadMods();
_base._menu.InstalledTab.Selector.ClearSelection(); _base._menu.InstalledTab.Selector.ClearSelection();
_base._modManager.DiscoverMods();
_base._menu.InstalledTab.Selector.Cache.TriggerListReset();
} }
} }
@ -108,7 +140,7 @@ namespace Penumbra.UI
{ {
_config.SortFoldersFirst = foldersFirst; _config.SortFoldersFirst = foldersFirst;
_base._menu.InstalledTab.Selector.Cache.TriggerListReset(); _base._menu.InstalledTab.Selector.Cache.TriggerListReset();
_configChanged = true; _configChanged = true;
} }
} }
@ -224,6 +256,7 @@ namespace Penumbra.UI
private void DrawAdvancedSettings() private void DrawAdvancedSettings()
{ {
DrawTempFolder();
DrawLogLoadedFilesBox(); DrawLogLoadedFilesBox();
DrawDisableNotificationsBox(); DrawDisableNotificationsBox();
DrawEnableHttpApiBox(); DrawEnableHttpApiBox();

View file

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