diff --git a/Penumbra/Api/IPenumbraApi.cs b/Penumbra/Api/IPenumbraApi.cs index e14df92b..37265ce9 100644 --- a/Penumbra/Api/IPenumbraApi.cs +++ b/Penumbra/Api/IPenumbraApi.cs @@ -51,7 +51,6 @@ public interface IPenumbraApi : IPenumbraApiBase // Triggered when the user clicks a listed changed object in a mod tab. public event ChangedItemClick? ChangedItemClicked; - event EventHandler? ObjectIsRedrawn; // Queue redrawing of all actors of the given name with the given RedrawType. public void RedrawObject( string name, RedrawType setting ); @@ -73,9 +72,6 @@ public interface IPenumbraApi : IPenumbraApiBase // Returns the given gamePath if penumbra would not manipulate it. public string ResolvePath( string gamePath, string characterName ); - // Reverse resolves a given modded local path into its replacement in form of all applicable game path for given character - public string[] ReverseResolvePath( string moddedPath, string characterName ); - // Try to load a given gamePath with the resolved path from Penumbra. public T? GetFile< T >( string gamePath ) where T : FileResource; diff --git a/Penumbra/Api/PenumbraApi.cs b/Penumbra/Api/PenumbraApi.cs index 2fd52b99..a81ab204 100644 --- a/Penumbra/Api/PenumbraApi.cs +++ b/Penumbra/Api/PenumbraApi.cs @@ -18,9 +18,8 @@ namespace Penumbra.Api; public class PenumbraApi : IDisposable, IPenumbraApi { public int ApiVersion { get; } = 4; - private Penumbra? _penumbra; + private Penumbra? _penumbra; private Lumina.GameData? _lumina; - public event EventHandler? ObjectIsRedrawn; public bool Valid => _penumbra != null; @@ -31,19 +30,12 @@ public class PenumbraApi : IDisposable, IPenumbraApi _lumina = ( Lumina.GameData? )Dalamud.GameData.GetType() .GetField( "gameData", BindingFlags.Instance | BindingFlags.NonPublic ) ?.GetValue( Dalamud.GameData ); - _penumbra.ObjectReloader.ObjectIsRedrawn += ObjectReloader_ObjectIsRedrawn; - } - - private void ObjectReloader_ObjectIsRedrawn( object? sender, EventArgs e ) - { - ObjectIsRedrawn?.Invoke( sender, e ); } public void Dispose() { - _penumbra!.ObjectReloader.ObjectIsRedrawn -= ObjectReloader_ObjectIsRedrawn; _penumbra = null; - _lumina = null; + _lumina = null; } public event ChangedItemClick? ChangedItemClicked; @@ -57,7 +49,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi public IPluginConfiguration GetConfiguration() { CheckInitialized(); - return JsonConvert.DeserializeObject( JsonConvert.SerializeObject( Penumbra.Config ) ); + return JsonConvert.DeserializeObject< Configuration >( JsonConvert.SerializeObject( Penumbra.Config ) ); } public event ChangedItemHover? ChangedItemTooltip; @@ -112,7 +104,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi } var gamePath = Utf8GamePath.FromString( path, out var p, true ) ? p : Utf8GamePath.Empty; - var ret = collection.ResolvePath( gamePath ); + var ret = collection.ResolvePath( gamePath ); return ret?.ToString() ?? path; } @@ -129,31 +121,17 @@ public class PenumbraApi : IDisposable, IPenumbraApi Penumbra.CollectionManager.Character( characterName ) ); } - public string[] ReverseResolvePath( string path, string characterName ) - { - CheckInitialized(); - if( !Penumbra.Config.EnableMods ) - { - return new[] { path }; - } - - var gamePath = Utf8GamePath.FromString( path, out var p, true ) ? p : Utf8GamePath.Empty; - var ret = Penumbra.CollectionManager.Character( characterName ).ResolveReversePath( new FullPath( path ) ) ?? new List(); - if( ret.Count == 0 ) ret.Add( gamePath ); - return ret.Select( r => r.ToString() ).ToArray(); - } - - private T? GetFileIntern( string resolvedPath ) where T : FileResource + private T? GetFileIntern< T >( string resolvedPath ) where T : FileResource { CheckInitialized(); try { if( Path.IsPathRooted( resolvedPath ) ) { - return _lumina?.GetFileFromDisk( resolvedPath ); + return _lumina?.GetFileFromDisk< T >( resolvedPath ); } - return Dalamud.GameData.GetFile( resolvedPath ); + return Dalamud.GameData.GetFile< T >( resolvedPath ); } catch( Exception e ) { @@ -162,13 +140,13 @@ public class PenumbraApi : IDisposable, IPenumbraApi } } - public T? GetFile( string gamePath ) where T : FileResource - => GetFileIntern( ResolvePath( gamePath ) ); + public T? GetFile< T >( string gamePath ) where T : FileResource + => GetFileIntern< T >( ResolvePath( gamePath ) ); - public T? GetFile( string gamePath, string characterName ) where T : FileResource - => GetFileIntern( ResolvePath( gamePath, characterName ) ); + public T? GetFile< T >( string gamePath, string characterName ) where T : FileResource + => GetFileIntern< T >( ResolvePath( gamePath, characterName ) ); - public IReadOnlyDictionary GetChangedItemsForCollection( string collectionName ) + public IReadOnlyDictionary< string, object? > GetChangedItemsForCollection( string collectionName ) { CheckInitialized(); try @@ -184,7 +162,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi } PluginLog.Warning( $"Collection {collectionName} does not exist or is not loaded." ); - return new Dictionary(); + return new Dictionary< string, object? >(); } catch( Exception e ) { @@ -193,7 +171,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi } } - public IList GetCollections() + public IList< string > GetCollections() { CheckInitialized(); return Penumbra.CollectionManager.Skip( 1 ).Select( c => c.Name ).ToArray(); @@ -215,27 +193,27 @@ public class PenumbraApi : IDisposable, IPenumbraApi { CheckInitialized(); return Penumbra.CollectionManager.Characters.TryGetValue( characterName, out var collection ) - ? (collection.Name, true) - : (Penumbra.CollectionManager.Default.Name, false); + ? ( collection.Name, true ) + : ( Penumbra.CollectionManager.Default.Name, false ); } public (IntPtr, string) GetDrawObjectInfo( IntPtr drawObject ) { CheckInitialized(); var (obj, collection) = _penumbra!.PathResolver.IdentifyDrawObject( drawObject ); - return (obj, collection.Name); + return ( obj, collection.Name ); } - public IList<(string, string)> GetModList() + public IList< (string, string) > GetModList() { CheckInitialized(); - return Penumbra.ModManager.Select( m => (m.ModPath.Name, m.Name.Text) ).ToArray(); + return Penumbra.ModManager.Select( m => ( m.ModPath.Name, m.Name.Text ) ).ToArray(); } - public Dictionary? GetAvailableModSettings( string modDirectory, string modName ) + public Dictionary< string, (string[], SelectType) >? GetAvailableModSettings( string modDirectory, string modName ) => throw new NotImplementedException(); - public (PenumbraApiEc, (bool, int, Dictionary, bool)?) GetCurrentModSettings( string collectionName, string modDirectory, string modName, + public (PenumbraApiEc, (bool, int, Dictionary< string, string[] >, bool)?) GetCurrentModSettings( string collectionName, string modDirectory, string modName, bool allowInheritance ) => throw new NotImplementedException(); diff --git a/Penumbra/Api/PenumbraIpc.cs b/Penumbra/Api/PenumbraIpc.cs index f5c59830..d8dc6db0 100644 --- a/Penumbra/Api/PenumbraIpc.cs +++ b/Penumbra/Api/PenumbraIpc.cs @@ -38,23 +38,23 @@ public partial class PenumbraIpc : IDisposable public partial class PenumbraIpc { - public const string LabelProviderInitialized = "Penumbra.Initialized"; - public const string LabelProviderDisposed = "Penumbra.Disposed"; - public const string LabelProviderApiVersion = "Penumbra.ApiVersion"; - public const string LabelProviderGetModDirectory = "Penumbra.GetModDirectory"; + public const string LabelProviderInitialized = "Penumbra.Initialized"; + public const string LabelProviderDisposed = "Penumbra.Disposed"; + public const string LabelProviderApiVersion = "Penumbra.ApiVersion"; + public const string LabelProviderGetModDirectory = "Penumbra.GetModDirectory"; public const string LabelProviderGetConfiguration = "Penumbra.GetConfiguration"; - internal ICallGateProvider? ProviderInitialized; - internal ICallGateProvider? ProviderDisposed; - internal ICallGateProvider? ProviderApiVersion; - internal ICallGateProvider? ProviderGetModDirectory; - internal ICallGateProvider? ProviderGetConfiguration; + internal ICallGateProvider< object? >? ProviderInitialized; + internal ICallGateProvider< object? >? ProviderDisposed; + internal ICallGateProvider< int >? ProviderApiVersion; + internal ICallGateProvider< string >? ProviderGetModDirectory; + internal ICallGateProvider< IPluginConfiguration >? ProviderGetConfiguration; private void InitializeGeneralProviders( DalamudPluginInterface pi ) { try { - ProviderInitialized = pi.GetIpcProvider( LabelProviderInitialized ); + ProviderInitialized = pi.GetIpcProvider< object? >( LabelProviderInitialized ); } catch( Exception e ) { @@ -63,7 +63,7 @@ public partial class PenumbraIpc try { - ProviderDisposed = pi.GetIpcProvider( LabelProviderDisposed ); + ProviderDisposed = pi.GetIpcProvider< object? >( LabelProviderDisposed ); } catch( Exception e ) { @@ -72,7 +72,7 @@ public partial class PenumbraIpc try { - ProviderApiVersion = pi.GetIpcProvider( LabelProviderApiVersion ); + ProviderApiVersion = pi.GetIpcProvider< int >( LabelProviderApiVersion ); ProviderApiVersion.RegisterFunc( () => Api.ApiVersion ); } catch( Exception e ) @@ -82,7 +82,7 @@ public partial class PenumbraIpc try { - ProviderGetModDirectory = pi.GetIpcProvider( LabelProviderGetModDirectory ); + ProviderGetModDirectory = pi.GetIpcProvider< string >( LabelProviderGetModDirectory ); ProviderGetModDirectory.RegisterFunc( Api.GetModDirectory ); } catch( Exception e ) @@ -92,7 +92,7 @@ public partial class PenumbraIpc try { - ProviderGetConfiguration = pi.GetIpcProvider( LabelProviderGetConfiguration ); + ProviderGetConfiguration = pi.GetIpcProvider< IPluginConfiguration >( LabelProviderGetConfiguration ); ProviderGetConfiguration.RegisterFunc( Api.GetConfiguration ); } catch( Exception e ) @@ -111,17 +111,15 @@ public partial class PenumbraIpc public partial class PenumbraIpc { - public const string LabelProviderRedrawName = "Penumbra.RedrawObjectByName"; - public const string LabelProviderRedrawIndex = "Penumbra.RedrawObjectByIndex"; + public const string LabelProviderRedrawName = "Penumbra.RedrawObjectByName"; + public const string LabelProviderRedrawIndex = "Penumbra.RedrawObjectByIndex"; public const string LabelProviderRedrawObject = "Penumbra.RedrawObject"; - public const string LabelProviderRedrawAll = "Penumbra.RedrawAll"; - public const string LabelProviderObjectIsRedrawn = "Penumbra.ObjectIsRedrawn"; + public const string LabelProviderRedrawAll = "Penumbra.RedrawAll"; - internal ICallGateProvider? ProviderRedrawName; - internal ICallGateProvider? ProviderRedrawIndex; - internal ICallGateProvider? ProviderRedrawObject; - internal ICallGateProvider? ProviderRedrawAll; - internal ICallGateProvider ProviderObjectIsRedrawn; + internal ICallGateProvider< string, int, object >? ProviderRedrawName; + internal ICallGateProvider< int, int, object >? ProviderRedrawIndex; + internal ICallGateProvider< GameObject, int, object >? ProviderRedrawObject; + internal ICallGateProvider< int, object >? ProviderRedrawAll; private static RedrawType CheckRedrawType( int value ) { @@ -138,7 +136,7 @@ public partial class PenumbraIpc { try { - ProviderRedrawName = pi.GetIpcProvider( LabelProviderRedrawName ); + ProviderRedrawName = pi.GetIpcProvider< string, int, object >( LabelProviderRedrawName ); ProviderRedrawName.RegisterAction( ( s, i ) => Api.RedrawObject( s, CheckRedrawType( i ) ) ); } catch( Exception e ) @@ -158,7 +156,7 @@ public partial class PenumbraIpc try { - ProviderRedrawObject = pi.GetIpcProvider( LabelProviderRedrawObject ); + ProviderRedrawObject = pi.GetIpcProvider< GameObject, int, object >( LabelProviderRedrawObject ); ProviderRedrawObject.RegisterAction( ( o, i ) => Api.RedrawObject( o, CheckRedrawType( i ) ) ); } catch( Exception e ) @@ -168,28 +166,13 @@ public partial class PenumbraIpc try { - ProviderRedrawAll = pi.GetIpcProvider( LabelProviderRedrawAll ); + ProviderRedrawAll = pi.GetIpcProvider< int, object >( LabelProviderRedrawAll ); ProviderRedrawAll.RegisterAction( i => Api.RedrawAll( CheckRedrawType( i ) ) ); } catch( Exception e ) { PluginLog.Error( $"Error registering IPC provider for {LabelProviderRedrawAll}:\n{e}" ); } - - try - { - ProviderObjectIsRedrawn = pi.GetIpcProvider( LabelProviderObjectIsRedrawn ); - Api.ObjectIsRedrawn += Api_ObjectIsRedrawn; - } - catch( Exception e ) - { - PluginLog.Error( $"Error registering IPC provider for {LabelProviderObjectIsRedrawn}:\n{e}" ); - } - } - - private void Api_ObjectIsRedrawn( object? sender, EventArgs e ) - { - ProviderObjectIsRedrawn.SendMessage( ( ( GameObject? )sender )?.Name.ToString() ?? "" ); } private void DisposeRedrawProviders() @@ -198,27 +181,24 @@ public partial class PenumbraIpc ProviderRedrawIndex?.UnregisterAction(); ProviderRedrawObject?.UnregisterAction(); ProviderRedrawAll?.UnregisterAction(); - Api.ObjectIsRedrawn -= Api_ObjectIsRedrawn; } } public partial class PenumbraIpc { - public const string LabelProviderResolveDefault = "Penumbra.ResolveDefaultPath"; - public const string LabelProviderResolveCharacter = "Penumbra.ResolveCharacterPath"; + public const string LabelProviderResolveDefault = "Penumbra.ResolveDefaultPath"; + public const string LabelProviderResolveCharacter = "Penumbra.ResolveCharacterPath"; public const string LabelProviderGetDrawObjectInfo = "Penumbra.GetDrawObjectInfo"; - public const string LabelProviderReverseResolvePath = "Penumbra.ReverseResolvePath"; - internal ICallGateProvider? ProviderResolveDefault; - internal ICallGateProvider? ProviderResolveCharacter; - internal ICallGateProvider? ProviderGetDrawObjectInfo; - internal ICallGateProvider? ProviderReverseResolvePath; + internal ICallGateProvider< string, string >? ProviderResolveDefault; + internal ICallGateProvider< string, string, string >? ProviderResolveCharacter; + internal ICallGateProvider< IntPtr, (IntPtr, string) >? ProviderGetDrawObjectInfo; private void InitializeResolveProviders( DalamudPluginInterface pi ) { try { - ProviderResolveDefault = pi.GetIpcProvider( LabelProviderResolveDefault ); + ProviderResolveDefault = pi.GetIpcProvider< string, string >( LabelProviderResolveDefault ); ProviderResolveDefault.RegisterFunc( Api.ResolvePath ); } catch( Exception e ) @@ -228,7 +208,7 @@ public partial class PenumbraIpc try { - ProviderResolveCharacter = pi.GetIpcProvider( LabelProviderResolveCharacter ); + ProviderResolveCharacter = pi.GetIpcProvider< string, string, string >( LabelProviderResolveCharacter ); ProviderResolveCharacter.RegisterFunc( Api.ResolvePath ); } catch( Exception e ) @@ -238,23 +218,13 @@ public partial class PenumbraIpc try { - ProviderGetDrawObjectInfo = pi.GetIpcProvider( LabelProviderGetDrawObjectInfo ); + ProviderGetDrawObjectInfo = pi.GetIpcProvider< IntPtr, (IntPtr, string) >( LabelProviderGetDrawObjectInfo ); ProviderGetDrawObjectInfo.RegisterFunc( Api.GetDrawObjectInfo ); } catch( Exception e ) { PluginLog.Error( $"Error registering IPC provider for {LabelProviderGetDrawObjectInfo}:\n{e}" ); } - - try - { - ProviderReverseResolvePath = pi.GetIpcProvider( LabelProviderReverseResolvePath ); - ProviderReverseResolvePath.RegisterFunc( Api.ReverseResolvePath ); - } - catch( Exception e ) - { - PluginLog.Error( $"Error registering IPC provider for {LabelProviderGetDrawObjectInfo}:\n{e}" ); - } } private void DisposeResolveProviders() @@ -268,12 +238,12 @@ public partial class PenumbraIpc public partial class PenumbraIpc { public const string LabelProviderChangedItemTooltip = "Penumbra.ChangedItemTooltip"; - public const string LabelProviderChangedItemClick = "Penumbra.ChangedItemClick"; - public const string LabelProviderGetChangedItems = "Penumbra.GetChangedItems"; + public const string LabelProviderChangedItemClick = "Penumbra.ChangedItemClick"; + public const string LabelProviderGetChangedItems = "Penumbra.GetChangedItems"; - internal ICallGateProvider? ProviderChangedItemTooltip; - internal ICallGateProvider? ProviderChangedItemClick; - internal ICallGateProvider>? ProviderGetChangedItems; + internal ICallGateProvider< ChangedItemType, uint, object >? ProviderChangedItemTooltip; + internal ICallGateProvider< MouseButton, ChangedItemType, uint, object >? ProviderChangedItemClick; + internal ICallGateProvider< string, IReadOnlyDictionary< string, object? > >? ProviderGetChangedItems; private void OnClick( MouseButton click, object? item ) { @@ -291,8 +261,8 @@ public partial class PenumbraIpc { try { - ProviderChangedItemTooltip = pi.GetIpcProvider( LabelProviderChangedItemTooltip ); - Api.ChangedItemTooltip += OnTooltip; + ProviderChangedItemTooltip = pi.GetIpcProvider< ChangedItemType, uint, object >( LabelProviderChangedItemTooltip ); + Api.ChangedItemTooltip += OnTooltip; } catch( Exception e ) { @@ -301,8 +271,8 @@ public partial class PenumbraIpc try { - ProviderChangedItemClick = pi.GetIpcProvider( LabelProviderChangedItemClick ); - Api.ChangedItemClicked += OnClick; + ProviderChangedItemClick = pi.GetIpcProvider< MouseButton, ChangedItemType, uint, object >( LabelProviderChangedItemClick ); + Api.ChangedItemClicked += OnClick; } catch( Exception e ) { @@ -311,7 +281,7 @@ public partial class PenumbraIpc try { - ProviderGetChangedItems = pi.GetIpcProvider>( LabelProviderGetChangedItems ); + ProviderGetChangedItems = pi.GetIpcProvider< string, IReadOnlyDictionary< string, object? > >( LabelProviderGetChangedItems ); ProviderGetChangedItems.RegisterFunc( Api.GetChangedItemsForCollection ); } catch( Exception e ) @@ -330,23 +300,23 @@ public partial class PenumbraIpc public partial class PenumbraIpc { - public const string LabelProviderGetMods = "Penumbra.GetMods"; - public const string LabelProviderGetCollections = "Penumbra.GetCollections"; - public const string LabelProviderCurrentCollectionName = "Penumbra.GetCurrentCollectionName"; - public const string LabelProviderDefaultCollectionName = "Penumbra.GetDefaultCollectionName"; + public const string LabelProviderGetMods = "Penumbra.GetMods"; + public const string LabelProviderGetCollections = "Penumbra.GetCollections"; + public const string LabelProviderCurrentCollectionName = "Penumbra.GetCurrentCollectionName"; + public const string LabelProviderDefaultCollectionName = "Penumbra.GetDefaultCollectionName"; public const string LabelProviderCharacterCollectionName = "Penumbra.GetCharacterCollectionName"; - internal ICallGateProvider>? ProviderGetMods; - internal ICallGateProvider>? ProviderGetCollections; - internal ICallGateProvider? ProviderCurrentCollectionName; - internal ICallGateProvider? ProviderDefaultCollectionName; - internal ICallGateProvider? ProviderCharacterCollectionName; + internal ICallGateProvider< IList< (string, string) > >? ProviderGetMods; + internal ICallGateProvider< IList< string > >? ProviderGetCollections; + internal ICallGateProvider< string >? ProviderCurrentCollectionName; + internal ICallGateProvider< string >? ProviderDefaultCollectionName; + internal ICallGateProvider< string, (string, bool) >? ProviderCharacterCollectionName; private void InitializeDataProviders( DalamudPluginInterface pi ) { try { - ProviderGetMods = pi.GetIpcProvider>( LabelProviderGetMods ); + ProviderGetMods = pi.GetIpcProvider< IList< (string, string) > >( LabelProviderGetMods ); ProviderGetMods.RegisterFunc( Api.GetModList ); } catch( Exception e ) @@ -356,7 +326,7 @@ public partial class PenumbraIpc try { - ProviderGetCollections = pi.GetIpcProvider>( LabelProviderGetCollections ); + ProviderGetCollections = pi.GetIpcProvider< IList< string > >( LabelProviderGetCollections ); ProviderGetCollections.RegisterFunc( Api.GetCollections ); } catch( Exception e ) @@ -366,7 +336,7 @@ public partial class PenumbraIpc try { - ProviderCurrentCollectionName = pi.GetIpcProvider( LabelProviderCurrentCollectionName ); + ProviderCurrentCollectionName = pi.GetIpcProvider< string >( LabelProviderCurrentCollectionName ); ProviderCurrentCollectionName.RegisterFunc( Api.GetCurrentCollection ); } catch( Exception e ) @@ -376,7 +346,7 @@ public partial class PenumbraIpc try { - ProviderDefaultCollectionName = pi.GetIpcProvider( LabelProviderDefaultCollectionName ); + ProviderDefaultCollectionName = pi.GetIpcProvider< string >( LabelProviderDefaultCollectionName ); ProviderDefaultCollectionName.RegisterFunc( Api.GetDefaultCollection ); } catch( Exception e ) @@ -386,7 +356,7 @@ public partial class PenumbraIpc try { - ProviderCharacterCollectionName = pi.GetIpcProvider( LabelProviderCharacterCollectionName ); + ProviderCharacterCollectionName = pi.GetIpcProvider< string, ( string, bool) >( LabelProviderCharacterCollectionName ); ProviderCharacterCollectionName.RegisterFunc( Api.GetCharacterCollection ); } catch( Exception e ) diff --git a/Penumbra/Collections/ModCollection.Cache.Access.cs b/Penumbra/Collections/ModCollection.Cache.Access.cs index 871280a2..2e3bda92 100644 --- a/Penumbra/Collections/ModCollection.Cache.Access.cs +++ b/Penumbra/Collections/ModCollection.Cache.Access.cs @@ -44,7 +44,6 @@ public partial class ModCollection PluginLog.Verbose( "Cleared cache of collection {Name:l}.", Name ); } - public List? ResolveReversePath( FullPath path ) => _cache?.ReverseResolvePath( path ); public FullPath? ResolvePath( Utf8GamePath path ) => _cache?.ResolvePath( path ); diff --git a/Penumbra/Collections/ModCollection.Cache.cs b/Penumbra/Collections/ModCollection.Cache.cs index c1ed8f1c..6e959e69 100644 --- a/Penumbra/Collections/ModCollection.Cache.cs +++ b/Penumbra/Collections/ModCollection.Cache.cs @@ -12,7 +12,7 @@ using Penumbra.Util; namespace Penumbra.Collections; public record struct ModPath( Mod Mod, FullPath Path ); -public record ModConflicts( Mod Mod2, List Conflicts, bool HasPriority, bool Solved ); +public record ModConflicts( Mod Mod2, List< object > Conflicts, bool HasPriority, bool Solved ); public partial class ModCollection { @@ -20,17 +20,17 @@ public partial class ModCollection // It will only be setup if a collection gets activated in any way. private class Cache : IDisposable { - private readonly ModCollection _collection; - private readonly SortedList, object?)> _changedItems = new(); - public readonly Dictionary ResolvedFiles = new(); - public readonly MetaManager MetaManipulations; - private readonly Dictionary> _conflicts = new(); + private readonly ModCollection _collection; + private readonly SortedList< string, (SingleArray< Mod >, object?) > _changedItems = new(); + public readonly Dictionary< Utf8GamePath, ModPath > ResolvedFiles = new(); + public readonly MetaManager MetaManipulations; + private readonly Dictionary< Mod, SingleArray< ModConflicts > > _conflicts = new(); - public IEnumerable> AllConflicts + public IEnumerable< SingleArray< ModConflicts > > AllConflicts => _conflicts.Values; - public SingleArray Conflicts( Mod mod ) - => _conflicts.TryGetValue( mod, out var c ) ? c : new SingleArray(); + public SingleArray< ModConflicts > Conflicts( Mod mod ) + => _conflicts.TryGetValue( mod, out var c ) ? c : new SingleArray< ModConflicts >(); // Count the number of changes of the effective file list. // This is used for material and imc changes. @@ -38,7 +38,7 @@ public partial class ModCollection private int _changedItemsSaveCounter = -1; // Obtain currently changed items. Computes them if they haven't been computed before. - public IReadOnlyDictionary, object?)> ChangedItems + public IReadOnlyDictionary< string, (SingleArray< Mod >, object?) > ChangedItems { get { @@ -50,15 +50,15 @@ public partial class ModCollection // The cache reacts through events on its collection changing. public Cache( ModCollection collection ) { - _collection = collection; - MetaManipulations = new MetaManager( collection ); - _collection.ModSettingChanged += OnModSettingChange; + _collection = collection; + MetaManipulations = new MetaManager( collection ); + _collection.ModSettingChanged += OnModSettingChange; _collection.InheritanceChanged += OnInheritanceChange; } public void Dispose() { - _collection.ModSettingChanged -= OnModSettingChange; + _collection.ModSettingChanged -= OnModSettingChange; _collection.InheritanceChanged -= OnInheritanceChange; } @@ -79,50 +79,43 @@ public partial class ModCollection return candidate.Path; } - public List ReverseResolvePath( FullPath localFilePath ) - { - string strToSearchFor = localFilePath.FullName.Replace( '/', '\\' ).ToLower(); - return ResolvedFiles.Where( f => f.Value.Path.FullName.ToLower() == strToSearchFor ) - .Select( kvp => kvp.Key ).ToList(); - } - private void OnModSettingChange( ModSettingChange type, int modIdx, int oldValue, int groupIdx, bool _ ) { switch( type ) { case ModSettingChange.Inheritance: - ReloadMod( Penumbra.ModManager[modIdx], true ); + ReloadMod( Penumbra.ModManager[ modIdx ], true ); break; case ModSettingChange.EnableState: if( oldValue == 0 ) { - AddMod( Penumbra.ModManager[modIdx], true ); + AddMod( Penumbra.ModManager[ modIdx ], true ); } else if( oldValue == 1 ) { - RemoveMod( Penumbra.ModManager[modIdx], true ); + RemoveMod( Penumbra.ModManager[ modIdx ], true ); } - else if( _collection[modIdx].Settings?.Enabled == true ) + else if( _collection[ modIdx ].Settings?.Enabled == true ) { - ReloadMod( Penumbra.ModManager[modIdx], true ); + ReloadMod( Penumbra.ModManager[ modIdx ], true ); } else { - RemoveMod( Penumbra.ModManager[modIdx], true ); + RemoveMod( Penumbra.ModManager[ modIdx ], true ); } break; case ModSettingChange.Priority: - if( Conflicts( Penumbra.ModManager[modIdx] ).Count > 0 ) + if( Conflicts( Penumbra.ModManager[ modIdx ] ).Count > 0 ) { - ReloadMod( Penumbra.ModManager[modIdx], true ); + ReloadMod( Penumbra.ModManager[ modIdx ], true ); } break; case ModSettingChange.Setting: - if( _collection[modIdx].Settings?.Enabled == true ) + if( _collection[ modIdx ].Settings?.Enabled == true ) { - ReloadMod( Penumbra.ModManager[modIdx], true ); + ReloadMod( Penumbra.ModManager[ modIdx ], true ); } break; @@ -206,7 +199,7 @@ public partial class ModCollection var newConflicts = Conflicts( conflict.Mod2 ).Remove( c => c.Mod2 == mod ); if( newConflicts.Count > 0 ) { - _conflicts[conflict.Mod2] = newConflicts; + _conflicts[ conflict.Mod2 ] = newConflicts; } else { @@ -230,7 +223,7 @@ public partial class ModCollection // Add all files and possibly manipulations of a given mod according to its settings in this collection. public void AddMod( Mod mod, bool addMetaChanges ) { - var settings = _collection[mod.Index].Settings; + var settings = _collection[ mod.Index ].Settings; if( settings is not { Enabled: true } ) { return; @@ -243,23 +236,23 @@ public partial class ModCollection continue; } - var config = settings.Settings[groupIndex]; + var config = settings.Settings[ groupIndex ]; switch( group.Type ) { case SelectType.Single: - AddSubMod( group[( int )config], mod ); + AddSubMod( group[ ( int )config ], mod ); break; case SelectType.Multi: + { + foreach( var (option, _) in group.WithIndex() + .OrderByDescending( p => group.OptionPriority( p.Item2 ) ) + .Where( p => ( ( 1 << p.Item2 ) & config ) != 0 ) ) { - foreach( var (option, _) in group.WithIndex() - .OrderByDescending( p => group.OptionPriority( p.Item2 ) ) - .Where( p => ( ( 1 << p.Item2 ) & config ) != 0 ) ) - { - AddSubMod( option, mod ); - } - - break; + AddSubMod( option, mod ); } + + break; + } } } @@ -312,7 +305,7 @@ public partial class ModCollection return; } - var modPath = ResolvedFiles[path]; + var modPath = ResolvedFiles[ path ]; // Lower prioritized option in the same mod. if( mod == modPath.Mod ) { @@ -321,14 +314,14 @@ public partial class ModCollection if( AddConflict( path, mod, modPath.Mod ) ) { - ResolvedFiles[path] = new ModPath( mod, file ); + ResolvedFiles[ path ] = new ModPath( mod, file ); } } // Remove all empty conflict sets for a given mod with the given conflicts. // If transitive is true, also removes the corresponding version of the other mod. - private void RemoveEmptyConflicts( Mod mod, SingleArray oldConflicts, bool transitive ) + private void RemoveEmptyConflicts( Mod mod, SingleArray< ModConflicts > oldConflicts, bool transitive ) { var changedConflicts = oldConflicts.Remove( c => { @@ -350,7 +343,7 @@ public partial class ModCollection } else { - _conflicts[mod] = changedConflicts; + _conflicts[ mod ] = changedConflicts; } } @@ -359,15 +352,15 @@ public partial class ModCollection // Returns if the added mod takes priority before the existing mod. private bool AddConflict( object data, Mod addedMod, Mod existingMod ) { - var addedPriority = addedMod.Index >= 0 ? _collection[addedMod.Index].Settings!.Priority : int.MaxValue; - var existingPriority = existingMod.Index >= 0 ? _collection[existingMod.Index].Settings!.Priority : int.MaxValue; + var addedPriority = addedMod.Index >= 0 ? _collection[ addedMod.Index ].Settings!.Priority : int.MaxValue; + var existingPriority = existingMod.Index >= 0 ? _collection[ existingMod.Index ].Settings!.Priority : int.MaxValue; if( existingPriority < addedPriority ) { var tmpConflicts = Conflicts( existingMod ); foreach( var conflict in tmpConflicts ) { - if( data is Utf8GamePath path && conflict.Conflicts.RemoveAll( p => p is Utf8GamePath x && x.Equals( path ) ) > 0 + if( data is Utf8GamePath path && conflict.Conflicts.RemoveAll( p => p is Utf8GamePath x && x.Equals( path ) ) > 0 || data is MetaManipulation meta && conflict.Conflicts.RemoveAll( m => m is MetaManipulation x && x.Equals( meta ) ) > 0 ) { AddConflict( data, addedMod, conflict.Mod2 ); @@ -377,7 +370,7 @@ public partial class ModCollection RemoveEmptyConflicts( existingMod, tmpConflicts, true ); } - var addedConflicts = Conflicts( addedMod ); + var addedConflicts = Conflicts( addedMod ); var existingConflicts = Conflicts( existingMod ); if( addedConflicts.FindFirst( c => c.Mod2 == existingMod, out var oldConflicts ) ) { @@ -387,10 +380,10 @@ public partial class ModCollection else { // Add the same conflict list to both conflict directions. - var conflictList = new List { data }; - _conflicts[addedMod] = addedConflicts.Append( new ModConflicts( existingMod, conflictList, existingPriority < addedPriority, + var conflictList = new List< object > { data }; + _conflicts[ addedMod ] = addedConflicts.Append( new ModConflicts( existingMod, conflictList, existingPriority < addedPriority, existingPriority != addedPriority ) ); - _conflicts[existingMod] = existingConflicts.Append( new ModConflicts( addedMod, conflictList, + _conflicts[ existingMod ] = existingConflicts.Append( new ModConflicts( addedMod, conflictList, existingPriority >= addedPriority, existingPriority != addedPriority ) ); } @@ -448,15 +441,15 @@ public partial class ModCollection { if( !_changedItems.TryGetValue( name, out var data ) ) { - _changedItems.Add( name, (new SingleArray( modPath.Mod ), obj) ); + _changedItems.Add( name, ( new SingleArray< Mod >( modPath.Mod ), obj ) ); } else if( !data.Item1.Contains( modPath.Mod ) ) { - _changedItems[name] = (data.Item1.Append( modPath.Mod ), obj is int x && data.Item2 is int y ? x + y : obj); + _changedItems[ name ] = ( data.Item1.Append( modPath.Mod ), obj is int x && data.Item2 is int y ? x + y : obj ); } else if( obj is int x && data.Item2 is int y ) { - _changedItems[name] = (data.Item1, x + y); + _changedItems[ name ] = ( data.Item1, x + y ); } } } diff --git a/Penumbra/Interop/ObjectReloader.cs b/Penumbra/Interop/ObjectReloader.cs index d58d434c..058fc87c 100644 --- a/Penumbra/Interop/ObjectReloader.cs +++ b/Penumbra/Interop/ObjectReloader.cs @@ -25,7 +25,6 @@ public unsafe partial class ObjectReloader private static void EnableDraw( GameObject actor ) => ( ( delegate* unmanaged< IntPtr, void >** )actor.Address )[ 0 ][ 16 ]( actor.Address ); - public event EventHandler? ObjectIsRedrawn; // Check whether we currently are in GPose. // Also clear the name list. @@ -282,8 +281,6 @@ public sealed unsafe partial class ObjectReloader : IDisposable break; default: throw new ArgumentOutOfRangeException( nameof( settings ), settings, null ); } - - ObjectIsRedrawn?.Invoke( actor, new EventArgs() ); } private static GameObject? GetLocalPlayer()