From 8064376d3d6bfd308dcf1d0dc17f834bad901b38 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Mon, 13 Dec 2021 21:26:59 +0100 Subject: [PATCH] Further tries to fix. --- Penumbra/Mods/CollectionManager.cs | 594 ++++++++++++++--------------- Penumbra/Mods/ModManager.cs | 5 +- 2 files changed, 300 insertions(+), 299 deletions(-) diff --git a/Penumbra/Mods/CollectionManager.cs b/Penumbra/Mods/CollectionManager.cs index f9cc99e5..22bd00ce 100644 --- a/Penumbra/Mods/CollectionManager.cs +++ b/Penumbra/Mods/CollectionManager.cs @@ -7,414 +7,412 @@ using Penumbra.Mod; using Penumbra.Util; -namespace Penumbra.Mods +namespace Penumbra.Mods; + +// Contains all collections and respective functions, as well as the collection settings. +public class CollectionManager { - // Contains all collections and respective functions, as well as the collection settings. - public class CollectionManager - { - private readonly ModManager _manager; + private readonly ModManager _manager; - public string CollectionChangedTo { get; private set; } = string.Empty; - public Dictionary< string, ModCollection > Collections { get; } = new(); + public string CollectionChangedTo { get; private set; } = string.Empty; + public Dictionary< string, ModCollection > Collections { get; } = new(); + public Dictionary< string, ModCollection > CharacterCollection { get; } = new(); - public ModCollection CurrentCollection { get; private set; } = null!; - public ModCollection DefaultCollection { get; private set; } = null!; - public ModCollection ForcedCollection { get; private set; } = ModCollection.Empty; - public Dictionary< string, ModCollection > CharacterCollection { get; } = new(); + public ModCollection CurrentCollection { get; private set; } = ModCollection.Empty; + public ModCollection DefaultCollection { get; private set; } = ModCollection.Empty; + public ModCollection ForcedCollection { get; private set; } = ModCollection.Empty; + public ModCollection ActiveCollection { get; private set; } - public ModCollection ActiveCollection { get; private set; } + public CollectionManager( ModManager manager ) + { + _manager = manager; - public CollectionManager( ModManager manager ) - { - _manager = manager; + ReadCollections(); + LoadConfigCollections( Penumbra.Config ); + ActiveCollection = DefaultCollection; + } - ReadCollections(); - LoadConfigCollections( Penumbra.Config ); - ActiveCollection = DefaultCollection; + public bool SetActiveCollection( ModCollection newActive, string name ) + { + CollectionChangedTo = name; + if( newActive == ActiveCollection ) + { + return false; } - public bool SetActiveCollection( ModCollection newActive, string name ) + if( ActiveCollection.Cache?.MetaManipulations.Count > 0 || newActive.Cache?.MetaManipulations.Count > 0 ) { - CollectionChangedTo = name; - if( newActive == ActiveCollection ) - { - return false; - } + var resourceManager = Service< ResidentResources >.Get(); + resourceManager.ReloadPlayerResources(); + } - if( ActiveCollection.Cache?.MetaManipulations.Count > 0 || newActive.Cache?.MetaManipulations.Count > 0 ) - { - var resourceManager = Service< ResidentResources >.Get(); - resourceManager.ReloadPlayerResources(); - } + ActiveCollection = newActive; + return true; + } - ActiveCollection = newActive; - return true; - } + public bool ResetActiveCollection() + => SetActiveCollection( DefaultCollection, string.Empty ); - public bool ResetActiveCollection() - => SetActiveCollection( DefaultCollection, string.Empty ); + public void CreateNecessaryCaches() + { + AddCache( DefaultCollection ); + AddCache( ForcedCollection ); + foreach( var (_, collection) in CharacterCollection ) + { + AddCache( collection ); + } + } - public void CreateNecessaryCaches() + public void RecreateCaches() + { + if( !_manager.TempWritable ) { - if( !_manager.TempWritable ) - { - PluginLog.Error( "No temporary directory available." ); - return; - } + PluginLog.Error( "No temporary directory available." ); + return; + } - if( DefaultCollection.Name != ModCollection.Empty.Name && DefaultCollection.Cache == null ) - DefaultCollection.CreateCache( _manager.TempPath, _manager.StructuredMods.AllMods( _manager.Config.SortFoldersFirst )); + foreach( var collection in Collections.Values.Where( c => c.Cache != null ) ) + { + collection.CreateCache( _manager.TempPath, _manager.StructuredMods.AllMods( _manager.Config.SortFoldersFirst ) ); + } - if( ForcedCollection.Name != ModCollection.Empty.Name && ForcedCollection.Cache == null ) - ForcedCollection.CreateCache( _manager.TempPath, _manager.StructuredMods.AllMods( _manager.Config.SortFoldersFirst ) ); + CreateNecessaryCaches(); + } - foreach (var (_, collection) in CharacterCollection.Where( kvp => kvp.Value.Name != ModCollection.Empty.Name && kvp.Value.Cache == null )) - collection.CreateCache( _manager.TempPath, _manager.StructuredMods.AllMods( _manager.Config.SortFoldersFirst ) ); + public void RemoveModFromCaches( DirectoryInfo modDir ) + { + foreach( var collection in Collections.Values ) + { + collection.Cache?.RemoveMod( modDir ); } + } - public void RecreateCaches() + internal void UpdateCollections( ModData mod, bool metaChanges, ResourceChange fileChanges, bool nameChange, bool reloadMeta ) + { + foreach( var collection in Collections.Values ) { - if( !_manager.TempWritable ) + if( metaChanges ) { - PluginLog.Error( "No temporary directory available." ); - return; + collection.UpdateSetting( mod ); } - foreach( var collection in Collections.Values.Where( c => c.Cache != null ) ) + if( fileChanges.HasFlag( ResourceChange.Files ) + && collection.Settings.TryGetValue( mod.BasePath.Name, out var settings ) + && settings.Enabled ) { - collection.CreateCache( _manager.TempPath, _manager.StructuredMods.AllMods( _manager.Config.SortFoldersFirst ) ); + collection.Cache?.CalculateEffectiveFileList(); } - CreateNecessaryCaches(); + if( reloadMeta ) + { + collection.Cache?.UpdateMetaManipulations(); + } } - public void RemoveModFromCaches( DirectoryInfo modDir ) + if( reloadMeta && ActiveCollection.Settings.TryGetValue( mod.BasePath.Name, out var config ) && config.Enabled ) { - foreach( var collection in Collections.Values ) - { - collection.Cache?.RemoveMod( modDir ); - } + Service< ResidentResources >.Get().ReloadPlayerResources(); } + } - internal void UpdateCollections( ModData mod, bool metaChanges, ResourceChange fileChanges, bool nameChange, bool reloadMeta ) + public bool AddCollection( string name, Dictionary< string, ModSettings > settings ) + { + var nameFixed = name.RemoveInvalidPathSymbols().ToLowerInvariant(); + if( nameFixed == string.Empty || Collections.Values.Any( c => c.Name.RemoveInvalidPathSymbols().ToLowerInvariant() == nameFixed ) ) { - foreach( var collection in Collections.Values ) - { - if( metaChanges ) - { - collection.UpdateSetting( mod ); - } + PluginLog.Warning( $"The new collection {name} would lead to the same path as one that already exists." ); + return false; + } - if( fileChanges.HasFlag( ResourceChange.Files ) - && collection.Settings.TryGetValue( mod.BasePath.Name, out var settings ) - && settings.Enabled ) - { - collection.Cache?.CalculateEffectiveFileList(); - } + var newCollection = new ModCollection( name, settings ); + Collections.Add( name, newCollection ); + newCollection.Save(); + SetCurrentCollection( newCollection ); + return true; + } - if( reloadMeta ) - { - collection.Cache?.UpdateMetaManipulations(); - } - } + public bool RemoveCollection( string name ) + { + if( name == ModCollection.DefaultCollection ) + { + PluginLog.Error( "Can not remove the default collection." ); + return false; + } - if( reloadMeta && ActiveCollection.Settings.TryGetValue( mod.BasePath.Name, out var config ) && config.Enabled ) - { - Service< ResidentResources >.Get().ReloadPlayerResources(); - } + if( !Collections.TryGetValue( name, out var collection ) ) + { + return false; } - public bool AddCollection( string name, Dictionary< string, ModSettings > settings ) + if( CurrentCollection == collection ) { - var nameFixed = name.RemoveInvalidPathSymbols().ToLowerInvariant(); - if( nameFixed == string.Empty || Collections.Values.Any( c => c.Name.RemoveInvalidPathSymbols().ToLowerInvariant() == nameFixed ) ) - { - PluginLog.Warning( $"The new collection {name} would lead to the same path as one that already exists." ); - return false; - } + SetCurrentCollection( Collections[ ModCollection.DefaultCollection ] ); + } - var newCollection = new ModCollection( name, settings ); - Collections.Add( name, newCollection ); - newCollection.Save(); - SetCurrentCollection( newCollection ); - return true; + if( ForcedCollection == collection ) + { + SetForcedCollection( ModCollection.Empty ); } - public bool RemoveCollection( string name ) + if( DefaultCollection == collection ) { - if( name == ModCollection.DefaultCollection ) - { - PluginLog.Error( "Can not remove the default collection." ); - return false; - } + SetDefaultCollection( ModCollection.Empty ); + } - if( Collections.TryGetValue( name, out var collection ) ) + foreach( var (characterName, characterCollection) in CharacterCollection.ToArray() ) + { + if( characterCollection == collection ) { - if( CurrentCollection == collection ) - { - SetCurrentCollection( Collections[ ModCollection.DefaultCollection ] ); - } - - if( ForcedCollection == collection ) - { - SetForcedCollection( ModCollection.Empty ); - } - - if( DefaultCollection == collection ) - { - SetDefaultCollection( ModCollection.Empty ); - } + SetCharacterCollection( characterName, ModCollection.Empty ); + } + } - foreach( var kvp in CharacterCollection.ToArray() ) - { - if( kvp.Value == collection ) - { - SetCharacterCollection( kvp.Key, ModCollection.Empty ); - } - } + collection.Delete(); + Collections.Remove( name ); + return true; - collection.Delete(); - Collections.Remove( name ); - return true; - } + } - return false; + private void AddCache( ModCollection collection ) + { + if( !_manager.TempWritable ) + { + PluginLog.Error( "No tmp directory available." ); + return; } - private void AddCache( ModCollection collection ) + if( collection.Cache == null && collection.Name != string.Empty ) { - if( !_manager.TempWritable ) - { - PluginLog.Error( "No tmp directory available." ); - return; - } + collection.CreateCache( _manager.TempPath, _manager.StructuredMods.AllMods( _manager.Config.SortFoldersFirst ) ); + } + } - if( collection.Cache == null && collection.Name != string.Empty ) - { - collection.CreateCache( _manager.TempPath, _manager.StructuredMods.AllMods( _manager.Config.SortFoldersFirst ) ); - } + private void RemoveCache( ModCollection collection ) + { + if( collection.Name != ForcedCollection.Name + && collection.Name != CurrentCollection.Name + && collection.Name != DefaultCollection.Name + && CharacterCollection.All( kvp => kvp.Value.Name != collection.Name ) ) + { + collection.ClearCache(); } + } - private void RemoveCache( ModCollection collection ) + private void SetCollection( ModCollection newCollection, ModCollection oldCollection, Action< ModCollection > setter, + Action< string > configSetter ) + { + if( newCollection.Name == oldCollection.Name ) { - if( collection.Name != ForcedCollection.Name - && collection.Name != CurrentCollection.Name - && collection.Name != DefaultCollection.Name - && CharacterCollection.All( kvp => kvp.Value.Name != collection.Name ) ) - { - collection.ClearCache(); - } + return; } - private void SetCollection( ModCollection newCollection, ModCollection oldCollection, Action< ModCollection > setter, - Action< string > configSetter ) + AddCache( newCollection ); + + setter( newCollection ); + RemoveCache( oldCollection ); + configSetter( newCollection.Name ); + Penumbra.Config.Save(); + } + + public void SetDefaultCollection( ModCollection newCollection ) + => SetCollection( newCollection, DefaultCollection, c => { - if( newCollection.Name == oldCollection.Name ) + if( !CollectionChangedTo.Any() ) { - return; + ActiveCollection = c; + var resourceManager = Service< ResidentResources >.Get(); + resourceManager.ReloadPlayerResources(); } - AddCache( newCollection ); + DefaultCollection = c; + }, s => Penumbra.Config.DefaultCollection = s ); - setter( newCollection ); - RemoveCache( oldCollection ); - configSetter( newCollection.Name ); - Penumbra.Config.Save(); - } + public void SetForcedCollection( ModCollection newCollection ) + => SetCollection( newCollection, ForcedCollection, c => ForcedCollection = c, s => Penumbra.Config.ForcedCollection = s ); + + public void SetCurrentCollection( ModCollection newCollection ) + => SetCollection( newCollection, CurrentCollection, c => CurrentCollection = c, s => Penumbra.Config.CurrentCollection = s ); - public void SetDefaultCollection( ModCollection newCollection ) - => SetCollection( newCollection, DefaultCollection, c => + public void SetCharacterCollection( string characterName, ModCollection newCollection ) + => SetCollection( newCollection, + CharacterCollection.TryGetValue( characterName, out var oldCollection ) ? oldCollection : ModCollection.Empty, + c => { - if( !CollectionChangedTo.Any() ) + if( CollectionChangedTo == characterName && CharacterCollection.TryGetValue( characterName, out var collection ) ) { ActiveCollection = c; var resourceManager = Service< ResidentResources >.Get(); resourceManager.ReloadPlayerResources(); } - DefaultCollection = c; - }, s => Penumbra.Config.DefaultCollection = s ); + CharacterCollection[ characterName ] = c; + }, s => Penumbra.Config.CharacterCollections[ characterName ] = s ); - public void SetForcedCollection( ModCollection newCollection ) - => SetCollection( newCollection, ForcedCollection, c => ForcedCollection = c, s => Penumbra.Config.ForcedCollection = s ); - - public void SetCurrentCollection( ModCollection newCollection ) - => SetCollection( newCollection, CurrentCollection, c => CurrentCollection = c, s => Penumbra.Config.CurrentCollection = s ); + public bool CreateCharacterCollection( string characterName ) + { + if( !CharacterCollection.ContainsKey( characterName ) ) + { + CharacterCollection[ characterName ] = ModCollection.Empty; + Penumbra.Config.CharacterCollections[ characterName ] = string.Empty; + Penumbra.Config.Save(); + Penumbra.PlayerWatcher.AddPlayerToWatch( characterName ); + return true; + } - public void SetCharacterCollection( string characterName, ModCollection newCollection ) - => SetCollection( newCollection, - CharacterCollection.TryGetValue( characterName, out var oldCollection ) ? oldCollection : ModCollection.Empty, - c => - { - if( CollectionChangedTo == characterName && CharacterCollection.TryGetValue( characterName, out var collection ) ) - { - ActiveCollection = c; - var resourceManager = Service< ResidentResources >.Get(); - resourceManager.ReloadPlayerResources(); - } + return false; + } - CharacterCollection[ characterName ] = c; - }, s => Penumbra.Config.CharacterCollections[ characterName ] = s ); + public void RemoveCharacterCollection( string characterName ) + { + if( CharacterCollection.TryGetValue( characterName, out var collection ) ) + { + RemoveCache( collection ); + CharacterCollection.Remove( characterName ); + Penumbra.PlayerWatcher.RemovePlayerFromWatch( characterName ); + } - public bool CreateCharacterCollection( string characterName ) + if( Penumbra.Config.CharacterCollections.Remove( characterName ) ) { - if( !CharacterCollection.ContainsKey( characterName ) ) - { - CharacterCollection[ characterName ] = ModCollection.Empty; - Penumbra.Config.CharacterCollections[ characterName ] = string.Empty; - Penumbra.Config.Save(); - Penumbra.PlayerWatcher.AddPlayerToWatch( characterName ); - return true; - } + Penumbra.Config.Save(); + } + } + private bool LoadCurrentCollection( Configuration config ) + { + if( Collections.TryGetValue( config.CurrentCollection, out var currentCollection ) ) + { + CurrentCollection = currentCollection; + AddCache( CurrentCollection ); return false; } - public void RemoveCharacterCollection( string characterName ) + PluginLog.Error( $"Last choice of CurrentCollection {config.CurrentCollection} is not available, reset to Default." ); + CurrentCollection = Collections[ ModCollection.DefaultCollection ]; + if( CurrentCollection.Cache == null ) { - if( CharacterCollection.TryGetValue( characterName, out var collection ) ) - { - RemoveCache( collection ); - CharacterCollection.Remove( characterName ); - Penumbra.PlayerWatcher.RemovePlayerFromWatch( characterName ); - } - - if( Penumbra.Config.CharacterCollections.Remove( characterName ) ) - { - Penumbra.Config.Save(); - } + CurrentCollection.CreateCache( _manager.TempPath, _manager.StructuredMods.AllMods( _manager.Config.SortFoldersFirst ) ); } - private bool LoadCurrentCollection( Configuration config ) - { - if( Collections.TryGetValue( config.CurrentCollection, out var currentCollection ) ) - { - CurrentCollection = currentCollection; - AddCache( CurrentCollection ); - return false; - } + config.CurrentCollection = ModCollection.DefaultCollection; + return true; + } - PluginLog.Error( $"Last choice of CurrentCollection {config.CurrentCollection} is not available, reset to Default." ); - CurrentCollection = Collections[ ModCollection.DefaultCollection ]; - config.CurrentCollection = ModCollection.DefaultCollection; - return true; + private bool LoadForcedCollection( Configuration config ) + { + if( config.ForcedCollection == string.Empty ) + { + ForcedCollection = ModCollection.Empty; + return false; } - private bool LoadForcedCollection( Configuration config ) + if( Collections.TryGetValue( config.ForcedCollection, out var forcedCollection ) ) { - if( config.ForcedCollection == string.Empty ) - { - ForcedCollection = ModCollection.Empty; - return false; - } + ForcedCollection = forcedCollection; + AddCache( ForcedCollection ); + return false; + } - if( Collections.TryGetValue( config.ForcedCollection, out var forcedCollection ) ) - { - ForcedCollection = forcedCollection; - AddCache( ForcedCollection ); - return false; - } + PluginLog.Error( $"Last choice of ForcedCollection {config.ForcedCollection} is not available, reset to None." ); + ForcedCollection = ModCollection.Empty; + config.ForcedCollection = string.Empty; + return true; + } - PluginLog.Error( $"Last choice of ForcedCollection {config.ForcedCollection} is not available, reset to None." ); - ForcedCollection = ModCollection.Empty; - config.ForcedCollection = string.Empty; - return true; + private bool LoadDefaultCollection( Configuration config ) + { + if( config.DefaultCollection == string.Empty ) + { + DefaultCollection = ModCollection.Empty; + return false; } - private bool LoadDefaultCollection( Configuration config ) + if( Collections.TryGetValue( config.DefaultCollection, out var defaultCollection ) ) { - if( config.DefaultCollection == string.Empty ) + DefaultCollection = defaultCollection; + AddCache( DefaultCollection ); + return false; + } + + PluginLog.Error( $"Last choice of DefaultCollection {config.DefaultCollection} is not available, reset to None." ); + DefaultCollection = ModCollection.Empty; + config.DefaultCollection = string.Empty; + return true; + } + + private bool LoadCharacterCollections( Configuration config ) + { + var configChanged = false; + foreach( var (player, collectionName) in config.CharacterCollections.ToArray() ) + { + Penumbra.PlayerWatcher.AddPlayerToWatch( player ); + if( collectionName == string.Empty ) { - DefaultCollection = ModCollection.Empty; - return false; + CharacterCollection.Add( player, ModCollection.Empty ); } - - if( Collections.TryGetValue( config.DefaultCollection, out var defaultCollection ) ) + else if( Collections.TryGetValue( collectionName, out var charCollection ) ) + { + AddCache( charCollection ); + CharacterCollection.Add( player, charCollection ); + } + else { - DefaultCollection = defaultCollection; - AddCache( DefaultCollection ); - return false; + PluginLog.Error( $"Last choice of <{player}>'s Collection {collectionName} is not available, reset to None." ); + CharacterCollection.Add( player, ModCollection.Empty ); + config.CharacterCollections[ player ] = string.Empty; + configChanged = true; } + } - PluginLog.Error( $"Last choice of DefaultCollection {config.DefaultCollection} is not available, reset to None." ); - DefaultCollection = ModCollection.Empty; - config.DefaultCollection = string.Empty; - return true; + return configChanged; + } + + private void LoadConfigCollections( Configuration config ) + { + var configChanged = LoadCurrentCollection( config ); + configChanged |= LoadDefaultCollection( config ); + configChanged |= LoadForcedCollection( config ); + configChanged |= LoadCharacterCollections( config ); + + if( configChanged ) + { + config.Save(); } + } - private bool LoadCharacterCollections( Configuration config ) + private void ReadCollections() + { + var collectionDir = ModCollection.CollectionDir(); + if( collectionDir.Exists ) { - var configChanged = false; - foreach( var kvp in config.CharacterCollections.ToArray() ) + foreach( var file in collectionDir.EnumerateFiles( "*.json" ) ) { - Penumbra.PlayerWatcher.AddPlayerToWatch( kvp.Key ); - if( kvp.Value == string.Empty ) + var collection = ModCollection.LoadFromFile( file ); + if( collection == null || collection.Name == string.Empty ) { - CharacterCollection.Add( kvp.Key, ModCollection.Empty ); + continue; } - else if( Collections.TryGetValue( kvp.Value, out var charCollection ) ) + + if( file.Name != $"{collection.Name.RemoveInvalidPathSymbols()}.json" ) { - AddCache( charCollection ); - CharacterCollection.Add( kvp.Key, charCollection ); + PluginLog.Warning( $"Collection {file.Name} does not correspond to {collection.Name}." ); + } + + if( Collections.ContainsKey( collection.Name ) ) + { + PluginLog.Warning( $"Duplicate collection found: {collection.Name} already exists." ); } else { - PluginLog.Error( $"Last choice of <{kvp.Key}>'s Collection {kvp.Value} is not available, reset to None." ); - CharacterCollection.Add( kvp.Key, ModCollection.Empty ); - config.CharacterCollections[ kvp.Key ] = string.Empty; - configChanged = true; + Collections.Add( collection.Name, collection ); } } - - return configChanged; - } - - private void LoadConfigCollections( Configuration config ) - { - var configChanged = LoadCurrentCollection( config ); - configChanged |= LoadDefaultCollection( config ); - configChanged |= LoadForcedCollection( config ); - configChanged |= LoadCharacterCollections( config ); - - if( configChanged ) - { - config.Save(); - } } - private void ReadCollections() + if( !Collections.ContainsKey( ModCollection.DefaultCollection ) ) { - var collectionDir = ModCollection.CollectionDir(); - if( collectionDir.Exists ) - { - foreach( var file in collectionDir.EnumerateFiles( "*.json" ) ) - { - var collection = ModCollection.LoadFromFile( file ); - if( collection != null ) - { - if( file.Name != $"{collection.Name.RemoveInvalidPathSymbols()}.json" ) - { - PluginLog.Warning( $"Collection {file.Name} does not correspond to {collection.Name}." ); - } - - if( Collections.ContainsKey( collection.Name ) ) - { - PluginLog.Warning( $"Duplicate collection found: {collection.Name} already exists." ); - } - else - { - Collections.Add( collection.Name, collection ); - } - } - } - } - - if( !Collections.ContainsKey( ModCollection.DefaultCollection ) ) - { - var defaultCollection = new ModCollection(); - defaultCollection.Save(); - Collections.Add( defaultCollection.Name, defaultCollection ); - } + var defaultCollection = new ModCollection(); + defaultCollection.Save(); + Collections.Add( defaultCollection.Name, defaultCollection ); } } } \ No newline at end of file diff --git a/Penumbra/Mods/ModManager.cs b/Penumbra/Mods/ModManager.cs index 03846e9c..87b78d4b 100644 --- a/Penumbra/Mods/ModManager.cs +++ b/Penumbra/Mods/ModManager.cs @@ -130,7 +130,10 @@ private void SetBaseDirectory( string newPath, bool firstTime ) } } - Collections?.RecreateCaches(); + if( !firstTime ) + { + Collections.RecreateCaches(); + } } }