diff --git a/Penumbra/Interop/MetaFileManager.cs b/Penumbra/Interop/MetaFileManager.cs deleted file mode 100644 index c49efa1e..00000000 --- a/Penumbra/Interop/MetaFileManager.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using Dalamud.Utility.Signatures; -using FFXIVClientStructs.FFXIV.Client.System.Memory; -using Penumbra.GameData; - -namespace Penumbra.Interop; - -public unsafe class MetaFileManager -{ - public MetaFileManager() - { - SignatureHelper.Initialise( this ); - } - - // Allocate in the games space for file storage. - // We only need this if using any meta file. - [Signature( Sigs.GetFileSpace )] - private readonly IntPtr _getFileSpaceAddress = IntPtr.Zero; - - public IMemorySpace* GetFileSpace() - => ( ( delegate* unmanaged< IMemorySpace* > )_getFileSpaceAddress )(); - - public void* AllocateFileMemory( ulong length, ulong alignment = 0 ) - => GetFileSpace()->Malloc( length, alignment ); - - public void* AllocateFileMemory( int length, int alignment = 0 ) - => AllocateFileMemory( ( ulong )length, ( ulong )alignment ); - - public void* AllocateDefaultMemory( ulong length, ulong alignment = 0 ) - => GetFileSpace()->Malloc( length, alignment ); - - public void* AllocateDefaultMemory( int length, int alignment = 0 ) - => IMemorySpace.GetDefaultSpace()->Malloc( ( ulong )length, ( ulong )alignment ); - - public void Free( IntPtr ptr, int length ) - => IMemorySpace.Free( ( void* )ptr, ( ulong )length ); -} \ No newline at end of file diff --git a/Penumbra/Interop/Resolver/CutsceneCharacters.cs b/Penumbra/Interop/Resolver/CutsceneCharacters.cs index 9cf765d0..06b4f228 100644 --- a/Penumbra/Interop/Resolver/CutsceneCharacters.cs +++ b/Penumbra/Interop/Resolver/CutsceneCharacters.cs @@ -4,7 +4,8 @@ using System.Diagnostics; using System.Linq; using Dalamud.Game.ClientState.Objects; using FFXIVClientStructs.FFXIV.Client.Game.Character; - +using Penumbra.Interop.Services; + namespace Penumbra.Interop.Resolver; public class CutsceneCharacters : IDisposable diff --git a/Penumbra/Interop/Resolver/IdentifiedCollectionCache.cs b/Penumbra/Interop/Resolver/IdentifiedCollectionCache.cs index cad29dc0..7135eebb 100644 --- a/Penumbra/Interop/Resolver/IdentifiedCollectionCache.cs +++ b/Penumbra/Interop/Resolver/IdentifiedCollectionCache.cs @@ -5,6 +5,7 @@ using FFXIVClientStructs.FFXIV.Client.Game.Character; using FFXIVClientStructs.FFXIV.Client.Game.Object; using Penumbra.Collections; using Penumbra.GameData.Actors; +using Penumbra.Interop.Services; using Penumbra.Services; namespace Penumbra.Interop.Resolver; diff --git a/Penumbra/Interop/Resolver/PathResolver.Subfiles.cs b/Penumbra/Interop/Resolver/PathResolver.Subfiles.cs index 37059bf6..da976f0b 100644 --- a/Penumbra/Interop/Resolver/PathResolver.Subfiles.cs +++ b/Penumbra/Interop/Resolver/PathResolver.Subfiles.cs @@ -11,6 +11,7 @@ using Penumbra.Collections; using Penumbra.GameData; using Penumbra.GameData.Enums; using Penumbra.Interop.Loader; +using Penumbra.Interop.Services; using Penumbra.Interop.Structs; using Penumbra.String; using Penumbra.String.Classes; diff --git a/Penumbra/Interop/Resolver/PathResolver.cs b/Penumbra/Interop/Resolver/PathResolver.cs index 2d94516d..4050d2f1 100644 --- a/Penumbra/Interop/Resolver/PathResolver.cs +++ b/Penumbra/Interop/Resolver/PathResolver.cs @@ -9,6 +9,7 @@ using OtterGui.Classes; using Penumbra.Collections; using Penumbra.GameData.Enums; using Penumbra.Interop.Loader; +using Penumbra.Interop.Services; using Penumbra.Interop.Structs; using Penumbra.Services; using Penumbra.String; diff --git a/Penumbra/Interop/FontReloader.cs b/Penumbra/Interop/Services/FontReloader.cs similarity index 68% rename from Penumbra/Interop/FontReloader.cs rename to Penumbra/Interop/Services/FontReloader.cs index f7e8af27..51f8abc2 100644 --- a/Penumbra/Interop/FontReloader.cs +++ b/Penumbra/Interop/Services/FontReloader.cs @@ -1,11 +1,13 @@ using FFXIVClientStructs.FFXIV.Client.System.Framework; using FFXIVClientStructs.FFXIV.Component.GUI; using Penumbra.GameData; + +namespace Penumbra.Interop.Services; -namespace Penumbra.Interop; - -// Handle font reloading via game functions. -// May cause a interface flicker while reloading. +/// +/// Handle font reloading via game functions. +/// May cause a interface flicker while reloading. +/// public unsafe class FontReloader { public bool Valid @@ -19,7 +21,7 @@ public unsafe class FontReloader Penumbra.Log.Error("Could not reload fonts, function could not be found."); } - private readonly AtkModule* _atkModule = null!; + private readonly AtkModule* _atkModule = null!; private readonly delegate* unmanaged _reloadFontsFunc = null!; public FontReloader() @@ -36,7 +38,7 @@ public unsafe class FontReloader if (atkModule == null) return; - _atkModule = &atkModule->AtkModule; - _reloadFontsFunc = ((delegate* unmanaged< AtkModule*, bool, bool, void >*)_atkModule->vtbl)[Offsets.ReloadFontsVfunc]; + _atkModule = &atkModule->AtkModule; + _reloadFontsFunc = ((delegate* unmanaged*)_atkModule->vtbl)[Offsets.ReloadFontsVfunc]; } } diff --git a/Penumbra/Interop/GameEventManager.cs b/Penumbra/Interop/Services/GameEventManager.cs similarity index 93% rename from Penumbra/Interop/GameEventManager.cs rename to Penumbra/Interop/Services/GameEventManager.cs index 1080e7b8..e6f84f53 100644 --- a/Penumbra/Interop/GameEventManager.cs +++ b/Penumbra/Interop/Services/GameEventManager.cs @@ -6,8 +6,8 @@ using FFXIVClientStructs.FFXIV.Client.Game.Character; using FFXIVClientStructs.FFXIV.Client.Game.Object; using OtterGui.Log; using Penumbra.Interop.Structs; - -namespace Penumbra.Interop; + +namespace Penumbra.Interop.Services; public unsafe class GameEventManager : IDisposable { @@ -56,7 +56,7 @@ public unsafe class GameEventManager : IDisposable _characterDtorHook.Original(character); } - public delegate void CharacterDestructorEvent(Character* character); + public delegate void CharacterDestructorEvent(Character* character); public event CharacterDestructorEvent? CharacterDestructor; #endregion @@ -89,7 +89,7 @@ public unsafe class GameEventManager : IDisposable return _copyCharacterHook.Original(target, source, unk); } - public delegate void CopyCharacterEvent(Character* target, Character* source); + public delegate void CopyCharacterEvent(Character* target, Character* source); public event CopyCharacterEvent? CopyCharacter; #endregion @@ -121,7 +121,7 @@ public unsafe class GameEventManager : IDisposable return _resourceHandleDestructorHook!.Original(handle); } - public delegate void ResourceHandleDestructorEvent(ResourceHandle* handle); + public delegate void ResourceHandleDestructorEvent(ResourceHandle* handle); public event ResourceHandleDestructorEvent? ResourceHandleDestructor; #endregion diff --git a/Penumbra/Interop/Services/MetaFileManager.cs b/Penumbra/Interop/Services/MetaFileManager.cs new file mode 100644 index 00000000..382a6c84 --- /dev/null +++ b/Penumbra/Interop/Services/MetaFileManager.cs @@ -0,0 +1,37 @@ +using System; +using Dalamud.Utility.Signatures; +using FFXIVClientStructs.FFXIV.Client.System.Memory; +using Penumbra.GameData; + +namespace Penumbra.Interop.Services; + +public unsafe class MetaFileManager +{ + public MetaFileManager() + { + SignatureHelper.Initialise(this); + } + + // Allocate in the games space for file storage. + // We only need this if using any meta file. + [Signature(Sigs.GetFileSpace)] + private readonly IntPtr _getFileSpaceAddress = IntPtr.Zero; + + public IMemorySpace* GetFileSpace() + => ((delegate* unmanaged)_getFileSpaceAddress)(); + + public void* AllocateFileMemory(ulong length, ulong alignment = 0) + => GetFileSpace()->Malloc(length, alignment); + + public void* AllocateFileMemory(int length, int alignment = 0) + => AllocateFileMemory((ulong)length, (ulong)alignment); + + public void* AllocateDefaultMemory(ulong length, ulong alignment = 0) + => GetFileSpace()->Malloc(length, alignment); + + public void* AllocateDefaultMemory(int length, int alignment = 0) + => IMemorySpace.GetDefaultSpace()->Malloc((ulong)length, (ulong)alignment); + + public void Free(IntPtr ptr, int length) + => IMemorySpace.Free((void*)ptr, (ulong)length); +} \ No newline at end of file diff --git a/Penumbra/Interop/ResidentResourceManager.cs b/Penumbra/Interop/Services/ResidentResourceManager.cs similarity index 59% rename from Penumbra/Interop/ResidentResourceManager.cs rename to Penumbra/Interop/Services/ResidentResourceManager.cs index ac732d7c..cd20b889 100644 --- a/Penumbra/Interop/ResidentResourceManager.cs +++ b/Penumbra/Interop/Services/ResidentResourceManager.cs @@ -1,21 +1,21 @@ using Dalamud.Utility.Signatures; using Penumbra.GameData; - -namespace Penumbra.Interop; + +namespace Penumbra.Interop.Services; public unsafe class ResidentResourceManager { // A static pointer to the resident resource manager address. - [Signature( Sigs.ResidentResourceManager, ScanType = ScanType.StaticAddress )] + [Signature(Sigs.ResidentResourceManager, ScanType = ScanType.StaticAddress)] private readonly Structs.ResidentResourceManager** _residentResourceManagerAddress = null; // Some attach and physics files are stored in the resident resource manager, and we need to manually trigger a reload of them to get them to apply. - public delegate void* ResidentResourceDelegate( void* residentResourceManager ); + public delegate void* ResidentResourceDelegate(void* residentResourceManager); - [Signature( Sigs.LoadPlayerResources )] + [Signature(Sigs.LoadPlayerResources)] public readonly ResidentResourceDelegate LoadPlayerResources = null!; - [Signature( Sigs.UnloadPlayerResources )] + [Signature(Sigs.UnloadPlayerResources)] public readonly ResidentResourceDelegate UnloadPlayerResources = null!; public Structs.ResidentResourceManager* Address @@ -23,17 +23,17 @@ public unsafe class ResidentResourceManager public ResidentResourceManager() { - SignatureHelper.Initialise( this ); + SignatureHelper.Initialise(this); } // Reload certain player resources by force. public void Reload() { - if( Address != null && Address->NumResources > 0 ) + if (Address != null && Address->NumResources > 0) { - Penumbra.Log.Debug( "Reload of resident resources triggered." ); - UnloadPlayerResources.Invoke( Address ); - LoadPlayerResources.Invoke( Address ); + Penumbra.Log.Debug("Reload of resident resources triggered."); + UnloadPlayerResources.Invoke(Address); + LoadPlayerResources.Invoke(Address); } } } \ No newline at end of file diff --git a/Penumbra/Mods/Manager/ModOptionChangeType.cs b/Penumbra/Mods/Manager/ModOptionChangeType.cs index b4c4947e..3e6ff5c6 100644 --- a/Penumbra/Mods/Manager/ModOptionChangeType.cs +++ b/Penumbra/Mods/Manager/ModOptionChangeType.cs @@ -22,11 +22,13 @@ public enum ModOptionChangeType public static class ModOptionChangeTypeExtension { - // Give information for each type of change. - // If requiresSaving, collections need to be re-saved after this change. - // If requiresReloading, caches need to be manipulated after this change. - // If wasPrepared, caches have already removed the mod beforehand, then need add it again when this event is fired. - // Otherwise, caches need to reload the mod itself. + /// + /// Give information for each type of change. + /// If requiresSaving, collections need to be re-saved after this change. + /// If requiresReloading, caches need to be manipulated after this change. + /// If wasPrepared, caches have already removed the mod beforehand, then need add it again when this event is fired. + /// Otherwise, caches need to reload the mod itself. + /// public static void HandlingInfo( this ModOptionChangeType type, out bool requiresSaving, out bool requiresReloading, out bool wasPrepared ) { ( requiresSaving, requiresReloading, wasPrepared ) = type switch diff --git a/Penumbra/Penumbra.cs b/Penumbra/Penumbra.cs index e34bad28..563e6de9 100644 --- a/Penumbra/Penumbra.cs +++ b/Penumbra/Penumbra.cs @@ -27,9 +27,10 @@ using Penumbra.Interop.Resolver; using Penumbra.Mods; using CharacterUtility = Penumbra.Interop.CharacterUtility; using DalamudUtil = Dalamud.Utility.Util; -using ResidentResourceManager = Penumbra.Interop.ResidentResourceManager; +using ResidentResourceManager = Penumbra.Interop.Services.ResidentResourceManager; using Penumbra.Services; - +using Penumbra.Interop.Services; + namespace Penumbra; public class Penumbra : IDalamudPlugin diff --git a/Penumbra/PenumbraNew.cs b/Penumbra/PenumbraNew.cs index fc1d5e84..429cd5ae 100644 --- a/Penumbra/PenumbraNew.cs +++ b/Penumbra/PenumbraNew.cs @@ -10,6 +10,7 @@ using Penumbra.GameData.Data; using Penumbra.Interop; using Penumbra.Interop.Loader; using Penumbra.Interop.Resolver; +using Penumbra.Interop.Services; using Penumbra.Services; using Penumbra.UI.Classes; using Penumbra.Util; diff --git a/Penumbra/Services/FilenameService.cs b/Penumbra/Services/FilenameService.cs index 27934da8..0e883149 100644 --- a/Penumbra/Services/FilenameService.cs +++ b/Penumbra/Services/FilenameService.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.IO; using Dalamud.Plugin; using OtterGui.Filesystem; +using Penumbra.Collections; +using Penumbra.Mods; namespace Penumbra.Services; @@ -25,12 +27,24 @@ public class FilenameService ActiveCollectionsFile = Path.Combine(pi.ConfigDirectory.FullName, "active_collections.json"); } + /// Obtain the path of a collection file given its name. Returns an empty string if the collection is temporary. + public string CollectionFile(ModCollection collection) + => collection.Index >= 0 ? Path.Combine(CollectionDirectory, $"{collection.Name.RemoveInvalidPathSymbols()}.json") : string.Empty; + + /// Obtain the path of a collection file given its name. public string CollectionFile(string collectionName) => Path.Combine(CollectionDirectory, $"{collectionName.RemoveInvalidPathSymbols()}.json"); - public string LocalDataFile(string modPath) - => Path.Combine(LocalDataDirectory, $"{modPath}.json"); + /// Obtain the path of the local data file given a mod directory. Returns an empty string if the mod is temporary. + public string LocalDataFile(IModReadable mod) + => mod.IsTemporary ? string.Empty : LocalDataFile(mod.ModPath.FullName); + + /// Obtain the path of the local data file given a mod directory. + public string LocalDataFile(string modDirectory) + => Path.Combine(LocalDataDirectory, $"{Path.GetFileName(modDirectory)}.json"); + + /// Enumerate all collection files. public IEnumerable CollectionFiles { get @@ -40,6 +54,7 @@ public class FilenameService } } + /// Enumerate all local data files. public IEnumerable LocalDataFiles { get @@ -48,4 +63,12 @@ public class FilenameService return directory.Exists ? directory.EnumerateFiles("*.json") : Array.Empty(); } } + + /// Obtain the path of the meta file for a given mod. Returns an empty string if the mod is temporary. + public string ModMetaPath(IModReadable mod) + => mod.IsTemporary ? string.Empty : ModMetaPath(mod.ModPath.FullName); + + /// Obtain the path of the meta file given a mod directory. + public string ModMetaPath(string modDirectory) + => Path.Combine(modDirectory, "meta.json"); } diff --git a/Penumbra/UI/ConfigWindow.SettingsTab.cs b/Penumbra/UI/ConfigWindow.SettingsTab.cs index d4aa093f..e6948019 100644 --- a/Penumbra/UI/ConfigWindow.SettingsTab.cs +++ b/Penumbra/UI/ConfigWindow.SettingsTab.cs @@ -11,7 +11,7 @@ using ImGuiNET; using OtterGui; using OtterGui.Raii; using OtterGui.Widgets; -using Penumbra.Interop; +using Penumbra.Interop.Services; using Penumbra.Services; using Penumbra.UI.Classes; diff --git a/Penumbra/UI/ConfigWindow.cs b/Penumbra/UI/ConfigWindow.cs index 2786a86b..f212feab 100644 --- a/Penumbra/UI/ConfigWindow.cs +++ b/Penumbra/UI/ConfigWindow.cs @@ -7,7 +7,7 @@ using OtterGui; using OtterGui.Raii; using OtterGui.Widgets; using Penumbra.Api.Enums; -using Penumbra.Interop; +using Penumbra.Interop.Services; using Penumbra.Mods; using Penumbra.Services; using Penumbra.UI.Classes; @@ -35,7 +35,7 @@ public sealed partial class ConfigWindow : Window, IDisposable public void SelectMod(Mod mod) => _selector.SelectByValue(mod); - + public ConfigWindow(CommunicatorService communicator, StartTracker timer, FontReloader fontReloader, Penumbra penumbra, ResourceWatcher watcher) : base(GetLabel()) {