Add event for changing mod directory.

This commit is contained in:
Ottermandias 2022-08-09 22:50:54 +02:00
parent c0542d0e94
commit 5b07245cd9
8 changed files with 75 additions and 21 deletions

View file

@ -49,6 +49,10 @@ public interface IPenumbraApi : IPenumbraApiBase
// Obtain the currently set mod directory from the configuration. // Obtain the currently set mod directory from the configuration.
public string GetModDirectory(); public string GetModDirectory();
// Fired whenever a mod directory change is finished.
// Gives the full path of the mod directory and whether Penumbra treats it as valid.
public event Action< string, bool >? ModDirectoryChanged;
// Obtain the entire current penumbra configuration as a json encoded string. // Obtain the entire current penumbra configuration as a json encoded string.
public string GetConfiguration(); public string GetConfiguration();

View file

@ -28,6 +28,7 @@ public class IpcTester : IDisposable
private readonly ICallGateSubscriber< object? > _disposed; private readonly ICallGateSubscriber< object? > _disposed;
private readonly ICallGateSubscriber< string, object? > _preSettingsDraw; private readonly ICallGateSubscriber< string, object? > _preSettingsDraw;
private readonly ICallGateSubscriber< string, object? > _postSettingsDraw; private readonly ICallGateSubscriber< string, object? > _postSettingsDraw;
private readonly ICallGateSubscriber< string, bool, object? > _modDirectoryChanged;
private readonly ICallGateSubscriber< IntPtr, int, object? > _redrawn; private readonly ICallGateSubscriber< IntPtr, int, object? > _redrawn;
private readonly ICallGateSubscriber< ModSettingChange, string, string, bool, object? > _settingChanged; private readonly ICallGateSubscriber< ModSettingChange, string, string, bool, object? > _settingChanged;
private readonly ICallGateSubscriber< IntPtr, string, IntPtr, IntPtr, IntPtr, object? > _characterBaseCreated; private readonly ICallGateSubscriber< IntPtr, string, IntPtr, IntPtr, IntPtr, object? > _characterBaseCreated;
@ -45,6 +46,7 @@ public class IpcTester : IDisposable
_preSettingsDraw = _pi.GetIpcSubscriber< string, object? >( PenumbraIpc.LabelProviderPreSettingsDraw ); _preSettingsDraw = _pi.GetIpcSubscriber< string, object? >( PenumbraIpc.LabelProviderPreSettingsDraw );
_postSettingsDraw = _pi.GetIpcSubscriber< string, object? >( PenumbraIpc.LabelProviderPostSettingsDraw ); _postSettingsDraw = _pi.GetIpcSubscriber< string, object? >( PenumbraIpc.LabelProviderPostSettingsDraw );
_settingChanged = _pi.GetIpcSubscriber< ModSettingChange, string, string, bool, object? >( PenumbraIpc.LabelProviderModSettingChanged ); _settingChanged = _pi.GetIpcSubscriber< ModSettingChange, string, string, bool, object? >( PenumbraIpc.LabelProviderModSettingChanged );
_modDirectoryChanged = _pi.GetIpcSubscriber< string, bool, object? >( PenumbraIpc.LabelProviderModDirectoryChanged );
_characterBaseCreated = _characterBaseCreated =
_pi.GetIpcSubscriber< IntPtr, string, IntPtr, IntPtr, IntPtr, object? >( PenumbraIpc.LabelProviderCreatingCharacterBase ); _pi.GetIpcSubscriber< IntPtr, string, IntPtr, IntPtr, IntPtr, object? >( PenumbraIpc.LabelProviderCreatingCharacterBase );
_initialized.Subscribe( AddInitialized ); _initialized.Subscribe( AddInitialized );
@ -54,6 +56,7 @@ public class IpcTester : IDisposable
_postSettingsDraw.Subscribe( UpdateLastDrawnMod ); _postSettingsDraw.Subscribe( UpdateLastDrawnMod );
_settingChanged.Subscribe( UpdateLastModSetting ); _settingChanged.Subscribe( UpdateLastModSetting );
_characterBaseCreated.Subscribe( UpdateLastCreated ); _characterBaseCreated.Subscribe( UpdateLastCreated );
_modDirectoryChanged.Subscribe( UpdateModDirectoryChanged );
} }
public void Dispose() public void Dispose()
@ -67,6 +70,7 @@ public class IpcTester : IDisposable
_postSettingsDraw.Unsubscribe( UpdateLastDrawnMod ); _postSettingsDraw.Unsubscribe( UpdateLastDrawnMod );
_settingChanged.Unsubscribe( UpdateLastModSetting ); _settingChanged.Unsubscribe( UpdateLastModSetting );
_characterBaseCreated.Unsubscribe( UpdateLastCreated ); _characterBaseCreated.Unsubscribe( UpdateLastCreated );
_modDirectoryChanged.Unsubscribe( UpdateModDirectoryChanged );
} }
private void AddInitialized() private void AddInitialized()
@ -131,11 +135,18 @@ public class IpcTester : IDisposable
private string _currentConfiguration = string.Empty; private string _currentConfiguration = string.Empty;
private string _lastDrawnMod = string.Empty; private string _lastDrawnMod = string.Empty;
private DateTimeOffset _lastDrawnModTime; private DateTimeOffset _lastDrawnModTime = DateTimeOffset.MinValue;
private void UpdateLastDrawnMod( string name ) private void UpdateLastDrawnMod( string name )
=> ( _lastDrawnMod, _lastDrawnModTime ) = ( name, DateTimeOffset.Now ); => ( _lastDrawnMod, _lastDrawnModTime ) = ( name, DateTimeOffset.Now );
private string _lastModDirectory = string.Empty;
private bool _lastModDirectoryValid = false;
private DateTimeOffset _lastModDirectoryTime = DateTimeOffset.MinValue;
private void UpdateModDirectoryChanged( string path, bool valid )
=> ( _lastModDirectory, _lastModDirectoryValid, _lastModDirectoryTime ) = ( path, valid, DateTimeOffset.Now );
private void DrawGeneral() private void DrawGeneral()
{ {
using var _ = ImRaii.TreeNode( "General IPC" ); using var _ = ImRaii.TreeNode( "General IPC" );
@ -173,6 +184,10 @@ public class IpcTester : IDisposable
ImGui.TextUnformatted( $"{breaking}.{features:D4}" ); ImGui.TextUnformatted( $"{breaking}.{features:D4}" );
DrawIntro( PenumbraIpc.LabelProviderGetModDirectory, "Current Mod Directory" ); DrawIntro( PenumbraIpc.LabelProviderGetModDirectory, "Current Mod Directory" );
ImGui.TextUnformatted( _pi.GetIpcSubscriber< string >( PenumbraIpc.LabelProviderGetModDirectory ).InvokeFunc() ); ImGui.TextUnformatted( _pi.GetIpcSubscriber< string >( PenumbraIpc.LabelProviderGetModDirectory ).InvokeFunc() );
DrawIntro( PenumbraIpc.LabelProviderModDirectoryChanged, "Last Mod Directory Change" );
ImGui.TextUnformatted( _lastModDirectoryTime > DateTimeOffset.MinValue
? $"{_lastModDirectory} ({( _lastModDirectoryValid ? "Valid" : "Invalid" )}) at {_lastModDirectoryTime}"
: "None" );
DrawIntro( PenumbraIpc.LabelProviderGetConfiguration, "Configuration" ); DrawIntro( PenumbraIpc.LabelProviderGetConfiguration, "Configuration" );
if( ImGui.Button( "Get" ) ) if( ImGui.Button( "Get" ) )
{ {

View file

@ -84,6 +84,12 @@ public class PenumbraApi : IDisposable, IPenumbraApi
return Penumbra.Config.ModDirectory; return Penumbra.Config.ModDirectory;
} }
public event Action< string, bool >? ModDirectoryChanged
{
add => Penumbra.ModManager.ModDirectoryChanged += value;
remove => Penumbra.ModManager.ModDirectoryChanged -= value;
}
public string GetConfiguration() public string GetConfiguration()
{ {
CheckInitialized(); CheckInitialized();

View file

@ -26,6 +26,7 @@ public partial class PenumbraIpc : IDisposable
InitializeSettingProviders( pi ); InitializeSettingProviders( pi );
InitializeTempProviders( pi ); InitializeTempProviders( pi );
ProviderInitialized?.SendMessage(); ProviderInitialized?.SendMessage();
InvokeModDirectoryChanged( Penumbra.ModManager.BasePath.FullName, Penumbra.ModManager.Valid );
} }
public void Dispose() public void Dispose()
@ -49,6 +50,7 @@ public partial class PenumbraIpc
public const string LabelProviderApiVersion = "Penumbra.ApiVersion"; public const string LabelProviderApiVersion = "Penumbra.ApiVersion";
public const string LabelProviderApiVersions = "Penumbra.ApiVersions"; public const string LabelProviderApiVersions = "Penumbra.ApiVersions";
public const string LabelProviderGetModDirectory = "Penumbra.GetModDirectory"; public const string LabelProviderGetModDirectory = "Penumbra.GetModDirectory";
public const string LabelProviderModDirectoryChanged = "Penumbra.ModDirectoryChanged";
public const string LabelProviderGetConfiguration = "Penumbra.GetConfiguration"; public const string LabelProviderGetConfiguration = "Penumbra.GetConfiguration";
public const string LabelProviderPreSettingsDraw = "Penumbra.PreSettingsDraw"; public const string LabelProviderPreSettingsDraw = "Penumbra.PreSettingsDraw";
public const string LabelProviderPostSettingsDraw = "Penumbra.PostSettingsDraw"; public const string LabelProviderPostSettingsDraw = "Penumbra.PostSettingsDraw";
@ -58,6 +60,7 @@ public partial class PenumbraIpc
internal ICallGateProvider< int >? ProviderApiVersion; internal ICallGateProvider< int >? ProviderApiVersion;
internal ICallGateProvider< (int Breaking, int Features) >? ProviderApiVersions; internal ICallGateProvider< (int Breaking, int Features) >? ProviderApiVersions;
internal ICallGateProvider< string >? ProviderGetModDirectory; internal ICallGateProvider< string >? ProviderGetModDirectory;
internal ICallGateProvider< string, bool, object? >? ProviderModDirectoryChanged;
internal ICallGateProvider< string >? ProviderGetConfiguration; internal ICallGateProvider< string >? ProviderGetConfiguration;
internal ICallGateProvider< string, object? >? ProviderPreSettingsDraw; internal ICallGateProvider< string, object? >? ProviderPreSettingsDraw;
internal ICallGateProvider< string, object? >? ProviderPostSettingsDraw; internal ICallGateProvider< string, object? >? ProviderPostSettingsDraw;
@ -116,6 +119,16 @@ public partial class PenumbraIpc
PluginLog.Error( $"Error registering IPC provider for {LabelProviderGetModDirectory}:\n{e}" ); PluginLog.Error( $"Error registering IPC provider for {LabelProviderGetModDirectory}:\n{e}" );
} }
try
{
ProviderModDirectoryChanged = pi.GetIpcProvider< string, bool, object? >( LabelProviderModDirectoryChanged );
Api.ModDirectoryChanged += InvokeModDirectoryChanged;
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderModDirectoryChanged}:\n{e}" );
}
try try
{ {
ProviderGetConfiguration = pi.GetIpcProvider< string >( LabelProviderGetConfiguration ); ProviderGetConfiguration = pi.GetIpcProvider< string >( LabelProviderGetConfiguration );
@ -155,7 +168,17 @@ public partial class PenumbraIpc
ProviderApiVersions?.UnregisterFunc(); ProviderApiVersions?.UnregisterFunc();
Api.PreSettingsPanelDraw -= InvokeSettingsPreDraw; Api.PreSettingsPanelDraw -= InvokeSettingsPreDraw;
Api.PostSettingsPanelDraw -= InvokeSettingsPostDraw; Api.PostSettingsPanelDraw -= InvokeSettingsPostDraw;
Api.ModDirectoryChanged -= InvokeModDirectoryChanged;
} }
private void InvokeSettingsPreDraw( string modDirectory )
=> ProviderPreSettingsDraw!.SendMessage( modDirectory );
private void InvokeSettingsPostDraw( string modDirectory )
=> ProviderPostSettingsDraw!.SendMessage( modDirectory );
private void InvokeModDirectoryChanged( string modDirectory, bool valid )
=> ProviderModDirectoryChanged?.SendMessage( modDirectory, valid );
} }
public partial class PenumbraIpc public partial class PenumbraIpc
@ -239,12 +262,6 @@ public partial class PenumbraIpc
private void OnGameObjectRedrawn( IntPtr objectAddress, int objectTableIndex ) private void OnGameObjectRedrawn( IntPtr objectAddress, int objectTableIndex )
=> ProviderGameObjectRedrawn?.SendMessage( objectAddress, objectTableIndex ); => ProviderGameObjectRedrawn?.SendMessage( objectAddress, objectTableIndex );
private void InvokeSettingsPreDraw( string modDirectory )
=> ProviderPreSettingsDraw!.SendMessage( modDirectory );
private void InvokeSettingsPostDraw( string modDirectory )
=> ProviderPostSettingsDraw!.SendMessage( modDirectory );
private void DisposeRedrawProviders() private void DisposeRedrawProviders()
{ {
ProviderRedrawName?.UnregisterAction(); ProviderRedrawName?.UnregisterAction();

View file

@ -14,7 +14,7 @@ public class CutsceneCharacters : IDisposable
public const int CutsceneSlots = 40; public const int CutsceneSlots = 40;
public const int CutsceneEndIdx = CutsceneStartIdx + CutsceneSlots; public const int CutsceneEndIdx = CutsceneStartIdx + CutsceneSlots;
private readonly short[] _copiedCharacters = Enumerable.Repeat( ( short )-1, ObjectReloader.CutsceneSlots ).ToArray(); private readonly short[] _copiedCharacters = Enumerable.Repeat( ( short )-1, CutsceneSlots ).ToArray();
public IEnumerable< KeyValuePair< int, global::Dalamud.Game.ClientState.Objects.Types.GameObject > > Actors public IEnumerable< KeyValuePair< int, global::Dalamud.Game.ClientState.Objects.Types.GameObject > > Actors
=> Enumerable.Range( CutsceneStartIdx, CutsceneSlots ) => Enumerable.Range( CutsceneStartIdx, CutsceneSlots )

View file

@ -190,7 +190,7 @@ public unsafe partial class PathResolver
242 => Penumbra.Config.UseCharacterCollectionInTryOn ? GetPlayerName() : null, // try-on 242 => Penumbra.Config.UseCharacterCollectionInTryOn ? GetPlayerName() : null, // try-on
243 => Penumbra.Config.UseCharacterCollectionInTryOn ? GetPlayerName() : null, // dye preview 243 => Penumbra.Config.UseCharacterCollectionInTryOn ? GetPlayerName() : null, // dye preview
>= ObjectReloader.CutsceneStartIdx and < ObjectReloader.CutsceneEndIdx => GetCutsceneName( gameObject ), >= CutsceneCharacters.CutsceneStartIdx and < CutsceneCharacters.CutsceneEndIdx => GetCutsceneName( gameObject ),
_ => null, _ => null,
} }

View file

@ -13,6 +13,7 @@ public sealed partial class Mod
public event Action? ModDiscoveryStarted; public event Action? ModDiscoveryStarted;
public event Action? ModDiscoveryFinished; public event Action? ModDiscoveryFinished;
public event Action< string, bool > ModDirectoryChanged;
// Change the mod base directory and discover available mods. // Change the mod base directory and discover available mods.
public void DiscoverMods( string newDir ) public void DiscoverMods( string newDir )
@ -35,6 +36,10 @@ public sealed partial class Mod
{ {
Valid = false; Valid = false;
BasePath = new DirectoryInfo( "." ); BasePath = new DirectoryInfo( "." );
if( Penumbra.Config.ModDirectory != BasePath.FullName )
{
ModDirectoryChanged.Invoke( string.Empty, false );
}
} }
else else
{ {
@ -56,12 +61,18 @@ public sealed partial class Mod
Valid = Directory.Exists( newDir.FullName ); Valid = Directory.Exists( newDir.FullName );
if( Penumbra.Config.ModDirectory != BasePath.FullName ) if( Penumbra.Config.ModDirectory != BasePath.FullName )
{ {
PluginLog.Information( "Set new mod base directory from {OldDirectory:l} to {NewDirectory:l}.", Penumbra.Config.ModDirectory, BasePath.FullName ); ModDirectoryChanged.Invoke( BasePath.FullName, Valid );
Penumbra.Config.ModDirectory = BasePath.FullName; }
}
}
private static void OnModDirectoryChange( string newPath, bool _ )
{
PluginLog.Information( "Set new mod base directory from {OldDirectory:l} to {NewDirectory:l}.",
Penumbra.Config.ModDirectory, newPath );
Penumbra.Config.ModDirectory = newPath;
Penumbra.Config.Save(); Penumbra.Config.Save();
} }
}
}
// Discover new mods. // Discover new mods.
public void DiscoverMods() public void DiscoverMods()

View file

@ -34,6 +34,7 @@ public sealed partial class Mod
public Manager( string modDirectory ) public Manager( string modDirectory )
{ {
ModDirectoryChanged += OnModDirectoryChange;
SetBaseDirectory( modDirectory, true ); SetBaseDirectory( modDirectory, true );
ModOptionChanged += OnModOptionChange; ModOptionChanged += OnModOptionChange;
ModPathChanged += OnModPathChange; ModPathChanged += OnModPathChange;