From c423ce1d47322624eb593e01ec3780b4812ab4da Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Fri, 12 Sep 2025 11:34:07 +0200 Subject: [PATCH] Get rid of OtterGui event wrappers. --- Luna | 2 +- Penumbra/Api/Api/GameStateApi.cs | 31 ++-- Penumbra/Api/Api/ModSettingsApi.cs | 25 ++- Penumbra/Api/Api/ModsApi.cs | 45 +++--- Penumbra/Api/Api/PluginStateApi.cs | 44 +++-- Penumbra/Api/Api/UiApi.cs | 67 ++++---- Penumbra/Api/DalamudSubstitutionProvider.cs | 33 ++-- Penumbra/Api/TempModManager.cs | 18 ++- Penumbra/Collections/Cache/CollectionCache.cs | 4 +- .../Cache/CollectionCacheManager.cs | 152 +++++++++--------- .../Collections/Manager/ActiveCollections.cs | 34 ++-- .../Collections/Manager/CollectionEditor.cs | 7 +- .../Collections/Manager/CollectionStorage.cs | 41 +++-- .../Collections/Manager/InheritanceManager.cs | 18 +-- .../Manager/TempCollectionManager.cs | 10 +- Penumbra/Communication/ChangedItemClick.cs | 18 +-- Penumbra/Communication/ChangedItemHover.cs | 17 +- .../Communication/CharacterUtilityFinished.cs | 8 +- Penumbra/Communication/CollectionChange.cs | 28 ++-- .../CollectionInheritanceChanged.cs | 11 +- .../Communication/CreatedCharacterBase.cs | 22 +-- .../Communication/CreatingCharacterBase.cs | 26 +-- Penumbra/Communication/EnabledChanged.cs | 19 +-- Penumbra/Communication/ModDataChanged.cs | 18 +-- Penumbra/Communication/ModDirectoryChanged.cs | 18 +-- .../Communication/ModDiscoveryFinished.cs | 4 +- Penumbra/Communication/ModDiscoveryStarted.cs | 4 +- Penumbra/Communication/ModFileChanged.cs | 18 +-- Penumbra/Communication/ModOptionChanged.cs | 33 ++-- Penumbra/Communication/ModPathChanged.cs | 24 ++- Penumbra/Communication/ModSettingChanged.cs | 33 ++-- Penumbra/Communication/MtrlLoaded.cs | 18 ++- Penumbra/Communication/PcpCreation.cs | 22 +-- Penumbra/Communication/PcpParsing.cs | 23 +-- Penumbra/Communication/PostEnabledDraw.cs | 16 +- .../Communication/PostSettingsPanelDraw.cs | 16 +- .../Communication/PreSettingsPanelDraw.cs | 16 +- .../Communication/PreSettingsTabBarDraw.cs | 23 ++- Penumbra/Communication/ResolvedFileChanged.cs | 33 ++-- Penumbra/Communication/SelectTab.cs | 17 +- .../Communication/TemporaryGlobalModChange.cs | 20 +-- Penumbra/EphemeralConfig.cs | 7 +- .../Hooks/Objects/CharacterBaseDestructor.cs | 16 +- .../Hooks/Objects/CharacterDestructor.cs | 15 +- .../Objects/ConstructCutsceneCharacter.cs | 15 +- .../Interop/Hooks/Objects/CopyCharacter.cs | 30 ++-- .../Hooks/Objects/CreateCharacterBase.cs | 50 ++++-- .../Interop/Hooks/Objects/WeaponReload.cs | 41 +++-- .../Hooks/PostProcessing/AttributeHook.cs | 12 +- .../PostProcessing/ShaderReplacementFixer.cs | 26 +-- .../Hooks/ResourceLoading/ResourceLoader.cs | 4 +- Penumbra/Interop/Hooks/Resources/LoadMtrl.cs | 3 +- .../Resources/ResourceHandleDestructor.cs | 15 +- .../Interop/PathResolving/CutsceneService.cs | 22 +-- .../Interop/PathResolving/DrawObjectState.cs | 32 ++-- .../IdentifiedCollectionCache.cs | 9 +- Penumbra/Interop/PathResolving/MetaState.cs | 20 +-- .../Interop/PathResolving/SubfileHelper.cs | 4 +- Penumbra/Interop/Services/CharacterUtility.cs | 10 +- Penumbra/Interop/Services/RedrawService.cs | 2 +- .../SchedulerResourceManagementService.cs | 14 +- Penumbra/Meta/ShapeAttributeManager.cs | 19 ++- Penumbra/Mods/Editor/DuplicateManager.cs | 2 +- Penumbra/Mods/Editor/ModFileEditor.cs | 3 +- Penumbra/Mods/Editor/ModMerger.cs | 17 +- Penumbra/Mods/Editor/ModNormalizer.cs | 1 - Penumbra/Mods/ItemSwap/ItemSwapContainer.cs | 2 +- Penumbra/Mods/Manager/ModCacheManager.cs | 37 ++--- Penumbra/Mods/Manager/ModDataEditor.cs | 35 ++-- Penumbra/Mods/Manager/ModExportManager.cs | 11 +- Penumbra/Mods/Manager/ModFileSystem.cs | 18 +-- Penumbra/Mods/Manager/ModManager.cs | 31 ++-- .../OptionEditor/CombiningModGroupEditor.cs | 4 +- .../Manager/OptionEditor/ImcModGroupEditor.cs | 26 +-- .../Manager/OptionEditor/ModGroupEditor.cs | 34 ++-- .../Manager/OptionEditor/ModOptionEditor.cs | 14 +- .../OptionEditor/MultiModGroupEditor.cs | 9 +- .../OptionEditor/SingleModGroupEditor.cs | 9 +- Penumbra/Mods/ModSelection.cs | 27 ++-- Penumbra/Penumbra.cs | 35 ++-- Penumbra/Services/BackupService.cs | 38 +---- Penumbra/Services/CommunicatorService.cs | 89 ++++------ Penumbra/Services/CrashHandlerService.cs | 8 +- Penumbra/Services/FilenameService.cs | 14 +- Penumbra/Services/PcpService.cs | 20 +-- Penumbra/Services/SaveService.cs | 1 - Penumbra/UI/AdvancedWindow/FileEditor.cs | 3 +- Penumbra/UI/AdvancedWindow/ItemSwapTab.cs | 66 ++++---- .../Materials/MtrlTab.LivePreview.cs | 8 +- .../AdvancedWindow/ModEditWindow.Textures.cs | 3 +- Penumbra/UI/AdvancedWindow/ModEditWindow.cs | 6 +- .../UI/AdvancedWindow/ResourceTreeViewer.cs | 3 +- Penumbra/UI/ChangedItemDrawer.cs | 5 +- .../UI/CollectionTab/CollectionSelector.cs | 14 +- .../CollectionTab/IndividualAssignmentUi.cs | 4 +- Penumbra/UI/FileDialogService.cs | 8 +- Penumbra/UI/ModsTab/ModFileSystemSelector.cs | 21 ++- Penumbra/UI/ModsTab/ModPanel.cs | 10 +- Penumbra/UI/ModsTab/ModPanelHeader.cs | 6 +- Penumbra/UI/ModsTab/ModPanelSettingsTab.cs | 9 +- .../UI/ResourceWatcher/ResourceWatcher.cs | 8 +- Penumbra/UI/Tabs/ChangedItemsTab.cs | 3 +- Penumbra/UI/Tabs/ConfigTabBar.cs | 10 +- 103 files changed, 1050 insertions(+), 1024 deletions(-) diff --git a/Luna b/Luna index ece206ed..f39b5143 160000 --- a/Luna +++ b/Luna @@ -1 +1 @@ -Subproject commit ece206edc96bc39844e4c6c314dd562fe1b1db55 +Subproject commit f39b514304d8f30030310f75d83f99385105c271 diff --git a/Penumbra/Api/Api/GameStateApi.cs b/Penumbra/Api/Api/GameStateApi.cs index 248842da..a7a1f4bb 100644 --- a/Penumbra/Api/Api/GameStateApi.cs +++ b/Penumbra/Api/Api/GameStateApi.cs @@ -1,6 +1,7 @@ using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using Penumbra.Api.Enums; using Penumbra.Collections; +using Penumbra.Communication; using Penumbra.Interop.Hooks.ResourceLoading; using Penumbra.Interop.PathResolving; using Penumbra.Interop.Structs; @@ -28,36 +29,24 @@ public class GameStateApi : IPenumbraApiGameState, Luna.IApiService, IDisposable _resourceLoader.ResourceLoaded += OnResourceLoaded; _resourceLoader.PapRequested += OnPapRequested; _communicator.CreatedCharacterBase.Subscribe(OnCreatedCharacterBase, Communication.CreatedCharacterBase.Priority.Api); + _communicator.CreatingCharacterBase.Subscribe(OnCreatingCharacterBase, Communication.CreatingCharacterBase.Priority.Api); } + private void OnCreatingCharacterBase(in CreatingCharacterBase.Arguments arguments) + => CreatingCharacterBase?.Invoke(arguments.GameObject.Address, arguments.Collection.Identity.Id, arguments.ModelCharaId, arguments.Customize, + arguments.EquipData); + public unsafe void Dispose() { _resourceLoader.ResourceLoaded -= OnResourceLoaded; _resourceLoader.PapRequested -= OnPapRequested; _communicator.CreatedCharacterBase.Unsubscribe(OnCreatedCharacterBase); + _communicator.CreatingCharacterBase.Unsubscribe(OnCreatingCharacterBase); } public event CreatedCharacterBaseDelegate? CreatedCharacterBase; public event GameObjectResourceResolvedDelegate? GameObjectResourceResolved; - - public event CreatingCharacterBaseDelegate? CreatingCharacterBase - { - add - { - if (value == null) - return; - - _communicator.CreatingCharacterBase.Subscribe(new Action(value), - Communication.CreatingCharacterBase.Priority.Api); - } - remove - { - if (value == null) - return; - - _communicator.CreatingCharacterBase.Unsubscribe(new Action(value)); - } - } + public event CreatingCharacterBaseDelegate? CreatingCharacterBase; public unsafe (nint GameObject, (Guid Id, string Name) Collection) GetDrawObjectInfo(nint drawObject) { @@ -117,6 +106,6 @@ public class GameStateApi : IPenumbraApiGameState, Luna.IApiService, IDisposable } } - private void OnCreatedCharacterBase(nint gameObject, ModCollection collection, nint drawObject) - => CreatedCharacterBase?.Invoke(gameObject, collection.Identity.Id, drawObject); + private void OnCreatedCharacterBase(in CreatedCharacterBase.Arguments arguments) + => CreatedCharacterBase?.Invoke(arguments.GameObject, arguments.Collection.Identity.Id, arguments.DrawObject); } diff --git a/Penumbra/Api/Api/ModSettingsApi.cs b/Penumbra/Api/Api/ModSettingsApi.cs index e0c0df17..c8b7efa4 100644 --- a/Penumbra/Api/Api/ModSettingsApi.cs +++ b/Penumbra/Api/Api/ModSettingsApi.cs @@ -6,12 +6,10 @@ using Penumbra.Collections.Manager; using Penumbra.Communication; using Penumbra.Interop.PathResolving; using Penumbra.Mods; -using Penumbra.Mods.Editor; using Penumbra.Mods.Groups; using Penumbra.Mods.Manager; using Penumbra.Mods.Manager.OptionEditor; using Penumbra.Mods.Settings; -using Penumbra.Mods.SubMods; using Penumbra.Services; namespace Penumbra.Api.Api; @@ -264,19 +262,18 @@ public class ModSettingsApi : IPenumbraApiModSettings, IApiService, IDisposable ModSettingChanged?.Invoke(ModSettingChange.Edited, collection.Identity.Id, mod.Identifier, parent != collection); } - private void OnModPathChange(ModPathChangeType type, Mod mod, DirectoryInfo? _1, DirectoryInfo? _2) + private void OnModPathChange(in ModPathChanged.Arguments arguments) { - if (type == ModPathChangeType.Reloaded) - TriggerSettingEdited(mod); + if (arguments.Type is ModPathChangeType.Reloaded) + TriggerSettingEdited(arguments.Mod); } - private void OnModSettingChange(ModCollection collection, ModSettingChange type, Mod? mod, Setting _1, int _2, bool inherited) - => ModSettingChanged?.Invoke(type, collection.Identity.Id, mod?.ModPath.Name ?? string.Empty, inherited); + private void OnModSettingChange(in ModSettingChanged.Arguments arguments) + => ModSettingChanged?.Invoke(arguments.Type, arguments.Collection.Identity.Id, arguments.Mod?.Identifier ?? string.Empty, arguments.Inherited); - private void OnModOptionEdited(ModOptionChangeType type, Mod mod, IModGroup? group, IModOption? option, IModDataContainer? container, - int moveIndex) + private void OnModOptionEdited(in ModOptionChanged.Arguments arguments) { - switch (type) + switch (arguments.Type) { case ModOptionChangeType.GroupDeleted: case ModOptionChangeType.GroupMoved: @@ -288,17 +285,17 @@ public class ModSettingsApi : IPenumbraApiModSettings, IApiService, IDisposable case ModOptionChangeType.OptionFilesAdded: case ModOptionChangeType.OptionSwapsChanged: case ModOptionChangeType.OptionMetaChanged: - TriggerSettingEdited(mod); + TriggerSettingEdited(arguments.Mod); break; } } - private void OnModFileChanged(Mod mod, FileRegistry file) + private void OnModFileChanged(in ModFileChanged.Arguments arguments) { - if (file.CurrentUsage == 0) + if (arguments.File.CurrentUsage == 0) return; - TriggerSettingEdited(mod); + TriggerSettingEdited(arguments.Mod); } public static PenumbraApiEc ConvertModSetting(Mod mod, string groupName, IReadOnlyList optionNames, out int groupIndex, diff --git a/Penumbra/Api/Api/ModsApi.cs b/Penumbra/Api/Api/ModsApi.cs index 4bd78339..fecfb916 100644 --- a/Penumbra/Api/Api/ModsApi.cs +++ b/Penumbra/Api/Api/ModsApi.cs @@ -2,7 +2,6 @@ using Luna; using Newtonsoft.Json.Linq; using Penumbra.Api.Enums; using Penumbra.Communication; -using Penumbra.Mods; using Penumbra.Mods.Manager; using Penumbra.Services; @@ -29,16 +28,24 @@ public class ModsApi : IPenumbraApiMods, IApiService, IDisposable _migrationManager = migrationManager; _log = log; _communicator.ModPathChanged.Subscribe(OnModPathChanged, ModPathChanged.Priority.ApiMods); + _communicator.PcpCreation.Subscribe(OnPcpCreation, PcpCreation.Priority.ApiMods); + _communicator.PcpParsing.Subscribe(OnPcpParsing, PcpParsing.Priority.ApiMods); } - private void OnModPathChanged(ModPathChangeType type, Mod mod, DirectoryInfo? oldDirectory, DirectoryInfo? newDirectory) + private void OnPcpParsing(in PcpParsing.Arguments arguments) + => ParsingPcp?.Invoke(arguments.JObject, arguments.Mod.Identifier, arguments.Collection?.Identity.Id ?? Guid.Empty); + + private void OnPcpCreation(in PcpCreation.Arguments arguments) + => CreatingPcp?.Invoke(arguments.JObject, arguments.ObjectIndex, arguments.DirectoryPath); + + private void OnModPathChanged(in ModPathChanged.Arguments arguments) { - switch (type) + switch (arguments.Type) { - case ModPathChangeType.Deleted when oldDirectory != null: ModDeleted?.Invoke(oldDirectory.Name); break; - case ModPathChangeType.Added when newDirectory != null: ModAdded?.Invoke(newDirectory.Name); break; - case ModPathChangeType.Moved when newDirectory != null && oldDirectory != null: - ModMoved?.Invoke(oldDirectory.Name, newDirectory.Name); + case ModPathChangeType.Deleted when arguments.OldDirectory is not null: ModDeleted?.Invoke(arguments.OldDirectory.Name); break; + case ModPathChangeType.Added when arguments.NewDirectory is not null: ModAdded?.Invoke(arguments.NewDirectory.Name); break; + case ModPathChangeType.Moved when arguments is { NewDirectory: not null, OldDirectory: not null }: + ModMoved?.Invoke(arguments.OldDirectory.Name, arguments.NewDirectory.Name); break; } } @@ -46,6 +53,8 @@ public class ModsApi : IPenumbraApiMods, IApiService, IDisposable public void Dispose() { _communicator.ModPathChanged.Unsubscribe(OnModPathChanged); + _communicator.PcpCreation.Unsubscribe(OnPcpCreation); + _communicator.PcpParsing.Unsubscribe(OnPcpParsing); } public Dictionary GetModList() @@ -105,21 +114,11 @@ public class ModsApi : IPenumbraApiMods, IApiService, IDisposable return ApiHelpers.Return(PenumbraApiEc.Success, ApiHelpers.Args("ModDirectory", modDirectory, "ModName", modName)); } - public event Action? ModDeleted; - public event Action? ModAdded; - public event Action? ModMoved; - - public event Action? CreatingPcp - { - add => _communicator.PcpCreation.Subscribe(value!, PcpCreation.Priority.ModsApi); - remove => _communicator.PcpCreation.Unsubscribe(value!); - } - - public event Action? ParsingPcp - { - add => _communicator.PcpParsing.Subscribe(value!, PcpParsing.Priority.ModsApi); - remove => _communicator.PcpParsing.Unsubscribe(value!); - } + public event Action? ModDeleted; + public event Action? ModAdded; + public event Action? ModMoved; + public event Action? CreatingPcp; + public event Action? ParsingPcp; public (PenumbraApiEc, string, bool, bool) GetModPath(string modDirectory, string modName) { @@ -155,7 +154,7 @@ public class ModsApi : IPenumbraApiMods, IApiService, IDisposable public Dictionary GetChangedItems(string modDirectory, string modName) => _modManager.TryGetMod(modDirectory, modName, out var mod) - ? mod.ChangedItems.ToDictionary(kvp => kvp.Key, kvp => kvp.Value?.ToInternalObject()) + ? mod.ChangedItems.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.ToInternalObject()) : []; public IReadOnlyDictionary> GetChangedItemAdapterDictionary() diff --git a/Penumbra/Api/Api/PluginStateApi.cs b/Penumbra/Api/Api/PluginStateApi.cs index b0a75fce..505b1a2c 100644 --- a/Penumbra/Api/Api/PluginStateApi.cs +++ b/Penumbra/Api/Api/PluginStateApi.cs @@ -1,4 +1,5 @@ using System.Collections.Frozen; +using Luna; using Newtonsoft.Json; using Penumbra.Communication; using Penumbra.Mods; @@ -6,32 +7,47 @@ using Penumbra.Services; namespace Penumbra.Api.Api; -public class PluginStateApi(Configuration config, CommunicatorService communicator) : IPenumbraApiPluginState, Luna.IApiService +public class PluginStateApi : IPenumbraApiPluginState, IApiService, IDisposable { + private readonly Configuration _config; + private readonly CommunicatorService _communicator; + + public PluginStateApi(Configuration config, CommunicatorService communicator) + { + _config = config; + _communicator = communicator; + _communicator.ModDirectoryChanged.Subscribe(OnModDirectoryChanged, Communication.ModDirectoryChanged.Priority.Api); + _communicator.EnabledChanged.Subscribe(OnEnabledChanged, EnabledChanged.Priority.Api); + } + + private void OnEnabledChanged(in EnabledChanged.Arguments arguments) + => EnabledChange?.Invoke(arguments.Enabled); + + private void OnModDirectoryChanged(in ModDirectoryChanged.Arguments arguments) + => ModDirectoryChanged?.Invoke(arguments.Directory, arguments.Valid); + public string GetModDirectory() - => config.ModDirectory; + => _config.ModDirectory; public string GetConfiguration() - => JsonConvert.SerializeObject(config, Formatting.Indented); + => JsonConvert.SerializeObject(_config, Formatting.Indented); - public event Action? ModDirectoryChanged - { - add => communicator.ModDirectoryChanged.Subscribe(value!, Communication.ModDirectoryChanged.Priority.Api); - remove => communicator.ModDirectoryChanged.Unsubscribe(value!); - } + public event Action? ModDirectoryChanged; public bool GetEnabledState() - => config.EnableMods; + => _config.EnableMods; - public event Action? EnabledChange - { - add => communicator.EnabledChanged.Subscribe(value!, EnabledChanged.Priority.Api); - remove => communicator.EnabledChanged.Unsubscribe(value!); - } + public event Action? EnabledChange; public FrozenSet SupportedFeatures => FeatureChecker.SupportedFeatures.ToFrozenSet(); public string[] CheckSupportedFeatures(IEnumerable requiredFeatures) => requiredFeatures.Where(f => !FeatureChecker.Supported(f)).ToArray(); + + public void Dispose() + { + _communicator.ModDirectoryChanged.Unsubscribe(OnModDirectoryChanged); + _communicator.EnabledChanged.Unsubscribe(OnEnabledChanged); + } } diff --git a/Penumbra/Api/Api/UiApi.cs b/Penumbra/Api/Api/UiApi.cs index 74f8f1cf..f776990b 100644 --- a/Penumbra/Api/Api/UiApi.cs +++ b/Penumbra/Api/Api/UiApi.cs @@ -1,6 +1,6 @@ +using FFXIVClientStructs.FFXIV.Common.Lua; using Penumbra.Api.Enums; using Penumbra.Communication; -using Penumbra.GameData.Data; using Penumbra.Mods.Manager; using Penumbra.Services; using Penumbra.UI; @@ -20,41 +20,40 @@ public class UiApi : IPenumbraApiUi, Luna.IApiService, IDisposable _modManager = modManager; _communicator.ChangedItemHover.Subscribe(OnChangedItemHover, ChangedItemHover.Priority.Default); _communicator.ChangedItemClick.Subscribe(OnChangedItemClick, ChangedItemClick.Priority.Default); + _communicator.PreSettingsTabBarDraw.Subscribe(OnPreSettingsTabBarDraw, Communication.PreSettingsTabBarDraw.Priority.Default); + _communicator.PreSettingsPanelDraw.Subscribe(OnPreSettingsPanelDraw, Communication.PreSettingsPanelDraw.Priority.Default); + _communicator.PostEnabledDraw.Subscribe(OnPostEnabledDraw, Communication.PostEnabledDraw.Priority.Default); + _communicator.PostSettingsPanelDraw.Subscribe(OnPostSettingsPanelDraw, Communication.PostSettingsPanelDraw.Priority.Default); } + private void OnPostSettingsPanelDraw(in PostSettingsPanelDraw.Arguments arguments) + => PostSettingsPanelDraw?.Invoke(arguments.Mod.Identifier); + + private void OnPostEnabledDraw(in PostEnabledDraw.Arguments arguments) + => PostEnabledDraw?.Invoke(arguments.Mod.Identifier); + + private void OnPreSettingsPanelDraw(in PreSettingsPanelDraw.Arguments arguments) + => PreSettingsPanelDraw?.Invoke(arguments.Mod.Identifier); + + private void OnPreSettingsTabBarDraw(in PreSettingsTabBarDraw.Arguments arguments) + => PreSettingsTabBarDraw?.Invoke(arguments.Mod.Identifier, arguments.HeaderWidth, arguments.TitleBoxWidth); + public void Dispose() { _communicator.ChangedItemHover.Unsubscribe(OnChangedItemHover); _communicator.ChangedItemClick.Unsubscribe(OnChangedItemClick); + _communicator.PreSettingsTabBarDraw.Unsubscribe(OnPreSettingsTabBarDraw); + _communicator.PreSettingsPanelDraw.Unsubscribe(OnPreSettingsPanelDraw); + _communicator.PostEnabledDraw.Unsubscribe(OnPostEnabledDraw); + _communicator.PostSettingsPanelDraw.Unsubscribe(OnPostSettingsPanelDraw); } - public event Action? ChangedItemTooltip; - + public event Action? ChangedItemTooltip; public event Action? ChangedItemClicked; - - public event Action? PreSettingsTabBarDraw - { - add => _communicator.PreSettingsTabBarDraw.Subscribe(value!, Communication.PreSettingsTabBarDraw.Priority.Default); - remove => _communicator.PreSettingsTabBarDraw.Unsubscribe(value!); - } - - public event Action? PreSettingsPanelDraw - { - add => _communicator.PreSettingsPanelDraw.Subscribe(value!, Communication.PreSettingsPanelDraw.Priority.Default); - remove => _communicator.PreSettingsPanelDraw.Unsubscribe(value!); - } - - public event Action? PostEnabledDraw - { - add => _communicator.PostEnabledDraw.Subscribe(value!, Communication.PostEnabledDraw.Priority.Default); - remove => _communicator.PostEnabledDraw.Unsubscribe(value!); - } - - public event Action? PostSettingsPanelDraw - { - add => _communicator.PostSettingsPanelDraw.Subscribe(value!, Communication.PostSettingsPanelDraw.Priority.Default); - remove => _communicator.PostSettingsPanelDraw.Unsubscribe(value!); - } + public event Action? PreSettingsTabBarDraw; + public event Action? PreSettingsPanelDraw; + public event Action? PostEnabledDraw; + public event Action? PostSettingsPanelDraw; public PenumbraApiEc OpenMainWindow(TabType tab, string modDirectory, string modName) { @@ -65,13 +64,13 @@ public class UiApi : IPenumbraApiUi, Luna.IApiService, IDisposable if (tab == TabType.Mods && (modDirectory.Length > 0 || modName.Length > 0)) { if (_modManager.TryGetMod(modDirectory, modName, out var mod)) - _communicator.SelectTab.Invoke(tab, mod); + _communicator.SelectTab.Invoke(new SelectTab.Arguments(tab, mod)); else return PenumbraApiEc.ModMissing; } else if (tab != TabType.None) { - _communicator.SelectTab.Invoke(tab, null); + _communicator.SelectTab.Invoke(new SelectTab.Arguments(tab, null)); } return PenumbraApiEc.Success; @@ -80,21 +79,21 @@ public class UiApi : IPenumbraApiUi, Luna.IApiService, IDisposable public void CloseMainWindow() => _configWindow.IsOpen = false; - private void OnChangedItemClick(MouseButton button, IIdentifiedObjectData data) + private void OnChangedItemClick(in ChangedItemClick.Arguments arguments) { if (ChangedItemClicked == null) return; - var (type, id) = data.ToApiObject(); - ChangedItemClicked.Invoke(button, type, id); + var (type, id) = arguments.Data.ToApiObject(); + ChangedItemClicked.Invoke(arguments.Button, type, id); } - private void OnChangedItemHover(IIdentifiedObjectData data) + private void OnChangedItemHover(in ChangedItemHover.Arguments arguments) { if (ChangedItemTooltip == null) return; - var (type, id) = data.ToApiObject(); + var (type, id) = arguments.Data.ToApiObject(); ChangedItemTooltip.Invoke(type, id); } } diff --git a/Penumbra/Api/DalamudSubstitutionProvider.cs b/Penumbra/Api/DalamudSubstitutionProvider.cs index 1165824d..0062355b 100644 --- a/Penumbra/Api/DalamudSubstitutionProvider.cs +++ b/Penumbra/Api/DalamudSubstitutionProvider.cs @@ -1,9 +1,7 @@ using Dalamud.Interface; using Dalamud.Plugin.Services; -using Penumbra.Collections; using Penumbra.Collections.Manager; using Penumbra.Communication; -using Penumbra.Mods.Editor; using Penumbra.Services; using Penumbra.String.Classes; @@ -74,42 +72,41 @@ public class DalamudSubstitutionProvider : IDisposable, Luna.IApiService public void Dispose() => Unsubscribe(); - private void OnCollectionChange(CollectionType type, ModCollection? oldCollection, ModCollection? newCollection, string _) + private void OnCollectionChange(in CollectionChange.Arguments arguments) { - if (type is not CollectionType.Interface) + if (arguments.Type is not CollectionType.Interface) return; - var enumerable = oldCollection?.ResolvedFiles.Keys ?? Array.Empty().AsEnumerable(); - enumerable = enumerable.Concat(newCollection?.ResolvedFiles.Keys ?? Array.Empty().AsEnumerable()); + var enumerable = arguments.OldCollection?.ResolvedFiles.Keys ?? Array.Empty().AsEnumerable(); + enumerable = enumerable.Concat(arguments.NewCollection?.ResolvedFiles.Keys ?? Array.Empty().AsEnumerable()); ResetSubstitutions(enumerable); } - private void OnResolvedFileChange(ModCollection collection, ResolvedFileChanged.Type type, Utf8GamePath key, FullPath _1, FullPath _2, - IMod? _3) + private void OnResolvedFileChange(in ResolvedFileChanged.Arguments arguments) { - if (_activeCollectionData.Interface != collection) + if (_activeCollectionData.Interface != arguments.Collection) return; - switch (type) + switch (arguments.Type) { case ResolvedFileChanged.Type.Added: case ResolvedFileChanged.Type.Removed: case ResolvedFileChanged.Type.Replaced: - ResetSubstitutions([key]); + ResetSubstitutions([arguments.GamePath]); break; case ResolvedFileChanged.Type.FullRecomputeStart: case ResolvedFileChanged.Type.FullRecomputeFinished: - ResetSubstitutions(collection.ResolvedFiles.Keys); + ResetSubstitutions(arguments.Collection.ResolvedFiles.Keys); break; } } - private void OnEnabledChange(bool state) + private void OnEnabledChange(in EnabledChanged.Arguments arguments) { - if (state) - OnCollectionChange(CollectionType.Interface, null, _activeCollectionData.Interface, string.Empty); + if (arguments.Enabled) + OnCollectionChange(new CollectionChange.Arguments(CollectionType.Interface, null, _activeCollectionData.Interface, string.Empty)); else - OnCollectionChange(CollectionType.Interface, _activeCollectionData.Interface, null, string.Empty); + OnCollectionChange(new CollectionChange.Arguments(CollectionType.Interface, _activeCollectionData.Interface, null, string.Empty)); } private void Substitute(string path, ref string? replacementPath) @@ -146,7 +143,7 @@ public class DalamudSubstitutionProvider : IDisposable, Luna.IApiService _communicator.CollectionChange.Subscribe(OnCollectionChange, CollectionChange.Priority.DalamudSubstitutionProvider); _communicator.ResolvedFileChanged.Subscribe(OnResolvedFileChange, ResolvedFileChanged.Priority.DalamudSubstitutionProvider); _communicator.EnabledChanged.Subscribe(OnEnabledChange, EnabledChanged.Priority.DalamudSubstitutionProvider); - OnCollectionChange(CollectionType.Interface, null, _activeCollectionData.Interface, string.Empty); + OnCollectionChange(new CollectionChange.Arguments(CollectionType.Interface, null, _activeCollectionData.Interface, string.Empty)); } private void Unsubscribe() @@ -155,6 +152,6 @@ public class DalamudSubstitutionProvider : IDisposable, Luna.IApiService _communicator.CollectionChange.Unsubscribe(OnCollectionChange); _communicator.ResolvedFileChanged.Unsubscribe(OnResolvedFileChange); _communicator.EnabledChanged.Unsubscribe(OnEnabledChange); - OnCollectionChange(CollectionType.Interface, _activeCollectionData.Interface, null, string.Empty); + OnCollectionChange(new CollectionChange.Arguments(CollectionType.Interface, _activeCollectionData.Interface, null, string.Empty)); } } diff --git a/Penumbra/Api/TempModManager.cs b/Penumbra/Api/TempModManager.cs index a8b6308c..675d2e57 100644 --- a/Penumbra/Api/TempModManager.cs +++ b/Penumbra/Api/TempModManager.cs @@ -86,19 +86,20 @@ public class TempModManager : IDisposable, Luna.IService { Penumbra.Log.Verbose($"Removing temporary Mod {mod.Name} from {collection.Identity.AnonymizedName}."); collection.Remove(mod); - _communicator.ModSettingChanged.Invoke(collection, ModSettingChange.TemporaryMod, null, Setting.False, 0, false); + _communicator.ModSettingChanged.Invoke(new ModSettingChanged.Arguments(ModSettingChange.TemporaryMod, collection, null, Setting.False, 0, false)); } else { - Penumbra.Log.Verbose($"Adding {(created ? "new " : string.Empty)}temporary Mod {mod.Name} to {collection.Identity.AnonymizedName}."); + Penumbra.Log.Verbose( + $"Adding {(created ? "new " : string.Empty)}temporary Mod {mod.Name} to {collection.Identity.AnonymizedName}."); collection.Apply(mod, created); - _communicator.ModSettingChanged.Invoke(collection, ModSettingChange.TemporaryMod, null, Setting.True, 0, false); + _communicator.ModSettingChanged.Invoke(new ModSettingChanged.Arguments(ModSettingChange.TemporaryMod, collection, null, Setting.True, 0, false)); } } else { Penumbra.Log.Verbose($"Triggering global mod change for {(created ? "new " : string.Empty)}temporary Mod {mod.Name}."); - _communicator.TemporaryGlobalModChange.Invoke(mod, created, removed); + _communicator.TemporaryGlobalModChange.Invoke(new TemporaryGlobalModChange.Arguments(mod, created, removed)); } } @@ -153,10 +154,11 @@ public class TempModManager : IDisposable, Luna.IService return mod; } - private void OnCollectionChange(CollectionType collectionType, ModCollection? oldCollection, ModCollection? newCollection, - string _) + private void OnCollectionChange(in CollectionChange.Arguments arguments) { - if (collectionType is CollectionType.Temporary or CollectionType.Inactive && newCollection == null && oldCollection != null) - _mods.Remove(oldCollection); + if (arguments.Type is CollectionType.Temporary or CollectionType.Inactive + && arguments.NewCollection is null + && arguments.OldCollection is not null) + _mods.Remove(arguments.OldCollection); } } diff --git a/Penumbra/Collections/Cache/CollectionCache.cs b/Penumbra/Collections/Cache/CollectionCache.cs index 90cbb9dc..a4fb92ac 100644 --- a/Penumbra/Collections/Cache/CollectionCache.cs +++ b/Penumbra/Collections/Cache/CollectionCache.cs @@ -188,7 +188,7 @@ public sealed class CollectionCache : IDisposable Penumbra.Log.Warning( $"Invalid mod state, removing {mod.Name} and associated file {path} returned current mod {mp.Mod.Name}."); else - _manager.ResolvedFileChanged.Invoke(_collection, ResolvedFileChanged.Type.Removed, path, FullPath.Empty, mp.Path, mp.Mod); + _manager.ResolvedFileChanged.Invoke(new ResolvedFileChanged.Arguments(ResolvedFileChanged.Type.Removed, _collection, path, FullPath.Empty, mp.Path, mp.Mod)); } } @@ -275,7 +275,7 @@ public sealed class CollectionCache : IDisposable FullPath old, IMod? mod) { if (Calculating == -1) - _manager.ResolvedFileChanged.Invoke(collection, type, key, value, old, mod); + _manager.ResolvedFileChanged.Invoke(new ResolvedFileChanged.Arguments(type, collection, key, value, old, mod)); } private static bool IsRedirectionSupported(Utf8GamePath path, IMod mod) diff --git a/Penumbra/Collections/Cache/CollectionCacheManager.cs b/Penumbra/Collections/Cache/CollectionCacheManager.cs index 8c30f434..3a79c2b4 100644 --- a/Penumbra/Collections/Cache/CollectionCacheManager.cs +++ b/Penumbra/Collections/Cache/CollectionCacheManager.cs @@ -7,11 +7,9 @@ using Penumbra.Communication; using Penumbra.Interop.Hooks.ResourceLoading; using Penumbra.Meta; using Penumbra.Mods; -using Penumbra.Mods.Groups; using Penumbra.Mods.Manager; using Penumbra.Mods.Manager.OptionEditor; using Penumbra.Mods.Settings; -using Penumbra.Mods.SubMods; using Penumbra.Services; using Penumbra.String.Classes; @@ -70,7 +68,8 @@ public class CollectionCacheManager : IDisposable, IService _communicator.ModDiscoveryFinished.Subscribe(OnModDiscoveryFinished, ModDiscoveryFinished.Priority.CollectionCacheManager); if (!MetaFileManager.CharacterUtility.Ready) - MetaFileManager.CharacterUtility.LoadingFinished.Subscribe(IncrementCounters, CharacterUtilityFinished.Priority.CollectionCacheManager); + MetaFileManager.CharacterUtility.LoadingFinished.Subscribe(IncrementCounters, + CharacterUtilityFinished.Priority.CollectionCacheManager); } public void Dispose() @@ -140,7 +139,8 @@ public class CollectionCacheManager : IDisposable, IService if (collection.Identity.Index == 0) return; - Penumbra.Log.Debug($"[{Environment.CurrentManagedThreadId}] Recalculating effective file list for {collection.Identity.AnonymizedName}"); + Penumbra.Log.Debug( + $"[{Environment.CurrentManagedThreadId}] Recalculating effective file list for {collection.Identity.AnonymizedName}"); if (!collection.HasCache) { Penumbra.Log.Error( @@ -169,8 +169,9 @@ public class CollectionCacheManager : IDisposable, IService cache.Calculating = Environment.CurrentManagedThreadId; try { - ResolvedFileChanged.Invoke(collection, ResolvedFileChanged.Type.FullRecomputeStart, Utf8GamePath.Empty, FullPath.Empty, - FullPath.Empty, null); + ResolvedFileChanged.Invoke(new ResolvedFileChanged.Arguments(ResolvedFileChanged.Type.FullRecomputeStart, collection, + Utf8GamePath.Empty, FullPath.Empty, + FullPath.Empty, null)); cache.ResolvedFiles.Clear(); cache.Meta.Reset(); cache.ConflictDict.Clear(); @@ -188,9 +189,9 @@ public class CollectionCacheManager : IDisposable, IService collection.Counters.IncrementChange(); MetaFileManager.ApplyDefaultFiles(collection); - ResolvedFileChanged.Invoke(collection, ResolvedFileChanged.Type.FullRecomputeFinished, Utf8GamePath.Empty, FullPath.Empty, - FullPath.Empty, - null); + ResolvedFileChanged.Invoke(new ResolvedFileChanged.Arguments(ResolvedFileChanged.Type.FullRecomputeFinished, collection, + Utf8GamePath.Empty, FullPath.Empty, + FullPath.Empty, null)); } finally { @@ -198,63 +199,69 @@ public class CollectionCacheManager : IDisposable, IService } } - private void OnCollectionChange(CollectionType type, ModCollection? old, ModCollection? newCollection, string displayName) + private void OnCollectionChange(in CollectionChange.Arguments arguments) { - if (type is CollectionType.Temporary) + if (arguments.Type is CollectionType.Temporary) { - if (newCollection != null && CreateCache(newCollection)) - CalculateEffectiveFileList(newCollection); + if (arguments.NewCollection is not null && CreateCache(arguments.NewCollection)) + CalculateEffectiveFileList(arguments.NewCollection); - if (old != null) - ClearCache(old); + if (arguments.OldCollection is not null) + ClearCache(arguments.OldCollection); } else { - RemoveCache(old); - if (type is not CollectionType.Inactive && newCollection != null && newCollection.Identity.Index != 0 && CreateCache(newCollection)) - CalculateEffectiveFileList(newCollection); + RemoveCache(arguments.OldCollection); + if (arguments.Type is not CollectionType.Inactive + && arguments.NewCollection is not null + && arguments.NewCollection.Identity.Index is not 0 + && CreateCache(arguments.NewCollection)) + CalculateEffectiveFileList(arguments.NewCollection); - if (type is CollectionType.Default) - if (newCollection != null) - MetaFileManager.ApplyDefaultFiles(newCollection); + if (arguments.Type is CollectionType.Default) + if (arguments.NewCollection is not null) + MetaFileManager.ApplyDefaultFiles(arguments.NewCollection); else MetaFileManager.CharacterUtility.ResetAll(); } } - private void OnModChangeRemoval(ModPathChangeType type, Mod mod, DirectoryInfo? oldModPath, DirectoryInfo? newModPath) + private void OnModChangeRemoval(in ModPathChanged.Arguments arguments) { - switch (type) + var index = arguments.Mod.Index; + switch (arguments.Type) { case ModPathChangeType.Deleted: case ModPathChangeType.StartingReload: - foreach (var collection in _storage.Where(c => c.HasCache && c.GetActualSettings(mod.Index).Settings?.Enabled == true)) - collection._cache!.RemoveMod(mod, true); + foreach (var collection in _storage.Where(c => c.HasCache && c.GetActualSettings(index).Settings?.Enabled == true)) + collection._cache!.RemoveMod(arguments.Mod, true); break; case ModPathChangeType.Moved: - foreach (var collection in _storage.Where(c => c.HasCache && c.GetActualSettings(mod.Index).Settings?.Enabled == true)) - collection._cache!.ReloadMod(mod, true); + foreach (var collection in _storage.Where(c => c.HasCache && c.GetActualSettings(index).Settings?.Enabled == true)) + collection._cache!.ReloadMod(arguments.Mod, true); break; } } - private void OnModChangeAddition(ModPathChangeType type, Mod mod, DirectoryInfo? oldModPath, DirectoryInfo? newModPath) + private void OnModChangeAddition(in ModPathChanged.Arguments arguments) { - if (type is not (ModPathChangeType.Added or ModPathChangeType.Reloaded)) + if (arguments.Type is not ModPathChangeType.Added and not ModPathChangeType.Reloaded) return; - foreach (var collection in _storage.Where(c => c.HasCache && c.GetActualSettings(mod.Index).Settings?.Enabled == true)) - collection._cache!.AddMod(mod, true); + var index = arguments.Mod.Index; + foreach (var collection in _storage.Where(c => c.HasCache && c.GetActualSettings(index).Settings?.Enabled == true)) + collection._cache!.AddMod(arguments.Mod, true); } /// Apply a mod change to all collections with a cache. - private void OnGlobalModChange(TemporaryMod mod, bool created, bool removed) - => TempModManager.OnGlobalModChange(_storage.Where(c => c.HasCache), mod, created, removed); + private void OnGlobalModChange(in TemporaryGlobalModChange.Arguments arguments) + => TempModManager.OnGlobalModChange(_storage.Where(c => c.HasCache), arguments.Mod, arguments.NewlyCreated, arguments.Deleted); /// Remove a cache from a collection if it is active. private void RemoveCache(ModCollection? collection) { + // ReSharper disable InconsistentlySynchronizedField if (collection != null && collection.Identity.Index > ModCollection.Empty.Identity.Index && collection.Identity.Index != _active.Default.Identity.Index @@ -263,31 +270,35 @@ public class CollectionCacheManager : IDisposable, IService && _active.SpecialAssignments.All(c => c.Value.Identity.Index != collection.Identity.Index) && _active.Individuals.All(c => c.Collection.Identity.Index != collection.Identity.Index)) ClearCache(collection); + // ReSharper restore InconsistentlySynchronizedField } /// Prepare Changes by removing mods from caches with collections or add or reload mods. - private void OnModOptionChange(ModOptionChangeType type, Mod mod, IModGroup? group, IModOption? option, IModDataContainer? container, - int movedToIdx) + private void OnModOptionChange(in ModOptionChanged.Arguments arguments) { - if (type is ModOptionChangeType.PrepareChange) + if (arguments.Type is ModOptionChangeType.PrepareChange) { - foreach (var collection in _storage.Where(collection => collection.HasCache && collection.GetActualSettings(mod.Index).Settings is { Enabled: true })) - collection._cache!.RemoveMod(mod, false); - - return; + var index = arguments.Mod.Index; + foreach (var collection in _storage.Where(collection + => collection.HasCache && collection.GetActualSettings(index).Settings is { Enabled: true })) + collection._cache!.RemoveMod(arguments.Mod, false); } - - type.HandlingInfo(out _, out var recomputeList, out var justAdd); - - if (!recomputeList) - return; - - foreach (var collection in _storage.Where(collection => collection.HasCache && collection.GetActualSettings(mod.Index).Settings is { Enabled: true })) + else { - if (justAdd) - collection._cache!.AddMod(mod, true); - else - collection._cache!.ReloadMod(mod, true); + arguments.Type.HandlingInfo(out _, out var recomputeList, out var justAdd); + + if (!recomputeList) + return; + + var index = arguments.Mod.Index; + foreach (var collection in _storage.Where(collection + => collection.HasCache && collection.GetActualSettings(index).Settings is { Enabled: true })) + { + if (justAdd) + collection._cache!.AddMod(arguments.Mod, true); + else + collection._cache!.ReloadMod(arguments.Mod, true); + } } } @@ -299,41 +310,38 @@ public class CollectionCacheManager : IDisposable, IService MetaFileManager.CharacterUtility.LoadingFinished.Unsubscribe(IncrementCounters); } - private void OnModSettingChange(ModCollection collection, ModSettingChange type, Mod? mod, Setting oldValue, int groupIdx, bool _) + private void OnModSettingChange(in ModSettingChanged.Arguments arguments) { + var collection = arguments.Collection; if (!collection.HasCache) return; var cache = collection._cache!; - switch (type) + switch (arguments.Type) { - case ModSettingChange.Inheritance: - cache.ReloadMod(mod!, true); - break; + case ModSettingChange.Inheritance: cache.ReloadMod(arguments.Mod!, true); break; case ModSettingChange.EnableState: - if (oldValue == Setting.False) - cache.AddMod(mod!, true); - else if (oldValue == Setting.True) - cache.RemoveMod(mod!, true); - else if (collection.GetActualSettings(mod!.Index).Settings?.Enabled == true) - cache.ReloadMod(mod!, true); + if (arguments.OldValue == Setting.False) + cache.AddMod(arguments.Mod!, true); + else if (arguments.OldValue == Setting.True) + cache.RemoveMod(arguments.Mod!, true); + else if (collection.GetActualSettings(arguments.Mod!.Index).Settings?.Enabled == true) + cache.ReloadMod(arguments.Mod!, true); else - cache.RemoveMod(mod!, true); + cache.RemoveMod(arguments.Mod!, true); break; case ModSettingChange.Priority: - if (cache.Conflicts(mod!).Count > 0) - cache.ReloadMod(mod!, true); + if (cache.Conflicts(arguments.Mod!).Count > 0) + cache.ReloadMod(arguments.Mod!, true); break; case ModSettingChange.Setting: - if (collection.GetActualSettings(mod!.Index).Settings?.Enabled == true) - cache.ReloadMod(mod, true); + if (collection.GetActualSettings(arguments.Mod!.Index).Settings?.Enabled == true) + cache.ReloadMod(arguments.Mod, true); break; - case ModSettingChange.TemporarySetting: - cache.ReloadMod(mod!, true); - break; + case ModSettingChange.TemporarySetting: cache.ReloadMod(arguments.Mod!, true); break; case ModSettingChange.MultiInheritance: case ModSettingChange.MultiEnableState: FullRecalculation(collection); @@ -349,8 +357,8 @@ public class CollectionCacheManager : IDisposable, IService /// Inheritance changes are too big to check for relevance, /// just recompute everything. /// - private void OnCollectionInheritanceChange(ModCollection collection, bool _) - => FullRecalculation(collection); + private void OnCollectionInheritanceChange(in CollectionInheritanceChanged.Arguments arguments) + => FullRecalculation(arguments.Collection); /// Clear the current cache of a collection. private void ClearCache(ModCollection collection) diff --git a/Penumbra/Collections/Manager/ActiveCollections.cs b/Penumbra/Collections/Manager/ActiveCollections.cs index 1a026644..9adee887 100644 --- a/Penumbra/Collections/Manager/ActiveCollections.cs +++ b/Penumbra/Collections/Manager/ActiveCollections.cs @@ -126,7 +126,7 @@ public class ActiveCollections : ISavable, IDisposable, IService return false; SpecialCollections[(int)collectionType] = Default; - _communicator.CollectionChange.Invoke(collectionType, null, Default, string.Empty); + _communicator.CollectionChange.Invoke(new CollectionChange.Arguments(collectionType, null, Default, string.Empty)); return true; } @@ -141,14 +141,14 @@ public class ActiveCollections : ISavable, IDisposable, IService return; SpecialCollections[(int)collectionType] = null; - _communicator.CollectionChange.Invoke(collectionType, old, null, string.Empty); + _communicator.CollectionChange.Invoke(new CollectionChange.Arguments(collectionType, old, null, string.Empty)); } /// Create an individual collection if possible. public void CreateIndividualCollection(params ActorIdentifier[] identifiers) { if (Individuals.Add(identifiers, Default)) - _communicator.CollectionChange.Invoke(CollectionType.Individual, null, Default, Individuals.Last().DisplayName); + _communicator.CollectionChange.Invoke(new CollectionChange.Arguments(CollectionType.Individual, null, Default, Individuals.Last().DisplayName)); } /// Remove an individual collection if it exists. @@ -159,7 +159,7 @@ public class ActiveCollections : ISavable, IDisposable, IService var (name, old) = Individuals[individualIndex]; if (Individuals.Delete(individualIndex)) - _communicator.CollectionChange.Invoke(CollectionType.Individual, old, null, name); + _communicator.CollectionChange.Invoke(new CollectionChange.Arguments(CollectionType.Individual, old, null, name)); } /// Move an individual collection from one index to another. @@ -234,8 +234,8 @@ public class ActiveCollections : ISavable, IDisposable, IService } UpdateCurrentCollectionInUse(); - _communicator.CollectionChange.Invoke(collectionType, oldCollection, collection, - collectionType == CollectionType.Individual ? Individuals[individualIndex].DisplayName : string.Empty); + _communicator.CollectionChange.Invoke(new CollectionChange.Arguments(collectionType, oldCollection, collection, + collectionType == CollectionType.Individual ? Individuals[individualIndex].DisplayName : string.Empty)); } public string ToFilePath(FilenameService fileNames) @@ -275,38 +275,38 @@ public class ActiveCollections : ISavable, IDisposable, IService .SelectMany(c => c.Inheritance.FlatHierarchy).Contains(Current); /// Save if any of the active collections is changed and set new collections to Current. - private void OnCollectionChange(CollectionType collectionType, ModCollection? oldCollection, ModCollection? newCollection, string _3) + private void OnCollectionChange(in CollectionChange.Arguments arguments) { - if (collectionType is CollectionType.Inactive) + if (arguments.Type is CollectionType.Inactive) { - if (newCollection != null) + if (arguments.NewCollection is not null) { - SetCollection(newCollection, CollectionType.Current); + SetCollection(arguments.NewCollection, CollectionType.Current); } - else if (oldCollection != null) + else if (arguments.OldCollection != null) { - if (oldCollection == Default) + if (arguments.OldCollection == Default) SetCollection(ModCollection.Empty, CollectionType.Default); - if (oldCollection == Interface) + if (arguments.OldCollection == Interface) SetCollection(ModCollection.Empty, CollectionType.Interface); - if (oldCollection == Current) + if (arguments.OldCollection == Current) SetCollection(Default.Identity.Index > ModCollection.Empty.Identity.Index ? Default : _storage.DefaultNamed, CollectionType.Current); for (var i = 0; i < SpecialCollections.Length; ++i) { - if (oldCollection == SpecialCollections[i]) + if (arguments.OldCollection == SpecialCollections[i]) SetCollection(ModCollection.Empty, (CollectionType)i); } for (var i = 0; i < Individuals.Count; ++i) { - if (oldCollection == Individuals[i].Collection) + if (arguments.OldCollection == Individuals[i].Collection) SetCollection(ModCollection.Empty, CollectionType.Individual, i); } } } - else if (collectionType is not CollectionType.Temporary) + else if (arguments.Type is not CollectionType.Temporary) { _saveService.DelaySave(this); } diff --git a/Penumbra/Collections/Manager/CollectionEditor.cs b/Penumbra/Collections/Manager/CollectionEditor.cs index ad78acec..ded84553 100644 --- a/Penumbra/Collections/Manager/CollectionEditor.cs +++ b/Penumbra/Collections/Manager/CollectionEditor.cs @@ -1,4 +1,5 @@ using Penumbra.Api.Enums; +using Penumbra.Communication; using Penumbra.Mods; using Penumbra.Mods.Manager; using Penumbra.Mods.Settings; @@ -208,7 +209,7 @@ public class CollectionEditor(SaveService saveService, CommunicatorService commu { if (type is not ModSettingChange.TemporarySetting) saveService.QueueSave(new ModCollectionSave(modStorage, changedCollection)); - communicator.ModSettingChanged.Invoke(changedCollection, type, mod, oldValue, groupIdx, false); + communicator.ModSettingChanged.Invoke(new ModSettingChanged.Arguments(type, changedCollection, mod, oldValue, groupIdx, false)); if (type is not ModSettingChange.TemporarySetting) RecurseInheritors(changedCollection, type, mod, oldValue, groupIdx); } @@ -223,11 +224,11 @@ public class CollectionEditor(SaveService saveService, CommunicatorService commu { case ModSettingChange.MultiInheritance: case ModSettingChange.MultiEnableState: - communicator.ModSettingChanged.Invoke(directInheritor, type, null, oldValue, groupIdx, true); + communicator.ModSettingChanged.Invoke(new ModSettingChanged.Arguments(type, directInheritor, null, oldValue, groupIdx, true)); break; default: if (directInheritor.GetOwnSettings(mod!.Index) == null) - communicator.ModSettingChanged.Invoke(directInheritor, type, mod, oldValue, groupIdx, true); + communicator.ModSettingChanged.Invoke(new ModSettingChanged.Arguments(type, directInheritor, mod, oldValue, groupIdx, true)); break; } diff --git a/Penumbra/Collections/Manager/CollectionStorage.cs b/Penumbra/Collections/Manager/CollectionStorage.cs index 0463a00b..b35f98e7 100644 --- a/Penumbra/Collections/Manager/CollectionStorage.cs +++ b/Penumbra/Collections/Manager/CollectionStorage.cs @@ -1,13 +1,9 @@ using Dalamud.Interface.ImGuiNotification; using Luna; using Penumbra.Communication; -using Penumbra.Mods; -using Penumbra.Mods.Editor; -using Penumbra.Mods.Groups; using Penumbra.Mods.Manager; using Penumbra.Mods.Manager.OptionEditor; using Penumbra.Mods.Settings; -using Penumbra.Mods.SubMods; using Penumbra.Services; namespace Penumbra.Collections.Manager; @@ -21,7 +17,7 @@ public readonly record struct LocalCollectionId(int Id) : IAdditionOperators new(left.Id + right); } -public class CollectionStorage : IReadOnlyList, IDisposable, Luna.IService +public class CollectionStorage : IReadOnlyList, IDisposable, IService { private readonly CommunicatorService _communicator; private readonly SaveService _saveService; @@ -157,7 +153,7 @@ public class CollectionStorage : IReadOnlyList, IDisposable, Luna _collections.Add(newCollection); _saveService.ImmediateSave(new ModCollectionSave(_modStorage, newCollection)); Penumbra.Messager.NotificationMessage($"Created new collection {newCollection.Identity.AnonymizedName}.", NotificationType.Success, false); - _communicator.CollectionChange.Invoke(CollectionType.Inactive, null, newCollection, string.Empty); + _communicator.CollectionChange.Invoke(new CollectionChange.Arguments(CollectionType.Inactive, null, newCollection, string.Empty)); return true; } @@ -187,7 +183,7 @@ public class CollectionStorage : IReadOnlyList, IDisposable, Luna _collectionsByLocal.Remove(collection.Identity.LocalId); Penumbra.Messager.NotificationMessage($"Deleted collection {collection.Identity.AnonymizedName}.", NotificationType.Success, false); - _communicator.CollectionChange.Invoke(CollectionType.Inactive, collection, null, string.Empty); + _communicator.CollectionChange.Invoke(new CollectionChange.Arguments(CollectionType.Inactive, collection, null, string.Empty)); return true; } @@ -321,29 +317,29 @@ public class CollectionStorage : IReadOnlyList, IDisposable, Luna } /// Add or remove a mod from all collections, or re-save all collections where the mod has settings. - private void OnModPathChange(ModPathChangeType type, Mod mod, DirectoryInfo? oldDirectory, - DirectoryInfo? newDirectory) + private void OnModPathChange(in ModPathChanged.Arguments arguments) { - switch (type) + switch (arguments.Type) { case ModPathChangeType.Added: foreach (var collection in this) - collection.Settings.AddMod(mod); + collection.Settings.AddMod(arguments.Mod); break; case ModPathChangeType.Deleted: foreach (var collection in this) - collection.Settings.RemoveMod(mod); + collection.Settings.RemoveMod(arguments.Mod); break; case ModPathChangeType.Moved: - foreach (var collection in this.Where(collection => collection.GetOwnSettings(mod.Index) != null)) + var index = arguments.Mod.Index; + foreach (var collection in this.Where(collection => collection.GetOwnSettings(index) is not null)) _saveService.QueueSave(new ModCollectionSave(_modStorage, collection)); break; case ModPathChangeType.Reloaded: foreach (var collection in this) { - if (collection.GetOwnSettings(mod.Index)?.Settings.FixAll(mod) ?? false) + if (collection.GetOwnSettings(arguments.Mod.Index)?.Settings.FixAll(arguments.Mod) ?? false) _saveService.QueueSave(new ModCollectionSave(_modStorage, collection)); - collection.Settings.SetTemporary(mod.Index, null); + collection.Settings.SetTemporary(arguments.Mod.Index, null); } break; @@ -351,30 +347,29 @@ public class CollectionStorage : IReadOnlyList, IDisposable, Luna } /// Save all collections where the mod has settings and the change requires saving. - private void OnModOptionChange(ModOptionChangeType type, Mod mod, IModGroup? group, IModOption? option, IModDataContainer? container, - int movedToIdx) + private void OnModOptionChange(in ModOptionChanged.Arguments arguments) { - type.HandlingInfo(out var requiresSaving, out _, out _); + arguments.Type.HandlingInfo(out var requiresSaving, out _, out _); if (!requiresSaving) return; foreach (var collection in this) { - if (collection.GetOwnSettings(mod.Index)?.HandleChanges(type, mod, group, option, movedToIdx) ?? false) + if (collection.GetOwnSettings(arguments.Mod.Index)?.HandleChanges(arguments.Type, arguments.Mod, arguments.Group, arguments.Option, arguments.DeletedIndex) ?? false) _saveService.QueueSave(new ModCollectionSave(_modStorage, collection)); - collection.Settings.SetTemporary(mod.Index, null); + collection.Settings.SetTemporary(arguments.Mod.Index, null); } } /// Update change counters when changing files. - private void OnModFileChanged(Mod mod, FileRegistry file) + private void OnModFileChanged(in ModFileChanged.Arguments arguments) { - if (file.CurrentUsage == 0) + if (arguments.File.CurrentUsage == 0) return; foreach (var collection in this) { - var (settings, _) = collection.GetActualSettings(mod.Index); + var (settings, _) = collection.GetActualSettings(arguments.Mod.Index); if (settings is { Enabled: true }) collection.Counters.IncrementChange(); } diff --git a/Penumbra/Collections/Manager/InheritanceManager.cs b/Penumbra/Collections/Manager/InheritanceManager.cs index 78a25a90..73127bf2 100644 --- a/Penumbra/Collections/Manager/InheritanceManager.cs +++ b/Penumbra/Collections/Manager/InheritanceManager.cs @@ -11,7 +11,7 @@ namespace Penumbra.Collections.Manager; /// This is transitive, so a collection A inheriting from B also inherits from everything B inherits. /// Circular dependencies are resolved by distinctness. /// -public class InheritanceManager : IDisposable, Luna.IService +public class InheritanceManager : IDisposable, IService { public enum ValidInheritance { @@ -82,7 +82,7 @@ public class InheritanceManager : IDisposable, Luna.IService { var parent = inheritor.Inheritance.RemoveInheritanceAt(inheritor, idx); _saveService.QueueSave(new ModCollectionSave(_modStorage, inheritor)); - _communicator.CollectionInheritanceChanged.Invoke(inheritor, false); + _communicator.CollectionInheritanceChanged.Invoke(new CollectionInheritanceChanged.Arguments(inheritor, false)); RecurseInheritanceChanges(inheritor, true); Penumbra.Log.Debug($"Removed {parent.Identity.AnonymizedName} from {inheritor.Identity.AnonymizedName} inheritances."); } @@ -94,7 +94,7 @@ public class InheritanceManager : IDisposable, Luna.IService return; _saveService.QueueSave(new ModCollectionSave(_modStorage, inheritor)); - _communicator.CollectionInheritanceChanged.Invoke(inheritor, false); + _communicator.CollectionInheritanceChanged.Invoke(new CollectionInheritanceChanged.Arguments(inheritor, false)); RecurseInheritanceChanges(inheritor, true); Penumbra.Log.Debug($"Moved {inheritor.Identity.AnonymizedName}s inheritance {from} to {to}."); } @@ -109,7 +109,7 @@ public class InheritanceManager : IDisposable, Luna.IService if (invokeEvent) { _saveService.QueueSave(new ModCollectionSave(_modStorage, inheritor)); - _communicator.CollectionInheritanceChanged.Invoke(inheritor, false); + _communicator.CollectionInheritanceChanged.Invoke(new CollectionInheritanceChanged.Arguments(inheritor, false)); } RecurseInheritanceChanges(inheritor, invokeEvent); @@ -167,18 +167,18 @@ public class InheritanceManager : IDisposable, Luna.IService } } - private void OnCollectionChange(CollectionType collectionType, ModCollection? old, ModCollection? newCollection, string _3) + private void OnCollectionChange(in CollectionChange.Arguments arguments) { - if (collectionType is not CollectionType.Inactive || old == null) + if (arguments.Type is not CollectionType.Inactive || arguments.OldCollection is null) return; foreach (var c in _storage) { - var inheritedIdx = c.Inheritance.DirectlyInheritsFrom.IndexOf(old); + var inheritedIdx = c.Inheritance.DirectlyInheritsFrom.IndexOf(arguments.OldCollection); if (inheritedIdx >= 0) RemoveInheritance(c, inheritedIdx); - c.Inheritance.RemoveChild(old); + c.Inheritance.RemoveChild(arguments.OldCollection); } } @@ -189,7 +189,7 @@ public class InheritanceManager : IDisposable, Luna.IService ModCollectionInheritance.UpdateFlattenedInheritance(inheritor); RecurseInheritanceChanges(inheritor, invokeEvent); if (invokeEvent) - _communicator.CollectionInheritanceChanged.Invoke(inheritor, true); + _communicator.CollectionInheritanceChanged.Invoke(new CollectionInheritanceChanged.Arguments(inheritor, true)); } } } diff --git a/Penumbra/Collections/Manager/TempCollectionManager.cs b/Penumbra/Collections/Manager/TempCollectionManager.cs index 5e5fc21b..3b48eaa4 100644 --- a/Penumbra/Collections/Manager/TempCollectionManager.cs +++ b/Penumbra/Collections/Manager/TempCollectionManager.cs @@ -33,8 +33,8 @@ public class TempCollectionManager : IDisposable, Luna.IService _communicator.TemporaryGlobalModChange.Unsubscribe(OnGlobalModChange); } - private void OnGlobalModChange(TemporaryMod mod, bool created, bool removed) - => TempModManager.OnGlobalModChange(_customCollections.Values, mod, created, removed); + private void OnGlobalModChange(in TemporaryGlobalModChange.Arguments arguments) + => TempModManager.OnGlobalModChange(_customCollections.Values, arguments.Mod, arguments.NewlyCreated, arguments.Deleted); public int Count => _customCollections.Count; @@ -57,7 +57,7 @@ public class TempCollectionManager : IDisposable, Luna.IService if (_customCollections.TryAdd(collection.Identity.Id, collection)) { // Temporary collection created. - _communicator.CollectionChange.Invoke(CollectionType.Temporary, null, collection, string.Empty); + _communicator.CollectionChange.Invoke(new CollectionChange.Arguments(CollectionType.Temporary, null, collection, string.Empty)); return collection.Identity.Id; } @@ -81,7 +81,7 @@ public class TempCollectionManager : IDisposable, Luna.IService continue; // Temporary collection assignment removed. - _communicator.CollectionChange.Invoke(CollectionType.Temporary, collection, null, Collections[i].DisplayName); + _communicator.CollectionChange.Invoke(new CollectionChange.Arguments(CollectionType.Temporary, collection, null, Collections[i].DisplayName)); Penumbra.Log.Verbose($"Unassigned temporary collection {collection.Identity.Id} from {Collections[i].DisplayName}."); Collections.Delete(i--); } @@ -96,7 +96,7 @@ public class TempCollectionManager : IDisposable, Luna.IService // Temporary collection assignment added. Penumbra.Log.Verbose($"Assigned temporary collection {collection.Identity.AnonymizedName} to {Collections.Last().DisplayName}."); - _communicator.CollectionChange.Invoke(CollectionType.Temporary, null, collection, Collections.Last().DisplayName); + _communicator.CollectionChange.Invoke(new CollectionChange.Arguments(CollectionType.Temporary, null, collection, Collections.Last().DisplayName)); return true; } diff --git a/Penumbra/Communication/ChangedItemClick.cs b/Penumbra/Communication/ChangedItemClick.cs index 2d27f36a..2b5c4a51 100644 --- a/Penumbra/Communication/ChangedItemClick.cs +++ b/Penumbra/Communication/ChangedItemClick.cs @@ -1,18 +1,13 @@ -using OtterGui.Classes; +using Luna; using Penumbra.Api.Api; using Penumbra.Api.Enums; using Penumbra.GameData.Data; namespace Penumbra.Communication; -/// -/// Triggered when a Changed Item in Penumbra is clicked. -/// -/// Parameter is the clicked mouse button. -/// Parameter is the clicked object data if any. -/// -/// -public sealed class ChangedItemClick() : EventWrapper(nameof(ChangedItemClick)) +/// Triggered when a Changed Item in Penumbra is clicked. +public sealed class ChangedItemClick(Logger log) + : EventBase(nameof(ChangedItemClick), log) { public enum Priority { @@ -22,4 +17,9 @@ public sealed class ChangedItemClick() : EventWrapper Link = 1, } + + /// The arguments for a changed item click event. + /// The clicked mouse button. + /// The associated data for the clicked object, if any. + public readonly record struct Arguments(MouseButton Button, IIdentifiedObjectData Data); } diff --git a/Penumbra/Communication/ChangedItemHover.cs b/Penumbra/Communication/ChangedItemHover.cs index 92d770f7..5b9b868b 100644 --- a/Penumbra/Communication/ChangedItemHover.cs +++ b/Penumbra/Communication/ChangedItemHover.cs @@ -1,16 +1,12 @@ -using OtterGui.Classes; +using Luna; using Penumbra.Api.Api; using Penumbra.GameData.Data; namespace Penumbra.Communication; -/// -/// Triggered when a Changed Item in Penumbra is hovered. -/// -/// Parameter is the hovered object data if any. -/// -/// -public sealed class ChangedItemHover() : EventWrapper(nameof(ChangedItemHover)) +/// Triggered when a Changed Item in Penumbra is hovered. +public sealed class ChangedItemHover(Logger log) + : EventBase(nameof(ChangedItemHover), log) { public enum Priority { @@ -21,6 +17,11 @@ public sealed class ChangedItemHover() : EventWrapper Whether this event has any subscribers. public bool HasTooltip => HasSubscribers; + + /// The arguments for a changed item hover event. + /// The associated data for the hovered object, if any. + public readonly record struct Arguments(IIdentifiedObjectData Data); } diff --git a/Penumbra/Communication/CharacterUtilityFinished.cs b/Penumbra/Communication/CharacterUtilityFinished.cs index fbeeb8a7..6e46237d 100644 --- a/Penumbra/Communication/CharacterUtilityFinished.cs +++ b/Penumbra/Communication/CharacterUtilityFinished.cs @@ -1,13 +1,11 @@ -using OtterGui.Classes; +using Luna; using Penumbra.Api; using Penumbra.Interop.Services; namespace Penumbra.Communication; -/// -/// Triggered when the Character Utility becomes ready. -/// -public sealed class CharacterUtilityFinished() : EventWrapper(nameof(CharacterUtilityFinished)) +/// Triggered when the Character Utility becomes ready. +public sealed class CharacterUtilityFinished(Logger log) : EventBase(nameof(CharacterUtilityFinished), log) { public enum Priority { diff --git a/Penumbra/Communication/CollectionChange.cs b/Penumbra/Communication/CollectionChange.cs index 2788177d..487c5e16 100644 --- a/Penumbra/Communication/CollectionChange.cs +++ b/Penumbra/Communication/CollectionChange.cs @@ -1,19 +1,12 @@ -using OtterGui.Classes; +using Luna; using Penumbra.Collections; using Penumbra.Collections.Manager; namespace Penumbra.Communication; -/// -/// Triggered whenever collection setup is changed. -/// -/// Parameter is the type of the changed collection. (Inactive or Temporary for additions or deletions) -/// Parameter is the old collection, or null on additions. -/// Parameter is the new collection, or null on deletions. -/// Parameter is the display name for Individual collections or an empty string otherwise. -/// -public sealed class CollectionChange() - : EventWrapper(nameof(CollectionChange)) +/// Triggered whenever collection setup is changed. +public sealed class CollectionChange(Logger log) + : EventBase(nameof(CollectionChange), log) { public enum Priority { @@ -32,7 +25,7 @@ public sealed class CollectionChange() /// InheritanceManager = 0, - /// + /// IdentifiedCollectionCache = 0, /// @@ -50,4 +43,15 @@ public sealed class CollectionChange() /// ModSelection = 10, } + + /// The arguments for a collection change event. + /// The type of the changed collection ( or for additions or deletions). + /// The old collection, or null on additions. + /// The new collection, or null on deletions. + /// The display name for Individual collections or an empty string otherwise. + public readonly record struct Arguments( + CollectionType Type, + ModCollection? OldCollection, + ModCollection? NewCollection, + string DisplayName); } diff --git a/Penumbra/Communication/CollectionInheritanceChanged.cs b/Penumbra/Communication/CollectionInheritanceChanged.cs index 30af2b20..c917875d 100644 --- a/Penumbra/Communication/CollectionInheritanceChanged.cs +++ b/Penumbra/Communication/CollectionInheritanceChanged.cs @@ -1,4 +1,4 @@ -using OtterGui.Classes; +using Luna; using Penumbra.Collections; namespace Penumbra.Communication; @@ -10,8 +10,8 @@ namespace Penumbra.Communication; /// Parameter is whether the change was itself inherited, i.e. if it happened in a direct parent (false) or a more removed ancestor (true). /// /// -public sealed class CollectionInheritanceChanged() - : EventWrapper(nameof(CollectionInheritanceChanged)) +public sealed class CollectionInheritanceChanged(Logger log) + : EventBase(nameof(CollectionInheritanceChanged), log) { public enum Priority { @@ -27,4 +27,9 @@ public sealed class CollectionInheritanceChanged() /// ModSelection = 10, } + + /// The arguments for a collection inheritance changed event. + /// The collection whose ancestors were changed. + /// Whether the change was itself inherited, i.e. if it happened in a direct parent (false) or a more removed ancestor (true). + public readonly record struct Arguments(ModCollection Collection, bool Inherited); } diff --git a/Penumbra/Communication/CreatedCharacterBase.cs b/Penumbra/Communication/CreatedCharacterBase.cs index 8992f9fc..bbc07f4d 100644 --- a/Penumbra/Communication/CreatedCharacterBase.cs +++ b/Penumbra/Communication/CreatedCharacterBase.cs @@ -1,21 +1,23 @@ -using OtterGui.Classes; -using Penumbra.Api; +using Luna; using Penumbra.Api.Api; using Penumbra.Collections; +using Penumbra.GameData.Interop; namespace Penumbra.Communication; -/// -/// Parameter is the game object for which a draw object is created. -/// Parameter is the applied collection. -/// Parameter is the created draw object. -/// -public sealed class CreatedCharacterBase() - : EventWrapper(nameof(CreatedCharacterBase)) +/// Invoked whenever a draw object is created for a game object. +public sealed class CreatedCharacterBase(Logger log) + : EventBase(nameof(CreatedCharacterBase), log) { public enum Priority { - /// + /// Api = int.MinValue, } + + /// The arguments for a created CharacterBase event. + /// The address of the game object for which a draw object was created. + /// The associated collection. + /// The newly created draw object for the game object. + public readonly record struct Arguments(Actor GameObject, ModCollection Collection, Model DrawObject); } diff --git a/Penumbra/Communication/CreatingCharacterBase.cs b/Penumbra/Communication/CreatingCharacterBase.cs index 51d55868..070d9bfc 100644 --- a/Penumbra/Communication/CreatingCharacterBase.cs +++ b/Penumbra/Communication/CreatingCharacterBase.cs @@ -1,20 +1,14 @@ -using OtterGui.Classes; +using Luna; using Penumbra.Api.Api; +using Penumbra.Collections; +using Penumbra.GameData.Interop; using Penumbra.Services; namespace Penumbra.Communication; -/// -/// Triggered whenever a character base draw object is being created by the game. -/// -/// Parameter is the game object for which a draw object is created. -/// Parameter is the name of the applied collection. -/// Parameter is a pointer to the model id (an uint). -/// Parameter is a pointer to the customize array. -/// Parameter is a pointer to the equip data array. -/// -public sealed class CreatingCharacterBase() - : EventWrapper(nameof(CreatingCharacterBase)) +/// Triggered whenever a character base draw object is being created by the game. +public sealed class CreatingCharacterBase(Logger log) + : EventBase(nameof(CreatingCharacterBase), log) { public enum Priority { @@ -24,4 +18,12 @@ public sealed class CreatingCharacterBase() /// CrashHandler = 0, } + + /// The arguments for a created CharacterBase event. + /// The address of the game object for which a draw object is being created. + /// The associated collection. + /// The address of the model ID that is being used. + /// The address of the customize array that is being used. + /// The address of the equip data array that is being used. + public readonly record struct Arguments(Actor GameObject, ModCollection Collection, nint ModelCharaId, nint Customize, nint EquipData); } diff --git a/Penumbra/Communication/EnabledChanged.cs b/Penumbra/Communication/EnabledChanged.cs index 846b1a58..81b7aaee 100644 --- a/Penumbra/Communication/EnabledChanged.cs +++ b/Penumbra/Communication/EnabledChanged.cs @@ -1,23 +1,20 @@ -using OtterGui.Classes; -using Penumbra.Api; -using Penumbra.Api.IpcSubscribers; +using Luna; namespace Penumbra.Communication; -/// -/// Triggered when the general Enabled state of Penumbra is changed. -/// -/// Parameter is whether Penumbra is now Enabled (true) or Disabled (false). -/// -/// -public sealed class EnabledChanged() : EventWrapper(nameof(EnabledChanged)) +/// Triggered when the general Enabled state of Penumbra is changed. +public sealed class EnabledChanged(Logger log) : EventBase(nameof(EnabledChanged), log) { public enum Priority { - /// + /// Api = int.MinValue, /// DalamudSubstitutionProvider = 0, } + + /// The arguments for a EnabledChanged event. + /// Whether Penumbra is now Enabled (true) or Disabled (false). + public readonly record struct Arguments(bool Enabled); } diff --git a/Penumbra/Communication/ModDataChanged.cs b/Penumbra/Communication/ModDataChanged.cs index ffa43d43..325247f5 100644 --- a/Penumbra/Communication/ModDataChanged.cs +++ b/Penumbra/Communication/ModDataChanged.cs @@ -1,17 +1,11 @@ -using OtterGui.Classes; +using Luna; using Penumbra.Mods; using Penumbra.Mods.Manager; namespace Penumbra.Communication; -/// -/// Triggered whenever mod meta data or local data is changed. -/// -/// Parameter is the type of data change for the mod, which can be multiple flags. -/// Parameter is the changed mod. -/// Parameter is the old name of the mod in case of a name change, and null otherwise. -/// -public sealed class ModDataChanged() : EventWrapper(nameof(ModDataChanged)) +/// Triggered whenever mod meta data or local data is changed. +public sealed class ModDataChanged(Logger log) : EventBase(nameof(ModDataChanged), log) { public enum Priority { @@ -27,4 +21,10 @@ public sealed class ModDataChanged() : EventWrapper ModPanelHeader = 0, } + + /// The arguments for a ModDataChanged event. + /// The type of data change for the mod, which can be multiple flags. + /// The changed mod. + /// The old name of the mod in case of a name change, and null otherwise. + public readonly record struct Arguments(ModDataChangeType Type, Mod Mod, string? OldName); } diff --git a/Penumbra/Communication/ModDirectoryChanged.cs b/Penumbra/Communication/ModDirectoryChanged.cs index 9c64573f..2bea68a5 100644 --- a/Penumbra/Communication/ModDirectoryChanged.cs +++ b/Penumbra/Communication/ModDirectoryChanged.cs @@ -1,16 +1,11 @@ -using OtterGui.Classes; +using Luna; using Penumbra.Api.Api; namespace Penumbra.Communication; -/// -/// Triggered whenever the mod root directory changes. -/// -/// Parameter is the full path of the new directory. -/// Parameter is whether the new directory is valid. -/// -/// -public sealed class ModDirectoryChanged() : EventWrapper(nameof(ModDirectoryChanged)) +/// Triggered whenever the mod root directory changes. +public sealed class ModDirectoryChanged(Logger log) + : EventBase(nameof(ModDirectoryChanged), log) { public enum Priority { @@ -20,4 +15,9 @@ public sealed class ModDirectoryChanged() : EventWrapper FileDialogService = 0, } + + /// The arguments for a ModFileChanged event. + /// The full path of the new mod directory. + /// Whether the directory is valid. + public readonly record struct Arguments(string Directory, bool Valid); } diff --git a/Penumbra/Communication/ModDiscoveryFinished.cs b/Penumbra/Communication/ModDiscoveryFinished.cs index 759ea42e..d0f370bd 100644 --- a/Penumbra/Communication/ModDiscoveryFinished.cs +++ b/Penumbra/Communication/ModDiscoveryFinished.cs @@ -1,9 +1,9 @@ -using OtterGui.Classes; +using Luna; namespace Penumbra.Communication; /// Triggered whenever a new mod discovery has finished. -public sealed class ModDiscoveryFinished() : EventWrapper(nameof(ModDiscoveryFinished)) +public sealed class ModDiscoveryFinished(Logger log) : EventBase(nameof(ModDiscoveryFinished), log) { public enum Priority { diff --git a/Penumbra/Communication/ModDiscoveryStarted.cs b/Penumbra/Communication/ModDiscoveryStarted.cs index 5cafd1ea..8edd59d2 100644 --- a/Penumbra/Communication/ModDiscoveryStarted.cs +++ b/Penumbra/Communication/ModDiscoveryStarted.cs @@ -1,9 +1,9 @@ -using OtterGui.Classes; +using Luna; namespace Penumbra.Communication; /// Triggered whenever mods are prepared to be rediscovered. -public sealed class ModDiscoveryStarted() : EventWrapper(nameof(ModDiscoveryStarted)) +public sealed class ModDiscoveryStarted(Logger log) : EventBase(nameof(ModDiscoveryStarted), log) { public enum Priority { diff --git a/Penumbra/Communication/ModFileChanged.cs b/Penumbra/Communication/ModFileChanged.cs index 8cda48e9..d43dce71 100644 --- a/Penumbra/Communication/ModFileChanged.cs +++ b/Penumbra/Communication/ModFileChanged.cs @@ -1,19 +1,12 @@ -using OtterGui.Classes; -using Penumbra.Api; +using Luna; using Penumbra.Api.Api; using Penumbra.Mods; using Penumbra.Mods.Editor; namespace Penumbra.Communication; -/// -/// Triggered whenever an existing file in a mod is overwritten by Penumbra. -/// -/// Parameter is the changed mod. -/// Parameter file registry of the changed file. -/// -public sealed class ModFileChanged() - : EventWrapper(nameof(ModFileChanged)) +/// Triggered whenever an existing file in a mod is overwritten by Penumbra. +public sealed class ModFileChanged(Logger log) : EventBase(nameof(ModFileChanged), log) { public enum Priority { @@ -26,4 +19,9 @@ public sealed class ModFileChanged() /// CollectionStorage = 0, } + + /// The arguments for a ModFileChanged event. + /// The changed mod. + /// The file registry of the changed file. + public readonly record struct Arguments(Mod Mod, FileRegistry File); } diff --git a/Penumbra/Communication/ModOptionChanged.cs b/Penumbra/Communication/ModOptionChanged.cs index 67f2c0c3..76364a99 100644 --- a/Penumbra/Communication/ModOptionChanged.cs +++ b/Penumbra/Communication/ModOptionChanged.cs @@ -1,26 +1,16 @@ -using OtterGui.Classes; +using Luna; using Penumbra.Api.Api; using Penumbra.Mods; using Penumbra.Mods.Groups; using Penumbra.Mods.Manager; using Penumbra.Mods.Manager.OptionEditor; using Penumbra.Mods.SubMods; -using static Penumbra.Communication.ModOptionChanged; namespace Penumbra.Communication; -/// -/// Triggered whenever an option of a mod is changed inside the mod. -/// -/// Parameter is the type option change. -/// Parameter is the changed mod. -/// Parameter is the changed group inside the mod. -/// Parameter is the changed option inside the group or null if it does not concern a specific option. -/// Parameter is the changed data container inside the group or null if it does not concern a specific data container. -/// Parameter is the index of the group or option moved or deleted from. -/// -public sealed class ModOptionChanged() - : EventWrapper(nameof(ModOptionChanged)) +/// Triggered whenever an option of a mod is changed inside the mod. +public sealed class ModOptionChanged(Logger log) + : EventBase(nameof(ModOptionChanged), log) { public enum Priority { @@ -39,4 +29,19 @@ public sealed class ModOptionChanged() /// CollectionStorage = 100, } + + /// The arguments for a ModOptionChanged event. + /// The type of option change for the mod. + /// The changed mod. + /// The changed group inside the mod, if any. + /// The changed option inside the group or null if it does not concern a specific option. + /// The changed data container inside the group or null if it does not concern a specific data container. + /// The index of the group or option moved or deleted from. + public readonly record struct Arguments( + ModOptionChangeType Type, + Mod Mod, + IModGroup? Group, + IModOption? Option, + IModDataContainer? Container, + int DeletedIndex); } diff --git a/Penumbra/Communication/ModPathChanged.cs b/Penumbra/Communication/ModPathChanged.cs index efe59482..afabbf29 100644 --- a/Penumbra/Communication/ModPathChanged.cs +++ b/Penumbra/Communication/ModPathChanged.cs @@ -1,5 +1,4 @@ -using OtterGui.Classes; -using Penumbra.Api; +using Luna; using Penumbra.Api.Api; using Penumbra.Mods; using Penumbra.Mods.Manager; @@ -7,17 +6,9 @@ using Penumbra.Services; namespace Penumbra.Communication; -/// -/// Triggered whenever a mod is added, deleted, moved or reloaded. -/// -/// Parameter is the type of change. -/// Parameter is the changed mod. -/// Parameter is the old directory on deletion, move or reload and null on addition. -/// Parameter is the new directory on addition, move or reload and null on deletion. -/// -/// -public sealed class ModPathChanged() - : EventWrapper(nameof(ModPathChanged)) +/// Triggered whenever a mod is added, deleted, moved or reloaded. +public sealed class ModPathChanged(Logger log) + : EventBase(nameof(ModPathChanged), log) { public enum Priority { @@ -60,4 +51,11 @@ public sealed class ModPathChanged() /// CollectionCacheManagerRemoval = 100, } + + /// The arguments for a ModPathChanged event. + /// The type of change for the mod. + /// The changed mod. + /// The old directory on deletion, move or reload and null on addition. + /// The new directory on addition, move or reload and null on deletion. + public readonly record struct Arguments(ModPathChangeType Type, Mod Mod, DirectoryInfo? OldDirectory, DirectoryInfo? NewDirectory); } diff --git a/Penumbra/Communication/ModSettingChanged.cs b/Penumbra/Communication/ModSettingChanged.cs index d4bf00be..f3628f78 100644 --- a/Penumbra/Communication/ModSettingChanged.cs +++ b/Penumbra/Communication/ModSettingChanged.cs @@ -1,4 +1,4 @@ -using OtterGui.Classes; +using Luna; using Penumbra.Api.Api; using Penumbra.Api.Enums; using Penumbra.Collections; @@ -7,19 +7,9 @@ using Penumbra.Mods.Settings; namespace Penumbra.Communication; -/// -/// Triggered whenever a mod setting is changed. -/// -/// Parameter is the collection in which the setting was changed. -/// Parameter is the type of change. -/// Parameter is the mod the setting was changed for, unless it was a multi-change. -/// Parameter is the old value of the setting before the change as Setting. -/// Parameter is the index of the changed group if the change type is Setting. -/// Parameter is whether the change was inherited from another collection. -/// -/// -public sealed class ModSettingChanged() - : EventWrapper(nameof(ModSettingChanged)) +/// Triggered whenever a mod setting is changed. +public sealed class ModSettingChanged(Logger log) + : EventBase(nameof(ModSettingChanged), log) { public enum Priority { @@ -38,4 +28,19 @@ public sealed class ModSettingChanged() /// ModSelection = 10, } + + /// The arguments for a ModSettingChanged event. + /// The type of change for the mod settings. + /// The collection in which the settings were changed, unless it was a multi-change. + /// The changed mod. + /// The old value of the setting before the change. + /// The index of the changed group if the change type is Setting. + /// Whether the change was inherited from another collection + public readonly record struct Arguments( + ModSettingChange Type, + ModCollection Collection, + Mod? Mod, + Setting OldValue, + int GroupIndex, + bool Inherited); } diff --git a/Penumbra/Communication/MtrlLoaded.cs b/Penumbra/Communication/MtrlLoaded.cs index 224438e5..de2e203a 100644 --- a/Penumbra/Communication/MtrlLoaded.cs +++ b/Penumbra/Communication/MtrlLoaded.cs @@ -1,16 +1,20 @@ -using OtterGui.Classes; +using Luna; +using Penumbra.GameData.Interop; +using Penumbra.Interop.Hooks.PostProcessing; namespace Penumbra.Communication; -/// -/// Parameter is the material resource handle for which the shader package has been loaded. -/// Parameter is the associated game object. -/// -public sealed class MtrlLoaded() : EventWrapper(nameof(MtrlLoaded)) +/// Invoked whenever a material is loaded. +public sealed class MtrlLoaded(Logger log) : EventBase(nameof(MtrlLoaded), log) { public enum Priority { - /// + /// ShaderReplacementFixer = 0, } + + /// The arguments for a MtrlLoaded event. + /// The material resource handle for which the shader package has been loaded. + /// The associated game object + public readonly record struct Arguments(nint MaterialResourceHandle, Actor GameObject); } diff --git a/Penumbra/Communication/PcpCreation.cs b/Penumbra/Communication/PcpCreation.cs index ca0cfcf6..34273010 100644 --- a/Penumbra/Communication/PcpCreation.cs +++ b/Penumbra/Communication/PcpCreation.cs @@ -1,21 +1,21 @@ +using Luna; using Newtonsoft.Json.Linq; -using OtterGui.Classes; +using Penumbra.GameData.Structs; namespace Penumbra.Communication; -/// -/// Triggered when the character.json file for a .pcp file is written. -/// -/// Parameter is the JObject that gets written to file. -/// Parameter is the object index of the game object this is written for. -/// Parameter is the full path to the directory being set up for the PCP creation. -/// -/// -public sealed class PcpCreation() : EventWrapper(nameof(PcpCreation)) +/// Triggered when the character.json file for a .pcp file is written. +public sealed class PcpCreation(Logger log) : EventBase(nameof(PcpCreation), log) { public enum Priority { /// - ModsApi = int.MinValue, + ApiMods = int.MinValue, } + + /// The arguments for a PcpCreation event. + /// The JObject that gets written to file. + /// The object index of the game object this is written for. + /// The full path to the directory being set up for the PCP creation. + public readonly record struct Arguments(JObject JObject, ObjectIndex ObjectIndex, string DirectoryPath); } diff --git a/Penumbra/Communication/PcpParsing.cs b/Penumbra/Communication/PcpParsing.cs index 95b78951..2c2332c3 100644 --- a/Penumbra/Communication/PcpParsing.cs +++ b/Penumbra/Communication/PcpParsing.cs @@ -1,21 +1,22 @@ +using Luna; using Newtonsoft.Json.Linq; -using OtterGui.Classes; +using Penumbra.Collections; +using Penumbra.Mods; namespace Penumbra.Communication; -/// -/// Triggered when the character.json file for a .pcp file is parsed and applied. -/// -/// Parameter is parsed JObject that contains the data. -/// Parameter is the identifier of the created mod. -/// Parameter is the GUID of the created collection. -/// -/// -public sealed class PcpParsing() : EventWrapper(nameof(PcpParsing)) +/// Triggered when the character.json file for a .pcp file is parsed and applied. +public sealed class PcpParsing(Logger log) : EventBase(nameof(PcpParsing), log) { public enum Priority { /// - ModsApi = int.MinValue, + ApiMods = int.MinValue, } + + /// The arguments for a PcpParsing event. + /// The parsed JObject that contains the data. + /// The created mod. + /// The created collection, if any. + public readonly record struct Arguments(JObject JObject, Mod Mod, ModCollection? Collection); } diff --git a/Penumbra/Communication/PostEnabledDraw.cs b/Penumbra/Communication/PostEnabledDraw.cs index e21f0183..69955ed2 100644 --- a/Penumbra/Communication/PostEnabledDraw.cs +++ b/Penumbra/Communication/PostEnabledDraw.cs @@ -1,19 +1,19 @@ -using OtterGui.Classes; +using Luna; using Penumbra.Api.Api; +using Penumbra.Mods; namespace Penumbra.Communication; -/// -/// Triggered after the Enabled Checkbox line in settings is drawn, but before options are drawn. -/// -/// Parameter is the identifier (directory name) of the currently selected mod. -/// -/// -public sealed class PostEnabledDraw() : EventWrapper(nameof(PostEnabledDraw)) +/// Triggered after the Enabled Checkbox line in settings is drawn, but before options are drawn. +public sealed class PostEnabledDraw(Logger log) : EventBase(nameof(PostEnabledDraw), log) { public enum Priority { /// Default = 0, } + + /// The arguments for a PostEnabledDraw event. + /// The mod currently being drawn. + public readonly record struct Arguments(Mod Mod); } diff --git a/Penumbra/Communication/PostSettingsPanelDraw.cs b/Penumbra/Communication/PostSettingsPanelDraw.cs index 525ac73e..1b491041 100644 --- a/Penumbra/Communication/PostSettingsPanelDraw.cs +++ b/Penumbra/Communication/PostSettingsPanelDraw.cs @@ -1,19 +1,19 @@ -using OtterGui.Classes; +using Luna; using Penumbra.Api.Api; +using Penumbra.Mods; namespace Penumbra.Communication; -/// -/// Triggered after the settings panel is drawn. -/// -/// Parameter is the identifier (directory name) of the currently selected mod. -/// -/// -public sealed class PostSettingsPanelDraw() : EventWrapper(nameof(PostSettingsPanelDraw)) +/// Triggered after the settings panel is drawn. +public sealed class PostSettingsPanelDraw(Logger log) : EventBase(nameof(PostSettingsPanelDraw), log) { public enum Priority { /// Default = 0, } + + /// The arguments for a PostSettingsPanelDraw event. + /// The mod currently being drawn. + public readonly record struct Arguments(Mod Mod); } diff --git a/Penumbra/Communication/PreSettingsPanelDraw.cs b/Penumbra/Communication/PreSettingsPanelDraw.cs index 33f6b4e1..dfe547a4 100644 --- a/Penumbra/Communication/PreSettingsPanelDraw.cs +++ b/Penumbra/Communication/PreSettingsPanelDraw.cs @@ -1,19 +1,19 @@ -using OtterGui.Classes; +using Luna; using Penumbra.Api.Api; +using Penumbra.Mods; namespace Penumbra.Communication; -/// -/// Triggered before the settings panel is drawn. -/// -/// Parameter is the identifier (directory name) of the currently selected mod. -/// -/// -public sealed class PreSettingsPanelDraw() : EventWrapper(nameof(PreSettingsPanelDraw)) +/// Triggered before the settings panel is drawn. +public sealed class PreSettingsPanelDraw(Logger log) : EventBase(nameof(PreSettingsPanelDraw), log) { public enum Priority { /// Default = 0, } + + /// The arguments for a PreSettingsPanelDraw event. + /// The mod currently being drawn. + public readonly record struct Arguments(Mod Mod); } diff --git a/Penumbra/Communication/PreSettingsTabBarDraw.cs b/Penumbra/Communication/PreSettingsTabBarDraw.cs index e1d67297..76e0d1e7 100644 --- a/Penumbra/Communication/PreSettingsTabBarDraw.cs +++ b/Penumbra/Communication/PreSettingsTabBarDraw.cs @@ -1,22 +1,21 @@ -using OtterGui.Classes; -using Penumbra.Api.Api; -using Penumbra.Api.IpcSubscribers; +using Luna; +using Penumbra.Mods; namespace Penumbra.Communication; -/// -/// Triggered before the settings tab bar for a mod is drawn, after the title group is drawn. -/// -/// Parameter is the identifier (directory name) of the currently selected mod. -/// is the total width of the header group. -/// is the width of the title box. -/// -/// -public sealed class PreSettingsTabBarDraw() : EventWrapper(nameof(PreSettingsTabBarDraw)) +/// Triggered before the settings tab bar for a mod is drawn, after the title group is drawn. +public sealed class PreSettingsTabBarDraw(Logger log) + : EventBase(nameof(PreSettingsTabBarDraw), log) { public enum Priority { /// Default = 0, } + + /// The arguments for a PreSettingsTabBarDraw event. + /// The mod currently being drawn. + /// The total width of the header group. + /// The width of the title box. + public readonly record struct Arguments(Mod Mod, float HeaderWidth, float TitleBoxWidth); } diff --git a/Penumbra/Communication/ResolvedFileChanged.cs b/Penumbra/Communication/ResolvedFileChanged.cs index 0c91a18b..b9c220ef 100644 --- a/Penumbra/Communication/ResolvedFileChanged.cs +++ b/Penumbra/Communication/ResolvedFileChanged.cs @@ -1,23 +1,13 @@ -using OtterGui.Classes; +using Luna; using Penumbra.Collections; using Penumbra.Mods.Editor; using Penumbra.String.Classes; namespace Penumbra.Communication; -/// -/// Triggered whenever a redirection in a mod collection cache is manipulated. -/// -/// Parameter is collection with a changed cache. -/// Parameter is the type of change. -/// Parameter is the game path to be redirected or empty for FullRecompute. -/// Parameter is the new redirection path or empty for Removed or FullRecompute -/// Parameter is the old redirection path for Replaced, or empty. -/// Parameter is the mod responsible for the new redirection if any. -/// -public sealed class ResolvedFileChanged() - : EventWrapper( - nameof(ResolvedFileChanged)) +/// Triggered whenever a redirection in a mod collection cache is manipulated. +public sealed class ResolvedFileChanged(Logger log) : EventBase( + nameof(ResolvedFileChanged), log) { public enum Type { @@ -36,4 +26,19 @@ public sealed class ResolvedFileChanged() /// SchedulerResourceManagementService = 0, } + + /// The arguments for a ResolvedFileChanged event. + /// The type of the redirection change. + /// The collection with a changed cache. + /// The game path to be redirected or empty for FullRecompute + /// The new redirection path or empty for Removed or FullRecompute. + /// The old redirection path for Replaced, or empty. + /// The mod responsible for the new redirection if any. + public readonly record struct Arguments( + Type Type, + ModCollection Collection, + Utf8GamePath GamePath, + FullPath OldRedirection, + FullPath NewRedirection, + IMod? Mod); } diff --git a/Penumbra/Communication/SelectTab.cs b/Penumbra/Communication/SelectTab.cs index cb7e2e56..144b362a 100644 --- a/Penumbra/Communication/SelectTab.cs +++ b/Penumbra/Communication/SelectTab.cs @@ -1,21 +1,20 @@ -using OtterGui.Classes; +using Luna; using Penumbra.Api.Enums; using Penumbra.Mods; namespace Penumbra.Communication; -/// -/// Trigger to select a tab and mod in the Config Window. -/// -/// Parameter is the selected tab. -/// Parameter is the selected mod, if any. -/// -/// -public sealed class SelectTab() : EventWrapper(nameof(SelectTab)) +/// Trigger to select a tab and mod in the Config Window. +public sealed class SelectTab(Logger log) : EventBase(nameof(SelectTab), log) { public enum Priority { /// ConfigTabBar = 0, } + + /// The arguments for a SelectTab event. + /// The selected tab. + /// The selected mod, if any. + public readonly record struct Arguments(TabType Tab, Mod? Mod); } diff --git a/Penumbra/Communication/TemporaryGlobalModChange.cs b/Penumbra/Communication/TemporaryGlobalModChange.cs index 6edf26d7..e6aa9409 100644 --- a/Penumbra/Communication/TemporaryGlobalModChange.cs +++ b/Penumbra/Communication/TemporaryGlobalModChange.cs @@ -1,17 +1,11 @@ -using OtterGui.Classes; +using Luna; using Penumbra.Mods; namespace Penumbra.Communication; -/// -/// Triggered whenever a temporary mod for all collections is changed. -/// -/// Parameter added, deleted or edited temporary mod. -/// Parameter is whether the mod was newly created. -/// Parameter is whether the mod was deleted. -/// -public sealed class TemporaryGlobalModChange() - : EventWrapper(nameof(TemporaryGlobalModChange)) +/// Triggered whenever a temporary mod for all collections is changed. +public sealed class TemporaryGlobalModChange(Logger log) + : EventBase(nameof(TemporaryGlobalModChange), log) { public enum Priority { @@ -21,4 +15,10 @@ public sealed class TemporaryGlobalModChange() /// TempCollectionManager = 0, } + + /// The arguments for a TemporaryGlobalModChange event. + /// The changed mod. + /// The changed mod. + /// The changed mod. + public readonly record struct Arguments(TemporaryMod Mod, bool NewlyCreated, bool Deleted); } diff --git a/Penumbra/EphemeralConfig.cs b/Penumbra/EphemeralConfig.cs index 475c32ad..1cfca3da 100644 --- a/Penumbra/EphemeralConfig.cs +++ b/Penumbra/EphemeralConfig.cs @@ -106,12 +106,13 @@ public class EphemeralConfig : ISavable, IDisposable, IService } /// Overwrite the last saved mod path if it changes. - private void OnModPathChanged(ModPathChangeType type, Mod mod, DirectoryInfo? old, DirectoryInfo? _) + private void OnModPathChanged(in ModPathChanged.Arguments arguments) { - if (type is not ModPathChangeType.Moved || !string.Equals(old?.Name, LastModPath, StringComparison.OrdinalIgnoreCase)) + if (arguments.Type is not ModPathChangeType.Moved + || !string.Equals(arguments.OldDirectory?.Name, LastModPath, StringComparison.OrdinalIgnoreCase)) return; - LastModPath = mod.Identifier; + LastModPath = arguments.Mod.Identifier; Save(); } } diff --git a/Penumbra/Interop/Hooks/Objects/CharacterBaseDestructor.cs b/Penumbra/Interop/Hooks/Objects/CharacterBaseDestructor.cs index ae3b38b3..9d91b6df 100644 --- a/Penumbra/Interop/Hooks/Objects/CharacterBaseDestructor.cs +++ b/Penumbra/Interop/Hooks/Objects/CharacterBaseDestructor.cs @@ -1,10 +1,12 @@ using Dalamud.Hooking; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; -using OtterGui.Classes; +using Luna; +using Penumbra.GameData.Interop; namespace Penumbra.Interop.Hooks.Objects; -public sealed unsafe class CharacterBaseDestructor : EventWrapperPtr, Luna.IHookService +public sealed unsafe class CharacterBaseDestructor : EventBase, + IHookService { public enum Priority { @@ -15,8 +17,8 @@ public sealed unsafe class CharacterBaseDestructor : EventWrapperPtr _task = hooks.CreateHook(Name, Address, Detour, !HookOverrides.Instance.Objects.CharacterBaseDestructor); private readonly Task> _task; @@ -41,7 +43,11 @@ public sealed unsafe class CharacterBaseDestructor : EventWrapperPtr The arguments for a character base destructor event. + /// The model that is being destroyed. + public readonly record struct Arguments(Model CharacterBase); } diff --git a/Penumbra/Interop/Hooks/Objects/CharacterDestructor.cs b/Penumbra/Interop/Hooks/Objects/CharacterDestructor.cs index 518b31a5..31757850 100644 --- a/Penumbra/Interop/Hooks/Objects/CharacterDestructor.cs +++ b/Penumbra/Interop/Hooks/Objects/CharacterDestructor.cs @@ -1,11 +1,12 @@ using Dalamud.Hooking; using FFXIVClientStructs.FFXIV.Client.Game.Character; -using OtterGui.Classes; +using Luna; using Penumbra.GameData; +using Penumbra.GameData.Interop; namespace Penumbra.Interop.Hooks.Objects; -public sealed unsafe class CharacterDestructor : EventWrapperPtr, Luna.IHookService +public sealed unsafe class CharacterDestructor : EventBase, IHookService { public enum Priority { @@ -19,8 +20,8 @@ public sealed unsafe class CharacterDestructor : EventWrapperPtr _task = hooks.CreateHook(Name, Sigs.CharacterDestructor, Detour, !HookOverrides.Instance.Objects.CharacterDestructor); private readonly Task> _task; @@ -45,7 +46,11 @@ public sealed unsafe class CharacterDestructor : EventWrapperPtr The arguments for a character destructor event. + /// The game object that is being destroyed. + public readonly record struct Arguments(Actor Character); } diff --git a/Penumbra/Interop/Hooks/Objects/ConstructCutsceneCharacter.cs b/Penumbra/Interop/Hooks/Objects/ConstructCutsceneCharacter.cs index 68877176..99e6ea0b 100644 --- a/Penumbra/Interop/Hooks/Objects/ConstructCutsceneCharacter.cs +++ b/Penumbra/Interop/Hooks/Objects/ConstructCutsceneCharacter.cs @@ -1,13 +1,12 @@ using Dalamud.Hooking; -using FFXIVClientStructs.FFXIV.Client.Game.Character; -using OtterGui.Classes; +using Luna; using Penumbra.GameData; using Penumbra.GameData.Enums; using Penumbra.GameData.Interop; namespace Penumbra.Interop.Hooks.Objects; -public sealed unsafe class ConstructCutsceneCharacter : EventWrapperPtr, Luna.IHookService +public sealed unsafe class ConstructCutsceneCharacter : EventBase, IHookService { private readonly GameState _gameState; private readonly ObjectManager _objects; @@ -18,8 +17,8 @@ public sealed unsafe class ConstructCutsceneCharacter : EventWrapperPtrObjectIndex}."); } @@ -66,4 +65,8 @@ public sealed unsafe class ConstructCutsceneCharacter : EventWrapperPtr _task.IsCompletedSuccessfully; + + /// The arguments for a construct cutscene character event. + /// The game object that is being destroyed. + public readonly record struct Arguments(Actor Character); } diff --git a/Penumbra/Interop/Hooks/Objects/CopyCharacter.cs b/Penumbra/Interop/Hooks/Objects/CopyCharacter.cs index 1628b9fb..374799f7 100644 --- a/Penumbra/Interop/Hooks/Objects/CopyCharacter.cs +++ b/Penumbra/Interop/Hooks/Objects/CopyCharacter.cs @@ -1,19 +1,20 @@ -using Dalamud.Hooking; -using FFXIVClientStructs.FFXIV.Client.Game.Character; -using OtterGui.Classes; - -namespace Penumbra.Interop.Hooks.Objects; - -public sealed unsafe class CopyCharacter : EventWrapperPtr, Luna.IHookService -{ +using Dalamud.Hooking; +using FFXIVClientStructs.FFXIV.Client.Game.Character; +using Luna; +using Penumbra.GameData.Interop; + +namespace Penumbra.Interop.Hooks.Objects; + +public sealed unsafe class CopyCharacter : EventBase, IHookService +{ public enum Priority { /// CutsceneService = 0, } - public CopyCharacter(Luna.HookManager hooks) - : base("Copy Character") + public CopyCharacter(Logger log, HookManager hooks) + : base("Copy Character", log) => _task = hooks.CreateHook(Name, Address, Detour, !HookOverrides.Instance.Objects.CopyCharacter); private readonly Task> _task; @@ -39,7 +40,12 @@ public sealed unsafe class CopyCharacter : EventWrapperPtrOwnerObject; Penumbra.Log.Verbose($"[{Name}] Triggered with target: 0x{(nint)target:X}, source : 0x{(nint)source:X} unk: {unk}."); - Invoke(character, source); + Invoke(new Arguments(character, source)); return _task.Result.Original(target, source, unk); } -} + + /// The arguments for a copy character event. + /// The character that is being created by a copy. + /// The character that is being copied. + public readonly record struct Arguments(Actor TargetCharacter, Actor SourceCharacter); +} diff --git a/Penumbra/Interop/Hooks/Objects/CreateCharacterBase.cs b/Penumbra/Interop/Hooks/Objects/CreateCharacterBase.cs index fa5d87ce..15f7a9d0 100644 --- a/Penumbra/Interop/Hooks/Objects/CreateCharacterBase.cs +++ b/Penumbra/Interop/Hooks/Objects/CreateCharacterBase.cs @@ -1,21 +1,25 @@ using Dalamud.Hooking; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; -using OtterGui.Classes; +using Luna; +using Penumbra.GameData.Interop; using Penumbra.GameData.Structs; namespace Penumbra.Interop.Hooks.Objects; -public sealed unsafe class CreateCharacterBase : EventWrapperPtr, Luna.IHookService -{ +public sealed unsafe class CreateCharacterBase : EventBase, IHookService +{ public enum Priority { /// MetaState = 0, } - public CreateCharacterBase(Luna.HookManager hooks) - : base("Create CharacterBase") - => _task = hooks.CreateHook(Name, Address, Detour, !HookOverrides.Instance.Objects.CreateCharacterBase); + public CreateCharacterBase(Logger log, HookManager hooks) + : base("Create CharacterBase", log) + { + _postEvent = new PostEvent("Created CharacterBase", log); + _task = hooks.CreateHook(Name, Address, Detour, !HookOverrides.Instance.Objects.CreateCharacterBase); + } private readonly Task> _task; @@ -38,36 +42,52 @@ public sealed unsafe class CreateCharacterBase : EventWrapperPtr subscriber, PostEvent.Priority priority) + public void Subscribe(InAction subscriber, PostEvent.Priority priority) => _postEvent.Subscribe(subscriber, priority); - public void Unsubscribe(ActionPtr234 subscriber) + public void Unsubscribe(InAction subscriber) => _postEvent.Unsubscribe(subscriber); - private readonly PostEvent _postEvent = new("Created CharacterBase"); + private readonly PostEvent _postEvent; protected override void Dispose(bool disposing) { _postEvent.Dispose(); } - public class PostEvent(string name) : EventWrapperPtr234(name) - { + public class PostEvent(string name, Logger log) : EventBase(name, log) + { public enum Priority { /// - DrawObjectState = 0, + DrawObjectState = 0, /// MetaState = 0, } + + public readonly struct Arguments(ModelCharaId modelCharaId, CustomizeArray* customize, CharacterArmor* equipment, Model characterBase) + { + public readonly ModelCharaId ModelCharaId = modelCharaId; + public readonly CustomizeArray* Customize = customize; + public readonly CharacterArmor* Equipment = equipment; + public readonly Model CharacterBase = characterBase; + } + } + + public readonly ref struct Arguments(ref ModelCharaId modelCharaId, CustomizeArray* customize, CharacterArmor* equipment) + { + public readonly ref ModelCharaId ModelCharaId = ref modelCharaId; + public readonly CustomizeArray* Customize = customize; + public readonly CharacterArmor* Equipment = equipment; } } diff --git a/Penumbra/Interop/Hooks/Objects/WeaponReload.cs b/Penumbra/Interop/Hooks/Objects/WeaponReload.cs index 247bbe27..bbf63a34 100644 --- a/Penumbra/Interop/Hooks/Objects/WeaponReload.cs +++ b/Penumbra/Interop/Hooks/Objects/WeaponReload.cs @@ -1,11 +1,12 @@ using Dalamud.Hooking; using FFXIVClientStructs.FFXIV.Client.Game.Character; -using OtterGui.Classes; +using Luna; +using Penumbra.GameData.Interop; using Penumbra.GameData.Structs; namespace Penumbra.Interop.Hooks.Objects; -public sealed unsafe class WeaponReload : EventWrapperPtr, Luna.IHookService +public sealed unsafe class WeaponReload : EventBase, IHookService { public enum Priority { @@ -13,9 +14,12 @@ public sealed unsafe class WeaponReload : EventWrapperPtr _task = hooks.CreateHook(Name, Address, Detour, !HookOverrides.Instance.Objects.WeaponReload); + public WeaponReload(Logger log, HookManager hooks) + : base("Reload Weapon", log) + { + _postEvent = new PostEvent("Created CharacterBase", log); + _task = hooks.CreateHook(Name, Address, Detour, !HookOverrides.Instance.Objects.WeaponReload); + } private readonly Task> _task; @@ -40,31 +44,44 @@ public sealed unsafe class WeaponReload : EventWrapperPtrOwnerObject; Penumbra.Log.Verbose($"[{Name}] Triggered with drawData: 0x{(nint)drawData:X}, {slot}, {weapon}, {d}, {e}, {f}, {g}, {h}."); - Invoke(drawData, gameObject, (CharacterWeapon*)(&weapon)); + Invoke(new Arguments(ref *drawData, gameObject, ref *(CharacterWeapon*)(&weapon))); _task.Result.Original(drawData, slot, weapon, d, e, f, g, h); - _postEvent.Invoke(drawData, gameObject); + _postEvent.Invoke(new PostEvent.Arguments(ref *drawData, gameObject)); } - public void Subscribe(ActionPtr subscriber, PostEvent.Priority priority) + public void Subscribe(InAction subscriber, PostEvent.Priority priority) => _postEvent.Subscribe(subscriber, priority); - public void Unsubscribe(ActionPtr subscriber) + public void Unsubscribe(InAction subscriber) => _postEvent.Unsubscribe(subscriber); - private readonly PostEvent _postEvent = new("Created CharacterBase"); + private readonly PostEvent _postEvent; protected override void Dispose(bool disposing) { _postEvent.Dispose(); } - public class PostEvent(string name) : EventWrapperPtr(name) - { + public class PostEvent(string name, Logger log) : EventBase(name, log) + { public enum Priority { /// DrawObjectState = 0, } + + public readonly ref struct Arguments(ref DrawDataContainer drawData, Actor owner) + { + public readonly ref DrawDataContainer DrawDataContainer = ref drawData; + public readonly Actor Owner = owner; + } + } + + public readonly ref struct Arguments(ref DrawDataContainer drawData, Actor owner, ref CharacterWeapon weapon) + { + public readonly ref DrawDataContainer DrawDataContainer = ref drawData; + public readonly Actor Owner = owner; + public readonly ref CharacterWeapon Weapon = ref weapon; } } diff --git a/Penumbra/Interop/Hooks/PostProcessing/AttributeHook.cs b/Penumbra/Interop/Hooks/PostProcessing/AttributeHook.cs index 6bb013a4..18c933bd 100644 --- a/Penumbra/Interop/Hooks/PostProcessing/AttributeHook.cs +++ b/Penumbra/Interop/Hooks/PostProcessing/AttributeHook.cs @@ -1,6 +1,6 @@ using Dalamud.Hooking; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; -using OtterGui.Classes; +using Luna; using Penumbra.Collections; using Penumbra.GameData; using Penumbra.GameData.Interop; @@ -17,7 +17,7 @@ namespace Penumbra.Interop.Hooks.PostProcessing; /// Parameter is the collection associated with the game object. /// Parameter is the slot that was recomputed. If this is Unknown, it is a general new update call. /// -public sealed unsafe class AttributeHook : EventWrapper, Luna.IHookService +public sealed unsafe class AttributeHook : EventBase, IHookService { public enum Priority { @@ -28,8 +28,8 @@ public sealed unsafe class AttributeHook : EventWrapper _task.Result.Dispose(); } diff --git a/Penumbra/Interop/Hooks/PostProcessing/ShaderReplacementFixer.cs b/Penumbra/Interop/Hooks/PostProcessing/ShaderReplacementFixer.cs index a7964223..35c4fe05 100644 --- a/Penumbra/Interop/Hooks/PostProcessing/ShaderReplacementFixer.cs +++ b/Penumbra/Interop/Hooks/PostProcessing/ShaderReplacementFixer.cs @@ -185,9 +185,9 @@ public sealed unsafe class ShaderReplacementFixer : IDisposable, IRequiredServic _characterOcclusionState.GetAndResetSlowPathCallDelta(), _hairMaskState.GetAndResetSlowPathCallDelta()); - private void OnMtrlLoaded(nint mtrlResourceHandle, nint gameObject) + private void OnMtrlLoaded(in MtrlLoaded.Arguments arguments) { - var mtrl = (MaterialResourceHandle*)mtrlResourceHandle; + var mtrl = (MaterialResourceHandle*)arguments.MaterialResourceHandle; var shpk = mtrl->ShaderPackageResourceHandle; if (shpk == null) return; @@ -199,20 +199,20 @@ public sealed unsafe class ShaderReplacementFixer : IDisposable, IRequiredServic ?? GetStateForModelRendererUnk(shpkName) ?? GetStateForColorTable(shpkName); if (shpkState != null && shpk != shpkState.DefaultShaderPackage) - shpkState.TryAddMaterial(mtrlResourceHandle); + shpkState.TryAddMaterial(arguments.MaterialResourceHandle); } - private void OnResourceHandleDestructor(Structs.ResourceHandle* handle) + private void OnResourceHandleDestructor(in ResourceHandleDestructor.Arguments arguments) { - _skinState.TryRemoveMaterial(handle); - _characterStockingsState.TryRemoveMaterial(handle); - _characterLegacyState.TryRemoveMaterial(handle); - _irisState.TryRemoveMaterial(handle); - _characterGlassState.TryRemoveMaterial(handle); - _characterTransparencyState.TryRemoveMaterial(handle); - _characterTattooState.TryRemoveMaterial(handle); - _characterOcclusionState.TryRemoveMaterial(handle); - _hairMaskState.TryRemoveMaterial(handle); + _skinState.TryRemoveMaterial(arguments.ResourceHandle); + _characterStockingsState.TryRemoveMaterial(arguments.ResourceHandle); + _characterLegacyState.TryRemoveMaterial(arguments.ResourceHandle); + _irisState.TryRemoveMaterial(arguments.ResourceHandle); + _characterGlassState.TryRemoveMaterial(arguments.ResourceHandle); + _characterTransparencyState.TryRemoveMaterial(arguments.ResourceHandle); + _characterTattooState.TryRemoveMaterial(arguments.ResourceHandle); + _characterOcclusionState.TryRemoveMaterial(arguments.ResourceHandle); + _hairMaskState.TryRemoveMaterial(arguments.ResourceHandle); } private ModdedShaderPackageState? GetStateForHumanSetup(MaterialResourceHandle* mtrlResource) diff --git a/Penumbra/Interop/Hooks/ResourceLoading/ResourceLoader.cs b/Penumbra/Interop/Hooks/ResourceLoading/ResourceLoader.cs index 3ecffeee..42c8fb2b 100644 --- a/Penumbra/Interop/Hooks/ResourceLoading/ResourceLoader.cs +++ b/Penumbra/Interop/Hooks/ResourceLoading/ResourceLoader.cs @@ -347,9 +347,9 @@ public unsafe class ResourceLoader : IDisposable, Luna.IService returnValue = 1; } - private void ResourceDestructorHandler(ResourceHandle* handle) + private void ResourceDestructorHandler(in ResourceHandleDestructor.Arguments arguments) { - _ongoingLoads.TryRemove((nint)handle, out _); + _ongoingLoads.TryRemove((nint)arguments.ResourceHandle, out _); } /// Compute the CRC32 hash for a given path together with potential resource parameters. diff --git a/Penumbra/Interop/Hooks/Resources/LoadMtrl.cs b/Penumbra/Interop/Hooks/Resources/LoadMtrl.cs index f56177e4..bf7584f0 100644 --- a/Penumbra/Interop/Hooks/Resources/LoadMtrl.cs +++ b/Penumbra/Interop/Hooks/Resources/LoadMtrl.cs @@ -1,5 +1,6 @@ using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle; using OtterGui.Services; +using Penumbra.Communication; using Penumbra.GameData; using Penumbra.Services; @@ -26,7 +27,7 @@ public sealed unsafe class LoadMtrl : FastHook _gameState.MtrlData.Value = mtrlData; var ret = Task.Result.Original(handle, unk1, unk2); _gameState.MtrlData.Value = last; - _communicator.MtrlLoaded.Invoke((nint)handle, mtrlData.AssociatedGameObject); + _communicator.MtrlLoaded.Invoke(new MtrlLoaded.Arguments((nint)handle, mtrlData.AssociatedGameObject)); return ret; } } diff --git a/Penumbra/Interop/Hooks/Resources/ResourceHandleDestructor.cs b/Penumbra/Interop/Hooks/Resources/ResourceHandleDestructor.cs index 88c9cbe8..9102cdf7 100644 --- a/Penumbra/Interop/Hooks/Resources/ResourceHandleDestructor.cs +++ b/Penumbra/Interop/Hooks/Resources/ResourceHandleDestructor.cs @@ -1,12 +1,12 @@ using Dalamud.Hooking; -using OtterGui.Classes; +using Luna; using Penumbra.GameData; using Penumbra.Interop.Structs; using Penumbra.UI.ResourceWatcher; namespace Penumbra.Interop.Hooks.Resources; -public sealed unsafe class ResourceHandleDestructor : EventWrapperPtr, Luna.IHookService +public sealed unsafe class ResourceHandleDestructor : EventBase, IHookService { public enum Priority { @@ -23,8 +23,8 @@ public sealed unsafe class ResourceHandleDestructor : EventWrapperPtr _task = hooks.CreateHook(Name, Sigs.ResourceHandleDestructor, Detour, !HookOverrides.Instance.Resources.ResourceHandleDestructor); @@ -50,7 +50,12 @@ public sealed unsafe class ResourceHandleDestructor : EventWrapperPtr _objects[i].Valid) .Select(i => KeyValuePair.Create(i, this[i] ?? _objects.GetDalamudObject(i)!)); - public unsafe CutsceneService(ObjectManager objects, CopyCharacter copyCharacter, CharacterDestructor characterDestructor, + public CutsceneService(ObjectManager objects, CopyCharacter copyCharacter, CharacterDestructor characterDestructor, ConstructCutsceneCharacter constructCutsceneCharacter, IClientState clientState) { _objects = objects; @@ -85,15 +84,16 @@ public sealed class CutsceneService : Luna.IRequiredService, IDisposable return -1; } - public unsafe void Dispose() + public void Dispose() { _copyCharacter.Unsubscribe(OnCharacterCopy); _characterDestructor.Unsubscribe(OnCharacterDestructor); _constructCutsceneCharacter.Unsubscribe(OnSetupPlayerNpc); } - private unsafe void OnCharacterDestructor(Character* character) + private unsafe void OnCharacterDestructor(in CharacterDestructor.Arguments arguments) { + var character = arguments.Character.AsCharacter; if (character->GameObject.ObjectIndex < CutsceneStartIdx) { // Remove all associations for now non-existing actor. @@ -118,21 +118,21 @@ public sealed class CutsceneService : Luna.IRequiredService, IDisposable } } - private unsafe void OnCharacterCopy(Character* target, Character* source) + private void OnCharacterCopy(in CopyCharacter.Arguments arguments) { - if (target == null || target->GameObject.ObjectIndex is < CutsceneStartIdx or >= CutsceneEndIdx) + if (!arguments.TargetCharacter.Valid || arguments.TargetCharacter.Index.Index is < CutsceneStartIdx or >= CutsceneEndIdx) return; - var idx = target->GameObject.ObjectIndex - CutsceneStartIdx; - _copiedCharacters[idx] = (short)(source != null ? source->GameObject.ObjectIndex : -1); + var idx = arguments.TargetCharacter.Index.Index - CutsceneStartIdx; + _copiedCharacters[idx] = (short)(arguments.SourceCharacter.Valid ? arguments.SourceCharacter.Index : -1); } - private unsafe void OnSetupPlayerNpc(Character* npc) + private void OnSetupPlayerNpc(in ConstructCutsceneCharacter.Arguments arguments) { - if (npc == null || npc->ObjectIndex is < CutsceneStartIdx or >= CutsceneEndIdx) + if (!arguments.Character.Valid || arguments.Character.Index.Index is < CutsceneStartIdx or >= CutsceneEndIdx) return; - var idx = npc->GameObject.ObjectIndex - CutsceneStartIdx; + var idx = arguments.Character.Index.Index - CutsceneStartIdx; _copiedCharacters[idx] = 0; } diff --git a/Penumbra/Interop/PathResolving/DrawObjectState.cs b/Penumbra/Interop/PathResolving/DrawObjectState.cs index 69d9096a..288b669f 100644 --- a/Penumbra/Interop/PathResolving/DrawObjectState.cs +++ b/Penumbra/Interop/PathResolving/DrawObjectState.cs @@ -1,6 +1,4 @@ using Dalamud.Plugin.Services; -using FFXIVClientStructs.FFXIV.Client.Game.Character; -using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using Penumbra.GameData.Interop; using Object = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.Object; using Penumbra.GameData.Structs; @@ -22,7 +20,7 @@ public sealed class DrawObjectState : IDisposable, IReadOnlyDictionary _gameState.LastGameObject; - public unsafe DrawObjectState(ObjectManager objects, CreateCharacterBase createCharacterBase, WeaponReload weaponReload, + public DrawObjectState(ObjectManager objects, CreateCharacterBase createCharacterBase, WeaponReload weaponReload, CharacterBaseDestructor characterBaseDestructor, GameState gameState, IFramework framework, CharacterDestructor characterDestructor) { _objects = objects; @@ -76,7 +74,7 @@ public sealed class DrawObjectState : IDisposable, IReadOnlyDictionary Values => _drawObjectToGameObject.Values; - public unsafe void Dispose() + public void Dispose() { _weaponReload.Unsubscribe(OnWeaponReloading); _weaponReload.Unsubscribe(OnWeaponReloaded); @@ -89,17 +87,16 @@ public sealed class DrawObjectState : IDisposable, IReadOnlyDictionary - private unsafe void OnCharacterDestructor(Character* a) + private unsafe void OnCharacterDestructor(in CharacterDestructor.Arguments arguments) { - if (a is null) + if (!arguments.Character.Valid) return; - var character = (nint)a; var delete = stackalloc nint[5]; var current = 0; foreach (var (drawObject, (gameObject, _, _)) in _drawObjectToGameObject) { - if (gameObject != character) + if (gameObject != arguments.Character.Address) continue; delete[current++] = drawObject; @@ -111,28 +108,27 @@ public sealed class DrawObjectState : IDisposable, IReadOnlyDictionary 0x{(nint)a:X} (actual: 0x{pair.GameObject.Address:X}, {pair.IsChild})."); + $"[DrawObjectState] Removed draw object 0x{*ptr:X} -> 0x{arguments.Character.Address:X} (actual: 0x{pair.GameObject.Address:X}, {pair.IsChild})."); } } - private unsafe void OnWeaponReloading(DrawDataContainer* _, Character* character, CharacterWeapon* _2) - => _gameState.QueueGameObject((nint)character); + private void OnWeaponReloading(in WeaponReload.Arguments arguments) + => _gameState.QueueGameObject(arguments.Owner); - private unsafe void OnWeaponReloaded(DrawDataContainer* _, Character* character) + private unsafe void OnWeaponReloaded(in WeaponReload.PostEvent.Arguments arguments) { _gameState.DequeueGameObject(); - IterateDrawObjectTree((Object*)character->GameObject.DrawObject, (nint)character, false, false); + IterateDrawObjectTree((Object*)arguments.Owner.Model.Address, arguments.Owner, false, false); } - private unsafe void OnCharacterBaseDestructor(CharacterBase* characterBase) - => _drawObjectToGameObject.Remove((nint)characterBase); + private void OnCharacterBaseDestructor(in CharacterBaseDestructor.Arguments arguments) + => _drawObjectToGameObject.Remove(arguments.CharacterBase.Address); - private unsafe void OnCharacterBaseCreated(ModelCharaId modelCharaId, CustomizeArray* customize, CharacterArmor* equipment, - CharacterBase* drawObject) + private void OnCharacterBaseCreated(in CreateCharacterBase.PostEvent.Arguments arguments) { Actor gameObject = LastGameObject; if (gameObject.Valid) - _drawObjectToGameObject[(nint)drawObject] = (gameObject, gameObject.Index, false); + _drawObjectToGameObject[arguments.CharacterBase] = (gameObject, gameObject.Index, false); } /// diff --git a/Penumbra/Interop/PathResolving/IdentifiedCollectionCache.cs b/Penumbra/Interop/PathResolving/IdentifiedCollectionCache.cs index 20a61171..1450d5a8 100644 --- a/Penumbra/Interop/PathResolving/IdentifiedCollectionCache.cs +++ b/Penumbra/Interop/PathResolving/IdentifiedCollectionCache.cs @@ -1,5 +1,4 @@ using Dalamud.Plugin.Services; -using FFXIVClientStructs.FFXIV.Client.Game.Character; using FFXIVClientStructs.FFXIV.Client.Game.Object; using Penumbra.Collections; using Penumbra.Collections.Manager; @@ -80,15 +79,15 @@ public unsafe class IdentifiedCollectionCache : IDisposable, IEnumerable<(nint A IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - private void CollectionChangeClear(CollectionType type, ModCollection? _1, ModCollection? _2, string _3) + private void CollectionChangeClear(in CollectionChange.Arguments arguments) { - if (type is not (CollectionType.Current or CollectionType.Interface or CollectionType.Inactive)) + if (arguments.Type is not (CollectionType.Current or CollectionType.Interface or CollectionType.Inactive)) _dirty = _cache.Count > 0; } private void TerritoryClear(ushort _2) => _dirty = _cache.Count > 0; - private void OnCharacterDestructor(Character* character) - => _cache.Remove((nint)character); + private void OnCharacterDestructor(in CharacterDestructor.Arguments arguments) + => _cache.Remove(arguments.Character); } diff --git a/Penumbra/Interop/PathResolving/MetaState.cs b/Penumbra/Interop/PathResolving/MetaState.cs index 79edaf39..7cd4485a 100644 --- a/Penumbra/Interop/PathResolving/MetaState.cs +++ b/Penumbra/Interop/PathResolving/MetaState.cs @@ -1,7 +1,7 @@ -using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using Luna; using Penumbra.Collections; using Penumbra.Api.Enums; +using Penumbra.Communication; using Penumbra.GameData.Structs; using Penumbra.Interop.Services; using Penumbra.Services; @@ -34,7 +34,7 @@ namespace Penumbra.Interop.PathResolving; // ChangeCustomize and RspSetupCharacter, which is hooked here, as well as Character.CalculateHeight. // GMP Entries seem to be only used by "48 8B ?? 53 55 57 48 83 ?? ?? 48 8B", which is SetupVisor. -public sealed unsafe class MetaState : IDisposable, Luna.IService +public sealed unsafe class MetaState : IDisposable, IService { public readonly Configuration Config; private readonly CommunicatorService _communicator; @@ -92,27 +92,27 @@ public sealed unsafe class MetaState : IDisposable, Luna.IService _createCharacterBase.Unsubscribe(OnCharacterBaseCreated); } - private void OnCreatingCharacterBase(ModelCharaId* modelCharaId, CustomizeArray* customize, CharacterArmor* equipData) + private void OnCreatingCharacterBase(in CreateCharacterBase.Arguments arguments) { _lastCreatedCollection = _collectionResolver.IdentifyLastGameObjectCollection(true); if (_lastCreatedCollection.Valid && _lastCreatedCollection.AssociatedGameObject != nint.Zero) - _communicator.CreatingCharacterBase.Invoke(_lastCreatedCollection.AssociatedGameObject, - _lastCreatedCollection.ModCollection.Identity.Id, (nint)modelCharaId, (nint)customize, (nint)equipData); + _communicator.CreatingCharacterBase.Invoke(new CreatingCharacterBase.Arguments(_lastCreatedCollection.AssociatedGameObject, + _lastCreatedCollection.ModCollection, (nint)Unsafe.AsPointer(ref arguments.ModelCharaId), (nint)arguments.Customize, (nint)arguments.Equipment)); var decal = new DecalReverter(Config, _characterUtility, _resources, _lastCreatedCollection, - UsesDecal(*(uint*)modelCharaId, (nint)customize)); + UsesDecal(arguments.ModelCharaId, (nint)arguments.Customize)); RspCollection.Push(_lastCreatedCollection); _characterBaseCreateMetaChanges.Dispose(); // Should always be empty. _characterBaseCreateMetaChanges = new DisposableContainer(decal); } - private void OnCharacterBaseCreated(ModelCharaId _1, CustomizeArray* _2, CharacterArmor* _3, CharacterBase* drawObject) + private void OnCharacterBaseCreated(in CreateCharacterBase.PostEvent.Arguments arguments) { _characterBaseCreateMetaChanges.Dispose(); _characterBaseCreateMetaChanges = DisposableContainer.Empty; - if (_lastCreatedCollection.Valid && _lastCreatedCollection.AssociatedGameObject != nint.Zero && drawObject != null) - _communicator.CreatedCharacterBase.Invoke(_lastCreatedCollection.AssociatedGameObject, - _lastCreatedCollection.ModCollection, (nint)drawObject); + if (_lastCreatedCollection.Valid && _lastCreatedCollection.AssociatedGameObject != nint.Zero && arguments.CharacterBase.Valid) + _communicator.CreatedCharacterBase.Invoke(new CreatedCharacterBase.Arguments(_lastCreatedCollection.AssociatedGameObject, + _lastCreatedCollection.ModCollection, arguments.CharacterBase)); RspCollection.Pop(); _lastCreatedCollection = ResolveData.Invalid; } diff --git a/Penumbra/Interop/PathResolving/SubfileHelper.cs b/Penumbra/Interop/PathResolving/SubfileHelper.cs index d70ba2ae..f04596bb 100644 --- a/Penumbra/Interop/PathResolving/SubfileHelper.cs +++ b/Penumbra/Interop/PathResolving/SubfileHelper.cs @@ -85,6 +85,6 @@ public sealed unsafe class SubfileHelper : IDisposable, IReadOnlyCollection _gameState.SubFileCollection.TryRemove((nint)handle, out _); + private void ResourceDestroyed(in ResourceHandleDestructor.Arguments arguments) + => _gameState.SubFileCollection.TryRemove((nint)arguments.ResourceHandle, out _); } diff --git a/Penumbra/Interop/Services/CharacterUtility.cs b/Penumbra/Interop/Services/CharacterUtility.cs index 4b7cb1ab..61b2b274 100644 --- a/Penumbra/Interop/Services/CharacterUtility.cs +++ b/Penumbra/Interop/Services/CharacterUtility.cs @@ -28,7 +28,7 @@ public unsafe class CharacterUtility : IDisposable, Luna.IRequiredService public bool Ready { get; private set; } - public readonly CharacterUtilityFinished LoadingFinished = new(); + public readonly CharacterUtilityFinished LoadingFinished; public nint DefaultHumanPbdResource { get; private set; } public nint DefaultTransparentResource { get; private set; } @@ -56,14 +56,16 @@ public unsafe class CharacterUtility : IDisposable, Luna.IRequiredService private readonly IFramework _framework; - public CharacterUtility(IFramework framework, IGameInteropProvider interop) + public CharacterUtility(IFramework framework, IGameInteropProvider interop, CharacterUtilityFinished finished) { + LoadingFinished = finished; interop.InitializeFromAttributes(this); _lists = Enumerable.Range(0, RelevantIndices.Length) .Select(idx => new MetaList(new InternalIndex(idx))) .ToArray(); - _framework = framework; - LoadingFinished.Subscribe(() => Penumbra.Log.Debug("Loading of CharacterUtility finished."), CharacterUtilityFinished.Priority.OnFinishedLoading); + _framework = framework; + LoadingFinished.Subscribe(() => Penumbra.Log.Debug("Loading of CharacterUtility finished."), + CharacterUtilityFinished.Priority.OnFinishedLoading); LoadDefaultResources(null!); if (!Ready) _framework.Update += LoadDefaultResources; diff --git a/Penumbra/Interop/Services/RedrawService.cs b/Penumbra/Interop/Services/RedrawService.cs index a76cc4e7..de3bab11 100644 --- a/Penumbra/Interop/Services/RedrawService.cs +++ b/Penumbra/Interop/Services/RedrawService.cs @@ -430,7 +430,7 @@ public sealed unsafe partial class RedrawService : IDisposable } } - private void OnModFileChanged(Mod _1, FileRegistry _2) + private void OnModFileChanged(in ModFileChanged.Arguments _) { if (!_config.Ephemeral.ForceRedrawOnFileChange) return; diff --git a/Penumbra/Interop/Services/SchedulerResourceManagementService.cs b/Penumbra/Interop/Services/SchedulerResourceManagementService.cs index d8af2d96..1399dde5 100644 --- a/Penumbra/Interop/Services/SchedulerResourceManagementService.cs +++ b/Penumbra/Interop/Services/SchedulerResourceManagementService.cs @@ -3,17 +3,16 @@ using Dalamud.Plugin.Services; using Dalamud.Utility.Signatures; using FFXIVClientStructs.FFXIV.Client.System.Scheduler.Resource; using Lumina.Excel.Sheets; -using Penumbra.Collections; +using Luna; using Penumbra.Communication; using Penumbra.GameData; -using Penumbra.Mods.Editor; using Penumbra.Services; using Penumbra.String; using Penumbra.String.Classes; namespace Penumbra.Interop.Services; -public unsafe class SchedulerResourceManagementService : Luna.IService, IDisposable +public unsafe class SchedulerResourceManagementService : IService, IDisposable { private static readonly CiByteString TmbExtension = new(".tmb"u8, MetaDataComputation.All); private static readonly CiByteString FolderPrefix = new("chara/action/"u8, MetaDataComputation.All); @@ -40,16 +39,15 @@ public unsafe class SchedulerResourceManagementService : Luna.IService, IDisposa interop.InitializeFromAttributes(this); } - private void OnResolvedFileChange(ModCollection collection, ResolvedFileChanged.Type type, Utf8GamePath gamePath, FullPath oldPath, - FullPath newPath, IMod? mod) + private void OnResolvedFileChange(in ResolvedFileChanged.Arguments arguments) { - switch (type) + switch (arguments.Type) { case ResolvedFileChanged.Type.Added: - CheckFile(gamePath); + CheckFile(arguments.GamePath); return; case ResolvedFileChanged.Type.FullRecomputeFinished: - foreach (var path in collection.ResolvedFiles.Keys) + foreach (var path in arguments.Collection.ResolvedFiles.Keys) CheckFile(path); return; } diff --git a/Penumbra/Meta/ShapeAttributeManager.cs b/Penumbra/Meta/ShapeAttributeManager.cs index 1cd2a2eb..4f7a94c5 100644 --- a/Penumbra/Meta/ShapeAttributeManager.cs +++ b/Penumbra/Meta/ShapeAttributeManager.cs @@ -1,4 +1,3 @@ -using Penumbra.Collections; using Penumbra.Collections.Cache; using Penumbra.GameData.Enums; using Penumbra.GameData.Interop; @@ -41,27 +40,27 @@ public unsafe class ShapeAttributeManager : Luna.IRequiredService, IDisposable public void Dispose() => _attributeHook.Unsubscribe(OnAttributeComputed); - private void OnAttributeComputed(Actor actor, Model model, ModCollection collection) + private void OnAttributeComputed(in AttributeHook.Arguments arguments) { - if (!collection.HasCache) + if (!arguments.Collection.HasCache) return; - _genderRace = (GenderRace)model.AsHuman->RaceSexId; + _genderRace = (GenderRace)arguments.Human.AsHuman->RaceSexId; for (_slotIndex = 0; _slotIndex < NumSlots; ++_slotIndex) { _modelIndex = UsedModels[_slotIndex]; - _model = model.AsHuman->Models[_modelIndex.ToIndex()]; + _model = arguments.Human.AsHuman->Models[_modelIndex.ToIndex()]; if (_model is null || _model->ModelResourceHandle is null) continue; - _ids[(int)_modelIndex] = model.GetModelId(_modelIndex); - CheckShapes(collection.MetaCache!.Shp); - CheckAttributes(collection.MetaCache!.Atr); + _ids[(int)_modelIndex] = arguments.Human.GetModelId(_modelIndex); + CheckShapes(arguments.Collection.MetaCache!.Shp); + CheckAttributes(arguments.Collection.MetaCache!.Atr); if (_modelIndex is <= HumanSlot.LFinger and >= HumanSlot.Ears) - AccessoryImcCheck(model); + AccessoryImcCheck(arguments.Human); } - UpdateDefaultMasks(model, collection.MetaCache!.Shp); + UpdateDefaultMasks(arguments.Human, arguments.Collection.MetaCache!.Shp); } private void AccessoryImcCheck(Model model) diff --git a/Penumbra/Mods/Editor/DuplicateManager.cs b/Penumbra/Mods/Editor/DuplicateManager.cs index 01187f25..af851175 100644 --- a/Penumbra/Mods/Editor/DuplicateManager.cs +++ b/Penumbra/Mods/Editor/DuplicateManager.cs @@ -1,4 +1,4 @@ -using Luna.Files; +using Luna; using Penumbra.Mods.Groups; using Penumbra.Mods.Manager; using Penumbra.Mods.SubMods; diff --git a/Penumbra/Mods/Editor/ModFileEditor.cs b/Penumbra/Mods/Editor/ModFileEditor.cs index 40ef7d74..722aad36 100644 --- a/Penumbra/Mods/Editor/ModFileEditor.cs +++ b/Penumbra/Mods/Editor/ModFileEditor.cs @@ -1,3 +1,4 @@ +using Penumbra.Communication; using Penumbra.Mods.Manager; using Penumbra.Mods.SubMods; using Penumbra.Services; @@ -137,7 +138,7 @@ public class ModFileEditor(ModFileCollection files, ModManager modManager, Commu try { File.Delete(file.File.FullName); - communicator.ModFileChanged.Invoke(mod, file); + communicator.ModFileChanged.Invoke(new ModFileChanged.Arguments(mod, file)); Penumbra.Log.Debug($"[DeleteFiles] Deleted {file.File.FullName} from {mod.Name}."); ++deletions; } diff --git a/Penumbra/Mods/Editor/ModMerger.cs b/Penumbra/Mods/Editor/ModMerger.cs index 5c1fa772..2c60250b 100644 --- a/Penumbra/Mods/Editor/ModMerger.cs +++ b/Penumbra/Mods/Editor/ModMerger.cs @@ -1,7 +1,6 @@ using Dalamud.Interface.ImGuiNotification; using Dalamud.Utility; using Luna; -using Luna.Files; using Penumbra.Api.Enums; using Penumbra.Communication; using Penumbra.Mods.Groups; @@ -478,27 +477,27 @@ public class ModMerger : IDisposable, IService } } - private void OnSelectionChange(Mod? oldSelection, Mod? newSelection) + private void OnSelectionChange(in ModSelection.Arguments arguments) { - if (OptionGroupName == "Merges" && OptionName.Length == 0 || OptionName == oldSelection?.Name.Text) - OptionName = newSelection?.Name.Text ?? string.Empty; + if (OptionGroupName == "Merges" && OptionName.Length == 0 || OptionName == arguments.OldSelection?.Name.Text) + OptionName = arguments.NewSelection?.Name.Text ?? string.Empty; - if (MergeToMod == newSelection) + if (MergeToMod == arguments.NewSelection) MergeToMod = null; SelectedOptions.Clear(); } - private void OnModPathChange(ModPathChangeType type, Mod mod, DirectoryInfo? _1, DirectoryInfo? _2) + private void OnModPathChange(in ModPathChanged.Arguments arguments) { - switch (type) + switch (arguments.Type) { case ModPathChangeType.Deleted: { - if (mod == MergeFromMod) + if (arguments.Mod == MergeFromMod) SelectedOptions.Clear(); - if (mod == MergeToMod) + if (arguments.Mod == MergeToMod) MergeToMod = null; break; } diff --git a/Penumbra/Mods/Editor/ModNormalizer.cs b/Penumbra/Mods/Editor/ModNormalizer.cs index 6b74ea49..0c5cdd89 100644 --- a/Penumbra/Mods/Editor/ModNormalizer.cs +++ b/Penumbra/Mods/Editor/ModNormalizer.cs @@ -1,6 +1,5 @@ using Dalamud.Interface.ImGuiNotification; using Luna; -using Luna.Files; using OtterGui.Tasks; using Penumbra.Mods.Groups; using Penumbra.Mods.Manager; diff --git a/Penumbra/Mods/ItemSwap/ItemSwapContainer.cs b/Penumbra/Mods/ItemSwap/ItemSwapContainer.cs index 63394cc7..1752478c 100644 --- a/Penumbra/Mods/ItemSwap/ItemSwapContainer.cs +++ b/Penumbra/Mods/ItemSwap/ItemSwapContainer.cs @@ -1,4 +1,4 @@ -using Luna.Files; +using Luna; using Penumbra.Collections; using Penumbra.GameData.Data; using Penumbra.GameData.Enums; diff --git a/Penumbra/Mods/Manager/ModCacheManager.cs b/Penumbra/Mods/Manager/ModCacheManager.cs index 5a4cc6f0..1d03eb22 100644 --- a/Penumbra/Mods/Manager/ModCacheManager.cs +++ b/Penumbra/Mods/Manager/ModCacheManager.cs @@ -1,8 +1,6 @@ using Penumbra.Communication; using Penumbra.GameData.Data; -using Penumbra.Mods.Groups; using Penumbra.Mods.Manager.OptionEditor; -using Penumbra.Mods.SubMods; using Penumbra.Services; using Penumbra.Util; @@ -39,52 +37,51 @@ public class ModCacheManager : IDisposable, Luna.IService _communicator.ModDiscoveryFinished.Unsubscribe(OnModDiscoveryFinished); } - private void OnModOptionChange(ModOptionChangeType type, Mod mod, IModGroup? group, IModOption? option, IModDataContainer? container, - int fromIdx) + private void OnModOptionChange(in ModOptionChanged.Arguments arguments) { - switch (type) + switch (arguments.Type) { case ModOptionChangeType.GroupAdded: case ModOptionChangeType.GroupDeleted: case ModOptionChangeType.OptionAdded: case ModOptionChangeType.OptionDeleted: - UpdateChangedItems(mod); - UpdateCounts(mod); + UpdateChangedItems(arguments.Mod); + UpdateCounts(arguments.Mod); break; case ModOptionChangeType.GroupTypeChanged: - UpdateHasOptions(mod); + UpdateHasOptions(arguments.Mod); break; case ModOptionChangeType.OptionFilesChanged: case ModOptionChangeType.OptionFilesAdded: - UpdateChangedItems(mod); - UpdateFileCount(mod); + UpdateChangedItems(arguments.Mod); + UpdateFileCount(arguments.Mod); break; case ModOptionChangeType.OptionSwapsChanged: - UpdateChangedItems(mod); - UpdateSwapCount(mod); + UpdateChangedItems(arguments.Mod); + UpdateSwapCount(arguments.Mod); break; case ModOptionChangeType.OptionMetaChanged: - UpdateChangedItems(mod); - UpdateMetaCount(mod); + UpdateChangedItems(arguments.Mod); + UpdateMetaCount(arguments.Mod); break; } } - private void OnModPathChange(ModPathChangeType type, Mod mod, DirectoryInfo? old, DirectoryInfo? @new) + private void OnModPathChange(in ModPathChanged.Arguments arguments) { - switch (type) + switch (arguments.Type) { case ModPathChangeType.Added: case ModPathChangeType.Reloaded: - RefreshWithChangedItems(mod); + RefreshWithChangedItems(arguments.Mod); break; } } - private static void OnModDataChange(ModDataChangeType type, Mod mod, string? _) + private static void OnModDataChange(in ModDataChanged.Arguments arguments) { - if ((type & (ModDataChangeType.LocalTags | ModDataChangeType.ModTags)) != 0) - UpdateTags(mod); + if ((arguments.Type & (ModDataChangeType.LocalTags | ModDataChangeType.ModTags)) is not 0) + UpdateTags(arguments.Mod); } private void OnModDiscoveryFinished() diff --git a/Penumbra/Mods/Manager/ModDataEditor.cs b/Penumbra/Mods/Manager/ModDataEditor.cs index 249ed3ac..04e743fa 100644 --- a/Penumbra/Mods/Manager/ModDataEditor.cs +++ b/Penumbra/Mods/Manager/ModDataEditor.cs @@ -1,5 +1,6 @@ using Dalamud.Utility; using OtterGui.Classes; +using Penumbra.Communication; using Penumbra.GameData.Data; using Penumbra.GameData.Structs; using Penumbra.Services; @@ -55,7 +56,7 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic var oldName = mod.Name; mod.Name = newName; saveService.QueueSave(new ModMeta(mod)); - communicatorService.ModDataChanged.Invoke(ModDataChangeType.Name, mod, oldName.Text); + communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(ModDataChangeType.Name, mod, oldName.Text)); } public void ChangeModAuthor(Mod mod, string newAuthor) @@ -65,7 +66,7 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic mod.Author = newAuthor; saveService.QueueSave(new ModMeta(mod)); - communicatorService.ModDataChanged.Invoke(ModDataChangeType.Author, mod, null); + communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(ModDataChangeType.Author, mod, null)); } public void ChangeModDescription(Mod mod, string newDescription) @@ -75,7 +76,7 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic mod.Description = newDescription; saveService.QueueSave(new ModMeta(mod)); - communicatorService.ModDataChanged.Invoke(ModDataChangeType.Description, mod, null); + communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(ModDataChangeType.Description, mod, null)); } public void ChangeModVersion(Mod mod, string newVersion) @@ -85,7 +86,7 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic mod.Version = newVersion; saveService.QueueSave(new ModMeta(mod)); - communicatorService.ModDataChanged.Invoke(ModDataChangeType.Version, mod, null); + communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(ModDataChangeType.Version, mod, null)); } public void ChangeModWebsite(Mod mod, string newWebsite) @@ -95,7 +96,7 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic mod.Website = newWebsite; saveService.QueueSave(new ModMeta(mod)); - communicatorService.ModDataChanged.Invoke(ModDataChangeType.Website, mod, null); + communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(ModDataChangeType.Website, mod, null)); } public void ChangeRequiredFeatures(Mod mod, FeatureFlags flags) @@ -105,7 +106,7 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic mod.RequiredFeatures = flags; saveService.QueueSave(new ModMeta(mod)); - communicatorService.ModDataChanged.Invoke(ModDataChangeType.RequiredFeatures, mod, null); + communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(ModDataChangeType.RequiredFeatures, mod, null)); } public void ChangeModTag(Mod mod, int tagIdx, string newTag) @@ -121,7 +122,7 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic mod.Favorite = state; saveService.QueueSave(new ModLocalData(mod)); - communicatorService.ModDataChanged.Invoke(ModDataChangeType.Favorite, mod, null); + communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(ModDataChangeType.Favorite, mod, null)); } public void ResetModImportDate(Mod mod) @@ -132,7 +133,7 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic mod.ImportDate = newDate; saveService.QueueSave(new ModLocalData(mod)); - communicatorService.ModDataChanged.Invoke(ModDataChangeType.ImportDate, mod, null); + communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(ModDataChangeType.ImportDate, mod, null)); } public void ChangeModNote(Mod mod, string newNote) @@ -142,7 +143,7 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic mod.Note = newNote; saveService.QueueSave(new ModLocalData(mod)); - communicatorService.ModDataChanged.Invoke(ModDataChangeType.Favorite, mod, null); + communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(ModDataChangeType.Favorite, mod, null)); } private void ChangeTag(Mod mod, int tagIdx, string newTag, bool local) @@ -170,7 +171,7 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic saveService.QueueSave(new ModLocalData(mod)); if (flags != 0) - communicatorService.ModDataChanged.Invoke(flags, mod, null); + communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(flags, mod, null)); } public void MoveDataFile(DirectoryInfo oldMod, DirectoryInfo newMod) @@ -196,13 +197,13 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic { ++mod.LastChangedItemsUpdate; saveService.QueueSave(new ModLocalData(mod)); - communicatorService.ModDataChanged.Invoke(ModDataChangeType.PreferredChangedItems, mod, null); + communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(ModDataChangeType.PreferredChangedItems, mod, null)); } if (toDefault && CleanExisting(mod.DefaultPreferredItems)) { saveService.QueueSave(new ModMeta(mod)); - communicatorService.ModDataChanged.Invoke(ModDataChangeType.DefaultChangedItems, mod, null); + communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(ModDataChangeType.DefaultChangedItems, mod, null)); } bool CleanExisting(HashSet items) @@ -251,13 +252,13 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic { ++mod.LastChangedItemsUpdate; saveService.QueueSave(new ModLocalData(mod)); - communicatorService.ModDataChanged.Invoke(ModDataChangeType.PreferredChangedItems, mod, null); + communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(ModDataChangeType.PreferredChangedItems, mod, null)); } if (fromDefault && mod.DefaultPreferredItems.Remove(id)) { saveService.QueueSave(new ModMeta(mod)); - communicatorService.ModDataChanged.Invoke(ModDataChangeType.DefaultChangedItems, mod, null); + communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(ModDataChangeType.DefaultChangedItems, mod, null)); } } @@ -271,7 +272,7 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic mod.PreferredChangedItems = newSet; ++mod.LastChangedItemsUpdate; saveService.QueueSave(new ModLocalData(mod)); - communicatorService.ModDataChanged.Invoke(ModDataChangeType.PreferredChangedItems, mod, null); + communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(ModDataChangeType.PreferredChangedItems, mod, null)); } newSet = new HashSet(mod.DefaultPreferredItems.Count); @@ -279,7 +280,7 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic { mod.DefaultPreferredItems = newSet; saveService.QueueSave(new ModMeta(mod)); - communicatorService.ModDataChanged.Invoke(ModDataChangeType.DefaultChangedItems, mod, null); + communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(ModDataChangeType.DefaultChangedItems, mod, null)); } return; @@ -308,6 +309,6 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic mod.PreferredChangedItems.UnionWith(mod.DefaultPreferredItems); ++mod.LastChangedItemsUpdate; saveService.QueueSave(new ModLocalData(mod)); - communicatorService.ModDataChanged.Invoke(ModDataChangeType.PreferredChangedItems, mod, null); + communicatorService.ModDataChanged.Invoke(new ModDataChanged.Arguments(ModDataChangeType.PreferredChangedItems, mod, null)); } } diff --git a/Penumbra/Mods/Manager/ModExportManager.cs b/Penumbra/Mods/Manager/ModExportManager.cs index 605306e3..3fd3d97f 100644 --- a/Penumbra/Mods/Manager/ModExportManager.cs +++ b/Penumbra/Mods/Manager/ModExportManager.cs @@ -79,14 +79,13 @@ public class ModExportManager : IDisposable, Luna.IService => _communicator.ModPathChanged.Unsubscribe(OnModPathChange); /// Automatically migrate the backup file to the new name if any exists. - private void OnModPathChange(ModPathChangeType type, Mod mod, DirectoryInfo? oldDirectory, - DirectoryInfo? newDirectory) + private void OnModPathChange(in ModPathChanged.Arguments arguments) { - if (type is not ModPathChangeType.Moved || oldDirectory == null || newDirectory == null) + if (arguments.Type is not ModPathChangeType.Moved || arguments.OldDirectory is null || arguments.NewDirectory is null) return; - mod.ModPath = oldDirectory; - new ModBackup(this, mod).Move(null, newDirectory.Name); - mod.ModPath = newDirectory; + arguments.Mod.ModPath = arguments.OldDirectory; + new ModBackup(this, arguments.Mod).Move(null, arguments.NewDirectory.Name); + arguments.Mod.ModPath = arguments.NewDirectory; } } diff --git a/Penumbra/Mods/Manager/ModFileSystem.cs b/Penumbra/Mods/Manager/ModFileSystem.cs index 14b21cb9..7163b7b9 100644 --- a/Penumbra/Mods/Manager/ModFileSystem.cs +++ b/Penumbra/Mods/Manager/ModFileSystem.cs @@ -77,21 +77,21 @@ public sealed class ModFileSystem : FileSystem, IDisposable, ISavable, ISer } // Update sort order when defaulted mod names change. - private void OnModDataChange(ModDataChangeType type, Mod mod, string? oldName) + private void OnModDataChange(in ModDataChanged.Arguments arguments) { - if (!type.HasFlag(ModDataChangeType.Name) || oldName == null || !TryGetValue(mod, out var leaf)) + if (!arguments.Type.HasFlag(ModDataChangeType.Name) || arguments.OldName == null || !TryGetValue(arguments.Mod, out var leaf)) return; - var old = oldName.FixName(); + var old = arguments.OldName.FixName(); if (old == leaf.Name || leaf.Name.IsDuplicateName(out var baseName, out _) && baseName == old) - RenameWithDuplicates(leaf, mod.Name.Text); + RenameWithDuplicates(leaf, arguments.Mod.Name.Text); } // Update the filesystem if a mod has been added or removed. // Save it, if the mod directory has been moved, since this will change the save format. - private void OnModPathChange(ModPathChangeType type, Mod mod, DirectoryInfo? oldPath, DirectoryInfo? newPath) + private void OnModPathChange(in ModPathChanged.Arguments arguments) { - switch (type) + switch (arguments.Type) { case ModPathChangeType.Added: var parent = Root; @@ -103,14 +103,14 @@ public sealed class ModFileSystem : FileSystem, IDisposable, ISavable, ISer catch (Exception e) { Penumbra.Messager.NotificationMessage(e, - $"Could not move newly imported mod {mod.Name} to default import folder {_config.DefaultImportFolder}.", + $"Could not move newly imported mod {arguments.Mod.Name} to default import folder {_config.DefaultImportFolder}.", NotificationType.Warning); } - CreateDuplicateLeaf(parent, mod.Name.Text, mod); + CreateDuplicateLeaf(parent, arguments.Mod.Name.Text, arguments.Mod); break; case ModPathChangeType.Deleted: - if (TryGetValue(mod, out var leaf)) + if (TryGetValue(arguments.Mod, out var leaf)) Delete(leaf); break; diff --git a/Penumbra/Mods/Manager/ModManager.cs b/Penumbra/Mods/Manager/ModManager.cs index 35830665..fd3a84bf 100644 --- a/Penumbra/Mods/Manager/ModManager.cs +++ b/Penumbra/Mods/Manager/ModManager.cs @@ -93,7 +93,7 @@ public sealed class ModManager : ModStorage, IDisposable, Luna.IService mod.Index = Count; Mods.Add(mod); - _communicator.ModPathChanged.Invoke(ModPathChangeType.Added, mod, null, mod.ModPath); + _communicator.ModPathChanged.Invoke(new ModPathChanged.Arguments(ModPathChangeType.Added, mod, null, mod.ModPath)); Penumbra.Log.Debug($"Added new mod {mod.Name} from {modFolder.FullName}."); } @@ -125,7 +125,7 @@ public sealed class ModManager : ModStorage, IDisposable, Luna.IService /// public void RemoveMod(Mod mod) { - _communicator.ModPathChanged.Invoke(ModPathChangeType.Deleted, mod, mod.ModPath, null); + _communicator.ModPathChanged.Invoke(new ModPathChanged.Arguments(ModPathChangeType.Deleted, mod, mod.ModPath, null)); foreach (var remainingMod in Mods.Skip(mod.Index + 1)) --remainingMod.Index; Mods.RemoveAt(mod.Index); @@ -140,7 +140,7 @@ public sealed class ModManager : ModStorage, IDisposable, Luna.IService { var oldName = mod.Name; - _communicator.ModPathChanged.Invoke(ModPathChangeType.StartingReload, mod, mod.ModPath, mod.ModPath); + _communicator.ModPathChanged.Invoke(new ModPathChanged.Arguments(ModPathChangeType.StartingReload, mod, mod.ModPath, mod.ModPath)); if (!Creator.ReloadMod(mod, true, false, out var metaChange)) { if (mod.RequiredFeatures is not FeatureFlags.Invalid) @@ -151,9 +151,9 @@ public sealed class ModManager : ModStorage, IDisposable, Luna.IService return; } - _communicator.ModPathChanged.Invoke(ModPathChangeType.Reloaded, mod, mod.ModPath, mod.ModPath); + _communicator.ModPathChanged.Invoke(new ModPathChanged.Arguments(ModPathChangeType.Reloaded, mod, mod.ModPath, mod.ModPath)); if (metaChange != ModDataChangeType.None) - _communicator.ModDataChanged.Invoke(metaChange, mod, oldName); + _communicator.ModDataChanged.Invoke(new ModDataChanged.Arguments(metaChange, mod, oldName)); } @@ -213,9 +213,9 @@ public sealed class ModManager : ModStorage, IDisposable, Luna.IService return; } - _communicator.ModPathChanged.Invoke(ModPathChangeType.Moved, mod, oldDirectory, dir); + _communicator.ModPathChanged.Invoke(new ModPathChanged.Arguments(ModPathChangeType.Moved, mod, oldDirectory, dir)); if (metaChange != ModDataChangeType.None) - _communicator.ModDataChanged.Invoke(metaChange, mod, oldName); + _communicator.ModDataChanged.Invoke(new ModDataChanged.Arguments(metaChange, mod, oldName)); } /// Return the state of the new potential name of a directory. @@ -247,16 +247,15 @@ public sealed class ModManager : ModStorage, IDisposable, Luna.IService /// Add new mods to NewMods and remove deleted mods from NewMods. - private void OnModPathChange(ModPathChangeType type, Mod mod, DirectoryInfo? oldDirectory, - DirectoryInfo? newDirectory) + private void OnModPathChange(in ModPathChanged.Arguments arguments) { - switch (type) + switch (arguments.Type) { - case ModPathChangeType.Added: SetNew(mod); break; - case ModPathChangeType.Deleted: SetKnown(mod); break; + case ModPathChangeType.Added: SetNew(arguments.Mod); break; + case ModPathChangeType.Deleted: SetKnown(arguments.Mod); break; case ModPathChangeType.Moved: - if (oldDirectory != null && newDirectory != null) - DataEditor.MoveDataFile(oldDirectory, newDirectory); + if (arguments.OldDirectory is not null && arguments.NewDirectory is not null) + DataEditor.MoveDataFile(arguments.OldDirectory, arguments.NewDirectory); break; } @@ -313,7 +312,7 @@ public sealed class ModManager : ModStorage, IDisposable, Luna.IService _config.ModDirectory = newPath; _config.Save(); Penumbra.Log.Information($"Set new mod base directory from {_config.ModDirectory} to {newPath}."); - _communicator.ModDirectoryChanged.Invoke(newPath, valid); + _communicator.ModDirectoryChanged.Invoke(new ModDirectoryChanged.Arguments(newPath, valid)); } @@ -346,7 +345,7 @@ public sealed class ModManager : ModStorage, IDisposable, Luna.IService catch (Exception ex) { Valid = false; - _communicator.ModDirectoryChanged.Invoke(BasePath.FullName, false); + _communicator.ModDirectoryChanged.Invoke(new ModDirectoryChanged.Arguments(BasePath.FullName, false)); Penumbra.Log.Error($"Could not scan for mods:\n{ex}"); } } diff --git a/Penumbra/Mods/Manager/OptionEditor/CombiningModGroupEditor.cs b/Penumbra/Mods/Manager/OptionEditor/CombiningModGroupEditor.cs index 1a35cc0f..34c4c72b 100644 --- a/Penumbra/Mods/Manager/OptionEditor/CombiningModGroupEditor.cs +++ b/Penumbra/Mods/Manager/OptionEditor/CombiningModGroupEditor.cs @@ -1,5 +1,5 @@ using Luna; -using Luna.Files; +using Penumbra.Communication; using Penumbra.Mods.Groups; using Penumbra.Mods.Settings; using Penumbra.Mods.SubMods; @@ -42,6 +42,6 @@ public sealed class CombiningModGroupEditor(CommunicatorService communicator, Sa container.Name = name; SaveService.Save(saveType, new ModSaveGroup(container.Group, Config.ReplaceNonAsciiOnImport)); - Communicator.ModOptionChanged.Invoke(ModOptionChangeType.DisplayChange, container.Group.Mod, container.Group, null, null, -1); + Communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.DisplayChange, container.Group.Mod, container.Group, null, null, -1)); } } diff --git a/Penumbra/Mods/Manager/OptionEditor/ImcModGroupEditor.cs b/Penumbra/Mods/Manager/OptionEditor/ImcModGroupEditor.cs index 9dbbef56..803bb4a4 100644 --- a/Penumbra/Mods/Manager/OptionEditor/ImcModGroupEditor.cs +++ b/Penumbra/Mods/Manager/OptionEditor/ImcModGroupEditor.cs @@ -1,5 +1,6 @@ -using Luna.Files; +using Luna; using OtterGui.Filesystem; +using Penumbra.Communication; using Penumbra.GameData.Structs; using Penumbra.Meta.Manipulations; using Penumbra.Mods.Groups; @@ -10,7 +11,7 @@ using Penumbra.Services; namespace Penumbra.Mods.Manager.OptionEditor; public sealed class ImcModGroupEditor(CommunicatorService communicator, SaveService saveService, Configuration config) - : ModOptionEditor(communicator, saveService, config), Luna.IService + : ModOptionEditor(communicator, saveService, config), IService { /// Add a new, empty imc group with the given manipulation data. public ImcModGroup? AddModGroup(Mod mod, string newName, ImcIdentifier identifier, ImcEntry defaultEntry, @@ -23,7 +24,7 @@ public sealed class ImcModGroupEditor(CommunicatorService communicator, SaveServ var group = CreateGroup(mod, newName, identifier, defaultEntry, maxPriority); mod.Groups.Add(group); SaveService.Save(saveType, new ModSaveGroup(group, Config.ReplaceNonAsciiOnImport)); - Communicator.ModOptionChanged.Invoke(ModOptionChangeType.GroupAdded, mod, group, null, null, -1); + Communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.GroupAdded, mod, group, null, null, -1)); return group; } @@ -41,7 +42,7 @@ public sealed class ImcModGroupEditor(CommunicatorService communicator, SaveServ }; group.OptionData.Add(subMod); SaveService.Save(saveType, new ModSaveGroup(group, Config.ReplaceNonAsciiOnImport)); - Communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionAdded, group.Mod, group, subMod, null, -1); + Communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.OptionAdded, group.Mod, group, subMod, null, -1)); return subMod; } @@ -55,7 +56,7 @@ public sealed class ImcModGroupEditor(CommunicatorService communicator, SaveServ return; SaveService.Save(saveType, new ModSaveGroup(group, Config.ReplaceNonAsciiOnImport)); - Communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionMetaChanged, group.Mod, group, null, null, -1); + Communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.OptionMetaChanged, group.Mod, group, null, null, -1)); } public void ChangeDefaultEntry(ImcModGroup group, in ImcEntry newEntry, SaveType saveType = SaveType.Queue) @@ -66,7 +67,7 @@ public sealed class ImcModGroupEditor(CommunicatorService communicator, SaveServ group.DefaultEntry = entry; SaveService.Save(saveType, new ModSaveGroup(group, Config.ReplaceNonAsciiOnImport)); - Communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionMetaChanged, group.Mod, group, null, null, -1); + Communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.OptionMetaChanged, group.Mod, group, null, null, -1)); } public void ChangeOptionAttribute(ImcSubMod option, in ImcAttributeCache cache, int idx, bool value, SaveType saveType = SaveType.Queue) @@ -75,7 +76,7 @@ public sealed class ImcModGroupEditor(CommunicatorService communicator, SaveServ return; SaveService.Save(saveType, new ModSaveGroup(option.Group, Config.ReplaceNonAsciiOnImport)); - Communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionMetaChanged, option.Mod, option.Group, option, null, -1); + Communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.OptionMetaChanged, option.Mod, option.Group, option, null, -1)); } public void ChangeAllVariants(ImcModGroup group, bool allVariants, SaveType saveType = SaveType.Queue) @@ -85,7 +86,7 @@ public sealed class ImcModGroupEditor(CommunicatorService communicator, SaveServ group.AllVariants = allVariants; SaveService.Save(saveType, new ModSaveGroup(group, Config.ReplaceNonAsciiOnImport)); - Communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionMetaChanged, group.Mod, group, null, null, -1); + Communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.OptionMetaChanged, group.Mod, group, null, null, -1)); } public void ChangeOnlyAttributes(ImcModGroup group, bool onlyAttributes, SaveType saveType = SaveType.Queue) @@ -95,7 +96,7 @@ public sealed class ImcModGroupEditor(CommunicatorService communicator, SaveServ group.OnlyAttributes = onlyAttributes; SaveService.Save(saveType, new ModSaveGroup(group, Config.ReplaceNonAsciiOnImport)); - Communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionMetaChanged, group.Mod, group, null, null, -1); + Communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.OptionMetaChanged, group.Mod, group, null, null, -1)); } public void ChangeCanBeDisabled(ImcModGroup group, bool canBeDisabled, SaveType saveType = SaveType.Queue) @@ -105,7 +106,7 @@ public sealed class ImcModGroupEditor(CommunicatorService communicator, SaveServ group.CanBeDisabled = canBeDisabled; SaveService.Save(saveType, new ModSaveGroup(group, Config.ReplaceNonAsciiOnImport)); - Communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionMetaChanged, group.Mod, group, null, null, -1); + Communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.OptionMetaChanged, group.Mod, group, null, null, -1)); } protected override ImcModGroup CreateGroup(Mod mod, string newName, ModPriority priority, SaveType saveType = SaveType.ImmediateSync) @@ -116,8 +117,7 @@ public sealed class ImcModGroupEditor(CommunicatorService communicator, SaveServ }; - private static ImcModGroup CreateGroup(Mod mod, string newName, ImcIdentifier identifier, ImcEntry defaultEntry, ModPriority priority, - SaveType saveType = SaveType.ImmediateSync) + private static ImcModGroup CreateGroup(Mod mod, string newName, ImcIdentifier identifier, ImcEntry defaultEntry, ModPriority priority, SaveType saveType = SaveType.ImmediateSync) => new(mod) { Name = newName, @@ -137,7 +137,7 @@ public sealed class ImcModGroupEditor(CommunicatorService communicator, SaveServ protected override bool MoveOption(ImcModGroup group, int optionIdxFrom, int optionIdxTo) { - if (!group.OptionData.Move(ref optionIdxFrom, ref optionIdxTo)) + if (!Extensions.Move(group.OptionData, ref optionIdxFrom, ref optionIdxTo)) return false; group.DefaultSettings = group.DefaultSettings.MoveBit(optionIdxFrom, optionIdxTo); diff --git a/Penumbra/Mods/Manager/OptionEditor/ModGroupEditor.cs b/Penumbra/Mods/Manager/OptionEditor/ModGroupEditor.cs index 41b977d0..fa3154cd 100644 --- a/Penumbra/Mods/Manager/OptionEditor/ModGroupEditor.cs +++ b/Penumbra/Mods/Manager/OptionEditor/ModGroupEditor.cs @@ -1,8 +1,8 @@ using Dalamud.Interface.ImGuiNotification; -using Luna.Files; using Luna; using OtterGui.Filesystem; using Penumbra.Api.Enums; +using Penumbra.Communication; using Penumbra.Meta.Manipulations; using Penumbra.Mods.Groups; using Penumbra.Mods.Settings; @@ -62,7 +62,7 @@ public class ModGroupEditor( group.DefaultSettings = defaultOption; saveService.QueueSave(new ModSaveGroup(group, config.ReplaceNonAsciiOnImport)); - communicator.ModOptionChanged.Invoke(ModOptionChangeType.DefaultOptionChanged, group.Mod, group, null, null, -1); + communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.DefaultOptionChanged, group.Mod, group, null, null, -1)); } /// Rename an option group if possible. @@ -75,7 +75,7 @@ public class ModGroupEditor( saveService.ImmediateDelete(new ModSaveGroup(group, config.ReplaceNonAsciiOnImport)); group.Name = newName; saveService.ImmediateSave(new ModSaveGroup(group, config.ReplaceNonAsciiOnImport)); - communicator.ModOptionChanged.Invoke(ModOptionChangeType.GroupRenamed, group.Mod, group, null, null, -1); + communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.GroupRenamed, group.Mod, group, null, null, -1)); } /// Delete a given option group. Fires an event to prepare before actually deleting. @@ -83,10 +83,10 @@ public class ModGroupEditor( { var mod = group.Mod; var idx = group.GetIndex(); - communicator.ModOptionChanged.Invoke(ModOptionChangeType.PrepareChange, mod, group, null, null, -1); + communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.PrepareChange, mod, group, null, null, -1)); mod.Groups.RemoveAt(idx); saveService.SaveAllOptionGroups(mod, false, config.ReplaceNonAsciiOnImport); - communicator.ModOptionChanged.Invoke(ModOptionChangeType.GroupDeleted, mod, null, null, null, idx); + communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.GroupDeleted, mod, null, null, null, idx)); } /// Move the index of a given option group. @@ -98,7 +98,7 @@ public class ModGroupEditor( return; saveService.SaveAllOptionGroups(mod, false, config.ReplaceNonAsciiOnImport); - communicator.ModOptionChanged.Invoke(ModOptionChangeType.GroupMoved, mod, group, null, null, idxFrom); + communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.GroupMoved, mod, group, null, null, idxFrom)); } /// Change the internal priority of the given option group. @@ -109,7 +109,7 @@ public class ModGroupEditor( group.Priority = newPriority; saveService.QueueSave(new ModSaveGroup(group, config.ReplaceNonAsciiOnImport)); - communicator.ModOptionChanged.Invoke(ModOptionChangeType.PriorityChanged, group.Mod, group, null, null, -1); + communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.PriorityChanged, group.Mod, group, null, null, -1)); } /// Change the description of the given option group. @@ -120,7 +120,7 @@ public class ModGroupEditor( group.Description = newDescription; saveService.QueueSave(new ModSaveGroup(group, config.ReplaceNonAsciiOnImport)); - communicator.ModOptionChanged.Invoke(ModOptionChangeType.DisplayChange, group.Mod, group, null, null, -1); + communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.DisplayChange, group.Mod, group, null, null, -1)); } /// Rename the given option. @@ -131,7 +131,7 @@ public class ModGroupEditor( option.Name = newName; saveService.QueueSave(new ModSaveGroup(option.Group, config.ReplaceNonAsciiOnImport)); - communicator.ModOptionChanged.Invoke(ModOptionChangeType.DisplayChange, option.Mod, option.Group, option, null, -1); + communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.DisplayChange, option.Mod, option.Group, option, null, -1)); } /// Change the description of the given option. @@ -142,7 +142,7 @@ public class ModGroupEditor( option.Description = newDescription; saveService.QueueSave(new ModSaveGroup(option.Group, config.ReplaceNonAsciiOnImport)); - communicator.ModOptionChanged.Invoke(ModOptionChangeType.DisplayChange, option.Mod, option.Group, option, null, -1); + communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.DisplayChange, option.Mod, option.Group, option, null, -1)); } /// Set the meta manipulations for a given option. Replaces existing manipulations. @@ -151,10 +151,10 @@ public class ModGroupEditor( if (subMod.Manipulations.Equals(manipulations)) return; - communicator.ModOptionChanged.Invoke(ModOptionChangeType.PrepareChange, (Mod)subMod.Mod, subMod.Group, null, subMod, -1); + communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.PrepareChange, (Mod)subMod.Mod, subMod.Group, null, subMod, -1)); subMod.Manipulations.SetTo(manipulations); saveService.Save(saveType, new ModSaveGroup(subMod, config.ReplaceNonAsciiOnImport)); - communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionMetaChanged, (Mod)subMod.Mod, subMod.Group, null, subMod, -1); + communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.OptionMetaChanged, (Mod)subMod.Mod, subMod.Group, null, subMod, -1)); } /// Set the file redirections for a given option. Replaces existing redirections. @@ -163,10 +163,10 @@ public class ModGroupEditor( if (subMod.Files.SetEquals(replacements)) return; - communicator.ModOptionChanged.Invoke(ModOptionChangeType.PrepareChange, (Mod)subMod.Mod, subMod.Group, null, subMod, -1); + communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.PrepareChange, (Mod)subMod.Mod, subMod.Group, null, subMod, -1)); subMod.Files.SetTo(replacements); saveService.Save(saveType, new ModSaveGroup(subMod, config.ReplaceNonAsciiOnImport)); - communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionFilesChanged, (Mod)subMod.Mod, subMod.Group, null, subMod, -1); + communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.OptionFilesChanged, (Mod)subMod.Mod, subMod.Group, null, subMod, -1)); } /// Forces a file save of the given container's group. @@ -181,7 +181,7 @@ public class ModGroupEditor( if (oldCount != subMod.Files.Count) { saveService.QueueSave(new ModSaveGroup(subMod, config.ReplaceNonAsciiOnImport)); - communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionFilesAdded, (Mod)subMod.Mod, subMod.Group, null, subMod, -1); + communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.OptionFilesAdded, (Mod)subMod.Mod, subMod.Group, null, subMod, -1)); } } @@ -191,10 +191,10 @@ public class ModGroupEditor( if (subMod.FileSwaps.SetEquals(swaps)) return; - communicator.ModOptionChanged.Invoke(ModOptionChangeType.PrepareChange, (Mod)subMod.Mod, subMod.Group, null, subMod, -1); + communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.PrepareChange, (Mod)subMod.Mod, subMod.Group, null, subMod, -1)); subMod.FileSwaps.SetTo(swaps); saveService.Save(saveType, new ModSaveGroup(subMod, config.ReplaceNonAsciiOnImport)); - communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionSwapsChanged, (Mod)subMod.Mod, subMod.Group, null, subMod, -1); + communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.OptionSwapsChanged, (Mod)subMod.Mod, subMod.Group, null, subMod, -1)); } /// Verify that a new option group name is unique in this mod. diff --git a/Penumbra/Mods/Manager/OptionEditor/ModOptionEditor.cs b/Penumbra/Mods/Manager/OptionEditor/ModOptionEditor.cs index c644ba18..304c41f4 100644 --- a/Penumbra/Mods/Manager/OptionEditor/ModOptionEditor.cs +++ b/Penumbra/Mods/Manager/OptionEditor/ModOptionEditor.cs @@ -1,5 +1,5 @@ using Luna; -using Luna.Files; +using Penumbra.Communication; using Penumbra.Mods.Groups; using Penumbra.Mods.Settings; using Penumbra.Mods.SubMods; @@ -28,7 +28,7 @@ public abstract class ModOptionEditor( var group = CreateGroup(mod, newName, maxPriority); mod.Groups.Add(group); SaveService.Save(saveType, new ModSaveGroup(group, Config.ReplaceNonAsciiOnImport)); - Communicator.ModOptionChanged.Invoke(ModOptionChangeType.GroupAdded, mod, group, null, null, -1); + Communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.GroupAdded, mod, group, null, null, -1)); return group; } @@ -57,7 +57,7 @@ public abstract class ModOptionEditor( return null; SaveService.Save(saveType, new ModSaveGroup(group, Config.ReplaceNonAsciiOnImport)); - Communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionAdded, group.Mod, group, option, null, -1); + Communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.OptionAdded, group.Mod, group, option, null, -1)); return option; } @@ -85,7 +85,7 @@ public abstract class ModOptionEditor( return null; SaveService.QueueSave(new ModSaveGroup(group, Config.ReplaceNonAsciiOnImport)); - Communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionAdded, group.Mod, group, clonedOption, null, -1); + Communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.OptionAdded, group.Mod, group, clonedOption, null, -1)); return clonedOption; } @@ -95,10 +95,10 @@ public abstract class ModOptionEditor( var mod = option.Mod; var group = option.Group; var optionIdx = option.GetIndex(); - Communicator.ModOptionChanged.Invoke(ModOptionChangeType.PrepareChange, mod, group, option, null, -1); + Communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.PrepareChange, mod, group, option, null, -1)); RemoveOption((TGroup)group, optionIdx); SaveService.QueueSave(new ModSaveGroup(group, Config.ReplaceNonAsciiOnImport)); - Communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionDeleted, mod, group, null, null, optionIdx); + Communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.OptionDeleted, mod, group, null, null, optionIdx)); } /// Move an option inside the given option group. @@ -110,7 +110,7 @@ public abstract class ModOptionEditor( return; SaveService.QueueSave(new ModSaveGroup(group, Config.ReplaceNonAsciiOnImport)); - Communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionMoved, group.Mod, group, option, null, idx); + Communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.OptionMoved, group.Mod, group, option, null, idx)); } protected abstract TGroup CreateGroup(Mod mod, string newName, ModPriority priority, SaveType saveType = SaveType.ImmediateSync); diff --git a/Penumbra/Mods/Manager/OptionEditor/MultiModGroupEditor.cs b/Penumbra/Mods/Manager/OptionEditor/MultiModGroupEditor.cs index 75e2d867..488d4025 100644 --- a/Penumbra/Mods/Manager/OptionEditor/MultiModGroupEditor.cs +++ b/Penumbra/Mods/Manager/OptionEditor/MultiModGroupEditor.cs @@ -1,5 +1,6 @@ -using Luna.Files; +using Luna; using OtterGui.Filesystem; +using Penumbra.Communication; using Penumbra.Mods.Groups; using Penumbra.Mods.Settings; using Penumbra.Mods.SubMods; @@ -16,7 +17,7 @@ public sealed class MultiModGroupEditor(CommunicatorService communicator, SaveSe var singleGroup = group.ConvertToSingle(); group.Mod.Groups[idx] = singleGroup; SaveService.QueueSave(new ModSaveGroup(singleGroup, Config.ReplaceNonAsciiOnImport)); - Communicator.ModOptionChanged.Invoke(ModOptionChangeType.GroupTypeChanged, singleGroup.Mod, singleGroup, null, null, -1); + Communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.GroupTypeChanged, singleGroup.Mod, singleGroup, null, null, -1)); } /// Change the internal priority of the given option. @@ -27,7 +28,7 @@ public sealed class MultiModGroupEditor(CommunicatorService communicator, SaveSe option.Priority = newPriority; SaveService.QueueSave(new ModSaveGroup(option.Group, Config.ReplaceNonAsciiOnImport)); - Communicator.ModOptionChanged.Invoke(ModOptionChangeType.PriorityChanged, option.Mod, option.Group, option, null, -1); + Communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.PriorityChanged, option.Mod, option.Group, option, null, -1)); } protected override MultiModGroup CreateGroup(Mod mod, string newName, ModPriority priority, SaveType saveType = SaveType.ImmediateSync) @@ -74,7 +75,7 @@ public sealed class MultiModGroupEditor(CommunicatorService communicator, SaveSe protected override bool MoveOption(MultiModGroup group, int optionIdxFrom, int optionIdxTo) { - if (!group.OptionData.Move(ref optionIdxFrom, ref optionIdxTo)) + if (!Extensions.Move(group.OptionData, ref optionIdxFrom, ref optionIdxTo)) return false; group.DefaultSettings = group.DefaultSettings.MoveBit(optionIdxFrom, optionIdxTo); diff --git a/Penumbra/Mods/Manager/OptionEditor/SingleModGroupEditor.cs b/Penumbra/Mods/Manager/OptionEditor/SingleModGroupEditor.cs index daa72819..baea361b 100644 --- a/Penumbra/Mods/Manager/OptionEditor/SingleModGroupEditor.cs +++ b/Penumbra/Mods/Manager/OptionEditor/SingleModGroupEditor.cs @@ -1,5 +1,6 @@ -using Luna.Files; +using Luna; using OtterGui.Filesystem; +using Penumbra.Communication; using Penumbra.Mods.Groups; using Penumbra.Mods.Settings; using Penumbra.Mods.SubMods; @@ -8,7 +9,7 @@ using Penumbra.Services; namespace Penumbra.Mods.Manager.OptionEditor; public sealed class SingleModGroupEditor(CommunicatorService communicator, SaveService saveService, Configuration config) - : ModOptionEditor(communicator, saveService, config), Luna.IService + : ModOptionEditor(communicator, saveService, config), IService { public void ChangeToMulti(SingleModGroup group) { @@ -16,7 +17,7 @@ public sealed class SingleModGroupEditor(CommunicatorService communicator, SaveS var multiGroup = group.ConvertToMulti(); group.Mod.Groups[idx] = multiGroup; SaveService.QueueSave(new ModSaveGroup(multiGroup, Config.ReplaceNonAsciiOnImport)); - Communicator.ModOptionChanged.Invoke(ModOptionChangeType.GroupTypeChanged, multiGroup.Mod, multiGroup, null, null, -1); + Communicator.ModOptionChanged.Invoke(new ModOptionChanged.Arguments(ModOptionChangeType.GroupTypeChanged, multiGroup.Mod, multiGroup, null, null, -1)); } protected override SingleModGroup CreateGroup(Mod mod, string newName, ModPriority priority, SaveType saveType = SaveType.ImmediateSync) @@ -47,7 +48,7 @@ public sealed class SingleModGroupEditor(CommunicatorService communicator, SaveS protected override bool MoveOption(SingleModGroup group, int optionIdxFrom, int optionIdxTo) { - if (!group.OptionData.Move(ref optionIdxFrom, ref optionIdxTo)) + if (!Extensions.Move(group.OptionData, ref optionIdxFrom, ref optionIdxTo)) return false; group.DefaultSettings = group.DefaultSettings.MoveSingle(optionIdxFrom, optionIdxTo); diff --git a/Penumbra/Mods/ModSelection.cs b/Penumbra/Mods/ModSelection.cs index b728bd00..986f074b 100644 --- a/Penumbra/Mods/ModSelection.cs +++ b/Penumbra/Mods/ModSelection.cs @@ -1,5 +1,4 @@ -using OtterGui.Classes; -using Penumbra.Api.Enums; +using Luna; using Penumbra.Collections; using Penumbra.Collections.Manager; using Penumbra.Communication; @@ -16,14 +15,14 @@ namespace Penumbra.Mods; /// Parameter is the new selected mod /// /// -public class ModSelection : EventWrapper +public class ModSelection : EventBase { private readonly ActiveCollections _collections; private readonly EphemeralConfig _config; private readonly CommunicatorService _communicator; - public ModSelection(CommunicatorService communicator, ModManager mods, ActiveCollections collections, EphemeralConfig config) - : base(nameof(ModSelection)) + public ModSelection(Logger log, CommunicatorService communicator, ModManager mods, ActiveCollections collections, EphemeralConfig config) + : base(nameof(ModSelection), log) { _communicator = communicator; _collections = collections; @@ -49,8 +48,8 @@ public class ModSelection : EventWrapper var oldMod = Mod; Mod = mod; - OnCollectionChange(CollectionType.Current, null, _collections.Current, string.Empty); - Invoke(oldMod, Mod); + OnCollectionChange(new CollectionChange.Arguments(CollectionType.Current, null, _collections.Current, string.Empty)); + Invoke(new Arguments(oldMod, Mod)); _config.LastModPath = mod?.ModPath.Name ?? string.Empty; _config.Save(); } @@ -62,21 +61,21 @@ public class ModSelection : EventWrapper _communicator.ModSettingChanged.Unsubscribe(OnSettingChange); } - private void OnCollectionChange(CollectionType type, ModCollection? oldCollection, ModCollection? newCollection, string _2) + private void OnCollectionChange(in CollectionChange.Arguments arguments) { - if (type is CollectionType.Current && oldCollection != newCollection) + if (arguments.Type is CollectionType.Current && arguments.OldCollection != arguments.NewCollection) UpdateSettings(); } - private void OnSettingChange(ModCollection collection, ModSettingChange _1, Mod? mod, Setting _2, int _3, bool _4) + private void OnSettingChange(in ModSettingChanged.Arguments arguments) { - if (collection == _collections.Current && mod == Mod) + if (arguments.Collection == _collections.Current && arguments.Mod == Mod) UpdateSettings(); } - private void OnInheritanceChange(ModCollection collection, bool arg2) + private void OnInheritanceChange(in CollectionInheritanceChanged.Arguments arguments) { - if (collection == _collections.Current) + if (arguments.Collection == _collections.Current) UpdateSettings(); } @@ -105,4 +104,6 @@ public class ModSelection : EventWrapper /// ModMerger = 0, } + + public readonly record struct Arguments(Mod? OldSelection, Mod? NewSelection); } diff --git a/Penumbra/Penumbra.cs b/Penumbra/Penumbra.cs index 655c5577..0d9f7ad6 100644 --- a/Penumbra/Penumbra.cs +++ b/Penumbra/Penumbra.cs @@ -19,6 +19,7 @@ using ResidentResourceManager = Penumbra.Interop.Services.ResidentResourceManage using Dalamud.Plugin.Services; using Lumina.Excel.Sheets; using Luna; +using Penumbra.Communication; using Penumbra.GameData.Data; using Penumbra.Interop; using Penumbra.Interop.Hooks; @@ -31,9 +32,9 @@ namespace Penumbra; public class Penumbra : IDalamudPlugin { - public static readonly OtterGui.Log.Logger Log = new(); - public static MessageService Messager { get; private set; } = null!; - public static DynamisIpc Dynamis { get; private set; } = null!; + public static readonly OtterGui.Log.Logger Log = new(); + public static MessageService Messager { get; private set; } = null!; + public static DynamisIpc Dynamis { get; private set; } = null!; private readonly ValidityChecker _validityChecker; private readonly ResidentResourceManager _residentResources; @@ -49,14 +50,14 @@ public class Penumbra : IDalamudPlugin private PenumbraWindowSystem? _windowSystem; private bool _disposed; - private readonly Luna.ServiceManager _services; + private readonly ServiceManager _services; public Penumbra(IDalamudPluginInterface pluginInterface) { try { HookOverrides.Instance = HookOverrides.LoadFile(pluginInterface); - _services = StaticServiceManager.CreateProvider(this, pluginInterface, new("Penumbra")); + _services = StaticServiceManager.CreateProvider(this, pluginInterface, new Logger("Penumbra")); // Invoke the IPC Penumbra.Launching method before any hooks or other services are created. _services.GetService(); Messager = _services.GetService(); @@ -64,7 +65,7 @@ public class Penumbra : IDalamudPlugin _validityChecker = _services.GetService(); _services.EnsureRequiredServices(); _services.EnsureRequiredServices(); - + var startup = _services.GetService() .GetDalamudConfig(DalamudConfigService.WaitingForPluginsOption, out bool s) ? s.ToString() @@ -87,21 +88,21 @@ public class Penumbra : IDalamudPlugin _services.GetService(); // Initialize because not required anywhere else. _collectionManager.Caches.CreateNecessaryCaches(); _services.GetService(); - + _services.GetService(); // Initialize before Interface. - - foreach (var service in _services.GetServicesImplementing()) + + foreach (var service in _services.GetServicesImplementing()) service.Awaiter.Wait(); - + SetupInterface(); SetupApi(); - + _validityChecker.LogExceptions(); Log.Information( $"Penumbra Version {_validityChecker.Version}, Commit #{_validityChecker.CommitHash} successfully Loaded from {pluginInterface.SourceRepository}."); OtterTex.NativeDll.Initialize(pluginInterface.AssemblyLocation.DirectoryName); Log.Information($"Loading native OtterTex assembly from {OtterTex.NativeDll.Directory}."); - + if (_characterUtility.Ready) _residentResources.Reload(); } @@ -117,15 +118,15 @@ public class Penumbra : IDalamudPlugin { _services.GetService(); var itemSheet = _services.GetService().GetExcelSheet(); - _communicatorService.ChangedItemHover.Subscribe(it => + _communicatorService.ChangedItemHover.Subscribe((in ChangedItemHover.Arguments args) => { - if (it is IdentifiedItem { Item.Id.IsItem: true }) + if (args.Data is IdentifiedItem { Item.Id.IsItem: true }) ImGui.TextUnformatted("Left Click to create an item link in chat."); }, ChangedItemHover.Priority.Link); - _communicatorService.ChangedItemClick.Subscribe((button, it) => + _communicatorService.ChangedItemClick.Subscribe((in ChangedItemClick.Arguments args) => { - if (button == MouseButton.Left && it is IdentifiedItem item && itemSheet.GetRow(item.Item.ItemId.Id) is { } i) + if (args is { Button: MouseButton.Left, Data: IdentifiedItem item } && itemSheet.GetRow(item.Item.ItemId.Id) is { } i) Messager.LinkItem(i); }, ChangedItemClick.Priority.Link); } @@ -169,7 +170,7 @@ public class Penumbra : IDalamudPlugin } _config.Save(); - _communicatorService.EnabledChanged.Invoke(enabled); + _communicatorService.EnabledChanged.Invoke(new EnabledChanged.Arguments(enabled)); return true; } diff --git a/Penumbra/Services/BackupService.cs b/Penumbra/Services/BackupService.cs index 0e9cbf03..da5ad779 100644 --- a/Penumbra/Services/BackupService.cs +++ b/Penumbra/Services/BackupService.cs @@ -3,44 +3,8 @@ using Newtonsoft.Json.Linq; namespace Penumbra.Services; -public class BackupService : IAsyncService +public sealed class BackupService(Logger log, FilenameService provider) : BaseBackupService(log, provider) { - private readonly Logger _logger; - private readonly DirectoryInfo _configDirectory; - private readonly IReadOnlyList _fileNames; - - /// - public Task Awaiter { get; } - - /// - public bool Finished - => Awaiter.IsCompletedSuccessfully; - - /// Start a backup process on the collected files. - public BackupService(Logger logger, FilenameService fileNames) - { - _logger = logger; - _fileNames = PenumbraFiles(fileNames); - _configDirectory = new DirectoryInfo(fileNames.ConfigurationDirectory); - Awaiter = Task.Run(() => Backup.CreateAutomaticBackup(logger, new DirectoryInfo(fileNames.ConfigurationDirectory), _fileNames)); - } - - /// Create a permanent backup with a given name for migrations. - public void CreateMigrationBackup(string name) - => Backup.CreatePermanentBackup(_logger, _configDirectory, _fileNames, name); - - /// Collect all relevant files for penumbra configuration. - private static IReadOnlyList PenumbraFiles(FilenameService fileNames) - { - var list = fileNames.CollectionFiles.ToList(); - list.AddRange(fileNames.LocalDataFiles); - list.Add(new FileInfo(fileNames.ConfigurationFile)); - list.Add(new FileInfo(fileNames.FilesystemFile)); - list.Add(new FileInfo(fileNames.ActiveCollectionsFile)); - list.Add(new FileInfo(fileNames.PredefinedTagFile)); - return list; - } - /// Try to parse a file to JObject and check backups if this does not succeed. public static JObject? GetJObjectForFile(FilenameService fileNames, string fileName) { diff --git a/Penumbra/Services/CommunicatorService.cs b/Penumbra/Services/CommunicatorService.cs index 85a4c105..2bdadb78 100644 --- a/Penumbra/Services/CommunicatorService.cs +++ b/Penumbra/Services/CommunicatorService.cs @@ -1,116 +1,85 @@ -using OtterGui.Classes; -using OtterGui.Log; +using Luna; using Penumbra.Communication; namespace Penumbra.Services; -public class CommunicatorService : IDisposable, Luna.IService +public class CommunicatorService(ServiceManager services) : IService { - public CommunicatorService(Logger logger) - { - EventWrapperBase.ChangeLogger(logger); - } - /// - public readonly CollectionChange CollectionChange = new(); + public readonly CollectionChange CollectionChange = services.GetService(); /// - public readonly TemporaryGlobalModChange TemporaryGlobalModChange = new(); + public readonly TemporaryGlobalModChange TemporaryGlobalModChange = services.GetService(); /// - public readonly CreatingCharacterBase CreatingCharacterBase = new(); + public readonly CreatingCharacterBase CreatingCharacterBase = services.GetService(); /// - public readonly CreatedCharacterBase CreatedCharacterBase = new(); + public readonly CreatedCharacterBase CreatedCharacterBase = services.GetService(); /// - public readonly MtrlLoaded MtrlLoaded = new(); + public readonly MtrlLoaded MtrlLoaded = services.GetService(); /// - public readonly ModDataChanged ModDataChanged = new(); + public readonly ModDataChanged ModDataChanged = services.GetService(); /// - public readonly ModOptionChanged ModOptionChanged = new(); + public readonly ModOptionChanged ModOptionChanged = services.GetService(); /// - public readonly ModDiscoveryStarted ModDiscoveryStarted = new(); + public readonly ModDiscoveryStarted ModDiscoveryStarted = services.GetService(); /// - public readonly ModDiscoveryFinished ModDiscoveryFinished = new(); + public readonly ModDiscoveryFinished ModDiscoveryFinished = services.GetService(); /// - public readonly ModDirectoryChanged ModDirectoryChanged = new(); + public readonly ModDirectoryChanged ModDirectoryChanged = services.GetService(); /// - public readonly ModFileChanged ModFileChanged = new(); + public readonly ModFileChanged ModFileChanged = services.GetService(); /// - public readonly ModPathChanged ModPathChanged = new(); + public readonly ModPathChanged ModPathChanged = services.GetService(); /// - public readonly ModSettingChanged ModSettingChanged = new(); + public readonly ModSettingChanged ModSettingChanged = services.GetService(); /// - public readonly CollectionInheritanceChanged CollectionInheritanceChanged = new(); + public readonly CollectionInheritanceChanged CollectionInheritanceChanged = services.GetService(); /// - public readonly EnabledChanged EnabledChanged = new(); + public readonly EnabledChanged EnabledChanged = services.GetService(); /// - public readonly PreSettingsTabBarDraw PreSettingsTabBarDraw = new(); + public readonly PreSettingsTabBarDraw PreSettingsTabBarDraw = services.GetService(); /// - public readonly PreSettingsPanelDraw PreSettingsPanelDraw = new(); + public readonly PreSettingsPanelDraw PreSettingsPanelDraw = services.GetService(); /// - public readonly PostEnabledDraw PostEnabledDraw = new(); + public readonly PostEnabledDraw PostEnabledDraw = services.GetService(); /// - public readonly PostSettingsPanelDraw PostSettingsPanelDraw = new(); + public readonly PostSettingsPanelDraw PostSettingsPanelDraw = services.GetService(); /// - public readonly ChangedItemHover ChangedItemHover = new(); + public readonly ChangedItemHover ChangedItemHover = services.GetService(); /// - public readonly ChangedItemClick ChangedItemClick = new(); + public readonly ChangedItemClick ChangedItemClick = services.GetService(); /// - public readonly SelectTab SelectTab = new(); + public readonly SelectTab SelectTab = services.GetService(); /// - public readonly ResolvedFileChanged ResolvedFileChanged = new(); + public readonly ResolvedFileChanged ResolvedFileChanged = services.GetService(); /// - public readonly PcpCreation PcpCreation = new(); + public readonly PcpCreation PcpCreation = services.GetService(); /// - public readonly PcpParsing PcpParsing = new(); + public readonly PcpParsing PcpParsing = services.GetService(); - public void Dispose() - { - CollectionChange.Dispose(); - TemporaryGlobalModChange.Dispose(); - CreatingCharacterBase.Dispose(); - CreatedCharacterBase.Dispose(); - MtrlLoaded.Dispose(); - ModDataChanged.Dispose(); - ModOptionChanged.Dispose(); - ModDiscoveryStarted.Dispose(); - ModDiscoveryFinished.Dispose(); - ModDirectoryChanged.Dispose(); - ModPathChanged.Dispose(); - ModSettingChanged.Dispose(); - CollectionInheritanceChanged.Dispose(); - EnabledChanged.Dispose(); - PreSettingsTabBarDraw.Dispose(); - PreSettingsPanelDraw.Dispose(); - PostEnabledDraw.Dispose(); - PostSettingsPanelDraw.Dispose(); - ChangedItemHover.Dispose(); - ChangedItemClick.Dispose(); - SelectTab.Dispose(); - ResolvedFileChanged.Dispose(); - PcpCreation.Dispose(); - PcpParsing.Dispose(); - } + /// + public readonly CharacterUtilityFinished LoadingFinished = services.GetService(); } diff --git a/Penumbra/Services/CrashHandlerService.cs b/Penumbra/Services/CrashHandlerService.cs index 566dc20c..23a01988 100644 --- a/Penumbra/Services/CrashHandlerService.cs +++ b/Penumbra/Services/CrashHandlerService.cs @@ -248,18 +248,18 @@ public sealed class CrashHandlerService : IDisposable, Luna.IService } } - private void OnCreatingCharacterBase(nint address, Guid collection, nint _1, nint _2, nint _3) + private void OnCreatingCharacterBase(in CreatingCharacterBase.Arguments arguments) { - if (_eventWriter == null) + if (_eventWriter is null) return; try { - var name = GetActorName(address); + var name = GetActorName(arguments.GameObject); lock (_eventWriter) { - _eventWriter?.CharacterBase.WriteLine(address, name.Span, collection); + _eventWriter?.CharacterBase.WriteLine(arguments.GameObject, name.Span, arguments.Collection.Identity.Id); } } catch (Exception ex) diff --git a/Penumbra/Services/FilenameService.cs b/Penumbra/Services/FilenameService.cs index 0b7a07c3..b135ea10 100644 --- a/Penumbra/Services/FilenameService.cs +++ b/Penumbra/Services/FilenameService.cs @@ -1,5 +1,5 @@ using Dalamud.Plugin; -using Luna.Files; +using Luna; using Penumbra.Collections; using Penumbra.Mods; @@ -80,4 +80,16 @@ public sealed class FilenameService(IDalamudPluginInterface pi) : BaseFilePathPr /// Enumerate all group files for a given mod. public IEnumerable GetOptionGroupFiles(Mod mod) => mod.ModPath.EnumerateFiles("group_*.json"); + + /// Collect all relevant files for penumbra configuration. + public override List GetBackupFiles() + { + var list = CollectionFiles.ToList(); + list.AddRange(LocalDataFiles); + list.Add(new FileInfo(ConfigurationFile)); + list.Add(new FileInfo(FilesystemFile)); + list.Add(new FileInfo(ActiveCollectionsFile)); + list.Add(new FileInfo(PredefinedTagFile)); + return list; + } } diff --git a/Penumbra/Services/PcpService.cs b/Penumbra/Services/PcpService.cs index d5e1ba42..6174db19 100644 --- a/Penumbra/Services/PcpService.cs +++ b/Penumbra/Services/PcpService.cs @@ -86,18 +86,18 @@ public class PcpService : IApiService, IDisposable _collections.Storage.RemoveCollection(collection); } - private void OnModPathChange(ModPathChangeType type, Mod mod, DirectoryInfo? oldDirectory, DirectoryInfo? newDirectory) + private void OnModPathChange(in ModPathChanged.Arguments arguments) { - if (type is not ModPathChangeType.Added || _config.PcpSettings.DisableHandling || newDirectory is null) + if (arguments.Type is not ModPathChangeType.Added || _config.PcpSettings.DisableHandling || arguments.NewDirectory is null) return; try { - var file = Path.Combine(newDirectory.FullName, "character.json"); + var file = Path.Combine(arguments.NewDirectory.FullName, "character.json"); if (!File.Exists(file)) { // First version had collection.json, changed. - var oldFile = Path.Combine(newDirectory.FullName, "collection.json"); + var oldFile = Path.Combine(arguments.NewDirectory.FullName, "collection.json"); if (File.Exists(oldFile)) { Penumbra.Log.Information("[PCPService] Renaming old PCP file from collection.json to character.json."); @@ -107,7 +107,7 @@ public class PcpService : IApiService, IDisposable return; } - Penumbra.Log.Information($"[PCPService] Found a PCP file for {mod.Name}, applying."); + Penumbra.Log.Information($"[PCPService] Found a PCP file for {arguments.Mod.Name}, applying."); var text = File.ReadAllText(file); var jObj = JObject.Parse(text); var collection = ModCollection.Empty; @@ -121,7 +121,7 @@ public class PcpService : IApiService, IDisposable if (_collections.Storage.AddCollection(name, null)) { collection = _collections.Storage[^1]; - _collections.Editor.SetModState(collection, mod, true); + _collections.Editor.SetModState(collection, arguments.Mod, true); // Assign collection. if (_config.PcpSettings.AssignCollection) @@ -134,7 +134,7 @@ public class PcpService : IApiService, IDisposable } // Move to folder. - if (_fileSystem.TryGetValue(mod, out var leaf)) + if (_fileSystem.TryGetValue(arguments.Mod, out var leaf)) { try { @@ -149,11 +149,11 @@ public class PcpService : IApiService, IDisposable // Invoke IPC. if (_config.PcpSettings.AllowIpc) - _communicator.PcpParsing.Invoke(jObj, mod.Identifier, collection.Identity.Id); + _communicator.PcpParsing.Invoke(new PcpParsing.Arguments(jObj, arguments.Mod, collection)); } catch (Exception ex) { - Penumbra.Log.Error($"Error reading the character.json file from {mod.Identifier}:\n{ex}"); + Penumbra.Log.Error($"Error reading the character.json file from {arguments.Mod.Identifier}:\n{ex}"); } } @@ -220,7 +220,7 @@ public class PcpService : IApiService, IDisposable if (note.Length > 0) cancel.ThrowIfCancellationRequested(); if (_config.PcpSettings.AllowIpc) - await _framework.Framework.RunOnFrameworkThread(() => _communicator.PcpCreation.Invoke(jObj, index.Index, directory.FullName)); + await _framework.Framework.RunOnFrameworkThread(() => _communicator.PcpCreation.Invoke(new PcpCreation.Arguments(jObj, index.Index, directory.FullName))); var filePath = Path.Combine(directory.FullName, "character.json"); await using var file = File.Open(filePath, File.Exists(filePath) ? FileMode.Truncate : FileMode.CreateNew); await using var stream = new StreamWriter(file); diff --git a/Penumbra/Services/SaveService.cs b/Penumbra/Services/SaveService.cs index 505d08ac..949c0d3f 100644 --- a/Penumbra/Services/SaveService.cs +++ b/Penumbra/Services/SaveService.cs @@ -1,5 +1,4 @@ using Luna; -using Luna.Files; using Penumbra.Mods; using Penumbra.Mods.Groups; diff --git a/Penumbra/UI/AdvancedWindow/FileEditor.cs b/Penumbra/UI/AdvancedWindow/FileEditor.cs index 25fc111b..cdbf27cf 100644 --- a/Penumbra/UI/AdvancedWindow/FileEditor.cs +++ b/Penumbra/UI/AdvancedWindow/FileEditor.cs @@ -8,6 +8,7 @@ using OtterGui.Classes; using OtterGui.Raii; using OtterGui.Text; using OtterGui.Widgets; +using Penumbra.Communication; using Penumbra.GameData.Data; using Penumbra.GameData.Files; using Penumbra.Mods.Editor; @@ -216,7 +217,7 @@ public class FileEditor( { compactor.WriteAllBytes(_currentPath!.File.FullName, _currentFile!.Write()); if (owner.Mod != null) - communicator.ModFileChanged.Invoke(owner.Mod, _currentPath); + communicator.ModFileChanged.Invoke(new ModFileChanged.Arguments(owner.Mod, _currentPath)); _changed = false; } diff --git a/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs b/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs index faa35a3e..636688a3 100644 --- a/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs +++ b/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs @@ -6,7 +6,6 @@ using OtterGui.Raii; using OtterGui.Text; using OtterGui.Widgets; using Penumbra.Api.Enums; -using Penumbra.Collections; using Penumbra.Collections.Manager; using Penumbra.Communication; using Penumbra.GameData.Data; @@ -28,7 +27,7 @@ using Penumbra.UI.ModsTab; namespace Penumbra.UI.AdvancedWindow; -public class ItemSwapTab : IDisposable, ITab, Luna.IUiService +public class ItemSwapTab : IDisposable, ITab, IUiService { private readonly Configuration _config; private readonly CommunicatorService _communicator; @@ -141,11 +140,16 @@ public class ItemSwapTab : IDisposable, ITab, Luna.IUiService { var list = data.ByType[type]; var enumerable = selector?.Selected is { } mod && mod.ChangedItems.Values.Any(o => o is IdentifiedItem i && i.Item.Type == type) - ? list.Select(i => (i, mod.ChangedItems.ContainsKey(i.Name), collections.Current.ChangedItems.TryGetValue(i.Name, out var m) ? m.Item1 : new SingleArray())) + ? list.Select(i => (i, mod.ChangedItems.ContainsKey(i.Name), + collections.Current.ChangedItems.TryGetValue(i.Name, out var m) ? m.Item1 : new SingleArray())) .OrderByDescending(p => p.Item2).ThenByDescending(p => p.Item3.Count) : selector is null - ? list.Select(i => (i, false, collections.Current.ChangedItems.TryGetValue(i.Name, out var m) ? m.Item1 : new SingleArray())).OrderBy(p => p.Item3.Count) - : list.Select(i => (i, false, collections.Current.ChangedItems.TryGetValue(i.Name, out var m) ? m.Item1 : new SingleArray())).OrderByDescending(p => p.Item3.Count); + ? list.Select(i => (i, false, + collections.Current.ChangedItems.TryGetValue(i.Name, out var m) ? m.Item1 : new SingleArray())) + .OrderBy(p => p.Item3.Count) + : list.Select(i => (i, false, + collections.Current.ChangedItems.TryGetValue(i.Name, out var m) ? m.Item1 : new SingleArray())) + .OrderByDescending(p => p.Item3.Count); return enumerable.ToList(); }, MouseWheelType.None, Penumbra.Log) { @@ -526,7 +530,7 @@ public class ItemSwapTab : IDisposable, ITab, Luna.IUiService } ImGui.TableNextColumn(); - _dirty |= selector.Draw("##itemSource", selector.CurrentSelection.Item.Name ?? string.Empty, string.Empty, + _dirty |= selector.Draw("##itemSource", selector.CurrentSelection.Item.Name, string.Empty, InputWidth * 2 * UiHelpers.Scale, ImGui.GetTextLineHeightWithSpacing()); @@ -638,19 +642,6 @@ public class ItemSwapTab : IDisposable, ITab, Luna.IUiService DrawGenderInput(); } - private void DrawFaceSwap() - { - using var disabled = ImRaii.Disabled(); - using var tab = DrawTab(SwapType.Face); - if (!tab) - return; - - using var table = ImRaii.Table("##settings", 2, ImGuiTableFlags.SizingFixedFit); - DrawTargetIdInput("Take this Face Type"); - DrawSourceIdInput(); - DrawGenderInput(); - } - private void DrawTailSwap() { using var tab = DrawTab(SwapType.Tail); @@ -686,7 +677,7 @@ public class ItemSwapTab : IDisposable, ITab, Luna.IUiService ImGui.TableNextColumn(); ImGui.SetNextItemWidth(InputWidth * UiHelpers.Scale); - if (ImGui.InputInt("##targetId", ref _targetId, 0, 0)) + if (ImGui.InputInt("##targetId", ref _targetId)) _targetId = Math.Clamp(_targetId, 0, byte.MaxValue); _dirty |= ImGui.IsItemDeactivatedAfterEdit(); @@ -700,7 +691,7 @@ public class ItemSwapTab : IDisposable, ITab, Luna.IUiService ImGui.TableNextColumn(); ImGui.SetNextItemWidth(InputWidth * UiHelpers.Scale); - if (ImGui.InputInt("##sourceId", ref _sourceId, 0, 0)) + if (ImGui.InputInt("##sourceId", ref _sourceId)) _sourceId = Math.Clamp(_sourceId, 0, byte.MaxValue); _dirty |= ImGui.IsItemDeactivatedAfterEdit(); @@ -713,7 +704,7 @@ public class ItemSwapTab : IDisposable, ITab, Luna.IUiService ImGui.TextUnformatted(text); ImGui.TableNextColumn(); - _dirty |= Combos.Gender("##Gender", _currentGender, out _currentGender, InputWidth); + _dirty |= Combos.Gender("##Gender", _currentGender, out _currentGender); if (drawRace == 1) { ImGui.SameLine(); @@ -725,12 +716,11 @@ public class ItemSwapTab : IDisposable, ITab, Luna.IUiService if (_currentRace is not ModelRace.Miqote and not ModelRace.AuRa and not ModelRace.Hrothgar) _currentRace = ModelRace.Miqote; - _dirty |= ImGuiUtil.GenericEnumCombo("##Race", InputWidth, _currentRace, out _currentRace, new[] - { + _dirty |= ImGuiUtil.GenericEnumCombo("##Race", InputWidth, _currentRace, out _currentRace, [ ModelRace.Miqote, ModelRace.AuRa, ModelRace.Hrothgar, - }, + ], RaceEnumExtensions.ToName); } } @@ -767,38 +757,40 @@ public class ItemSwapTab : IDisposable, ITab, Luna.IUiService DrawSwap(child); } - private void OnCollectionChange(CollectionType collectionType, ModCollection? oldCollection, - ModCollection? newCollection, string _) + private void OnCollectionChange(in CollectionChange.Arguments arguments) { - if (collectionType is not CollectionType.Current || _mod == null || newCollection == null) + if (arguments.Type is not CollectionType.Current || _mod is null || arguments.NewCollection is null) return; - UpdateMod(_mod, _mod.Index < newCollection.Settings.Count ? newCollection.GetInheritedSettings(_mod.Index).Settings : null); + UpdateMod(_mod, + _mod.Index < arguments.NewCollection.Settings.Count ? arguments.NewCollection.GetInheritedSettings(_mod.Index).Settings : null); } - private void OnSettingChange(ModCollection collection, ModSettingChange type, Mod? mod, Setting oldValue, int groupIdx, bool inherited) + private void OnSettingChange(in ModSettingChanged.Arguments arguments) { - if (collection != _collectionManager.Active.Current || mod != _mod || type is ModSettingChange.TemporarySetting) + if (arguments.Collection != _collectionManager.Active.Current + || arguments.Mod != _mod + || arguments.Type is ModSettingChange.TemporarySetting) return; _swapData.LoadMod(_mod, _modSettings); _dirty = true; } - private void OnInheritanceChange(ModCollection collection, bool _) + private void OnInheritanceChange(in CollectionInheritanceChanged.Arguments arguments) { - if (collection != _collectionManager.Active.Current || _mod == null) + if (arguments.Collection != _collectionManager.Active.Current || _mod == null) return; - UpdateMod(_mod, collection.GetInheritedSettings(_mod.Index).Settings); + UpdateMod(_mod, arguments.Collection.GetInheritedSettings(_mod.Index).Settings); _swapData.LoadMod(_mod, _modSettings); _dirty = true; } - private void OnModOptionChange(ModOptionChangeType type, Mod mod, IModGroup? group, IModOption? option, IModDataContainer? container, - int fromIdx) + private void OnModOptionChange(in ModOptionChanged.Arguments arguments) { - if (type is ModOptionChangeType.PrepareChange or ModOptionChangeType.GroupAdded or ModOptionChangeType.OptionAdded || mod != _mod) + if (arguments.Type is ModOptionChangeType.PrepareChange or ModOptionChangeType.GroupAdded or ModOptionChangeType.OptionAdded + || arguments.Mod != _mod) return; _swapData.LoadMod(_mod, _modSettings); diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LivePreview.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LivePreview.cs index dfa3a963..6873f8ff 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LivePreview.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LivePreview.cs @@ -1,9 +1,9 @@ using Dalamud.Bindings.ImGui; -using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using OtterGui.Raii; using OtterGui.Text; using Penumbra.GameData.Files.MaterialStructs; using Penumbra.GameData.Structs; +using Penumbra.Interop.Hooks.Objects; using Penumbra.Interop.MaterialPreview; using Penumbra.Services; using Penumbra.UI.Classes; @@ -91,12 +91,12 @@ public partial class MtrlTab _colorTablePreviewers.Clear(); } - private unsafe void UnbindFromDrawObjectMaterialInstances(CharacterBase* characterBase) + private unsafe void UnbindFromDrawObjectMaterialInstances(in CharacterBaseDestructor.Arguments arguments) { for (var i = _materialPreviewers.Count; i-- > 0;) { var previewer = _materialPreviewers[i]; - if (previewer.DrawObject != characterBase) + if (previewer.DrawObject != arguments.CharacterBase) continue; previewer.Dispose(); @@ -106,7 +106,7 @@ public partial class MtrlTab for (var i = _colorTablePreviewers.Count; i-- > 0;) { var previewer = _colorTablePreviewers[i]; - if (previewer.DrawObject != characterBase) + if (previewer.DrawObject != arguments.CharacterBase) continue; previewer.Dispose(); diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Textures.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Textures.cs index 2ad0a341..66b0c08b 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Textures.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Textures.cs @@ -3,6 +3,7 @@ using Luna; using OtterGui; using OtterGui.Raii; using OtterTex; +using Penumbra.Communication; using Penumbra.Import.Textures; using Penumbra.Mods; using Penumbra.UI.Classes; @@ -229,7 +230,7 @@ public partial class ModEditWindow out var registry)) return; - _communicator.ModFileChanged.Invoke(mod, registry); + _communicator.ModFileChanged.Invoke(new ModFileChanged.Arguments(mod, registry)); } private void OpenSaveAsDialog(string defaultExtension) diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.cs index 8428e492..0ee7dae6 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.cs @@ -681,12 +681,12 @@ public partial class ModEditWindow : Window, IDisposable, Luna.IUiService _center.Dispose(); } - private void OnModPathChange(ModPathChangeType type, Mod mod, DirectoryInfo? _1, DirectoryInfo? _2) + private void OnModPathChange(in ModPathChanged.Arguments arguments) { - if (type is not (ModPathChangeType.Reloaded or ModPathChangeType.Moved) || mod != Mod) + if (arguments.Type is not (ModPathChangeType.Reloaded or ModPathChangeType.Moved) || arguments.Mod != Mod) return; Mod = null; - ChangeMod(mod); + ChangeMod(arguments.Mod); } } diff --git a/Penumbra/UI/AdvancedWindow/ResourceTreeViewer.cs b/Penumbra/UI/AdvancedWindow/ResourceTreeViewer.cs index 56102f8e..9f6a9e83 100644 --- a/Penumbra/UI/AdvancedWindow/ResourceTreeViewer.cs +++ b/Penumbra/UI/AdvancedWindow/ResourceTreeViewer.cs @@ -10,6 +10,7 @@ using OtterGui; using OtterGui.Raii; using OtterGui.Text; using Penumbra.Api.Enums; +using Penumbra.Communication; using Penumbra.GameData.Files; using Penumbra.GameData.Structs; using Penumbra.Interop.ResourceTree; @@ -344,7 +345,7 @@ public class ResourceTreeViewer( if (ImGui.IsItemClicked()) ImGui.SetClipboardText(resourceNode.FullPath.ToPath()); if (hasMod && ImGui.IsItemClicked(ImGuiMouseButton.Right) && ImGui.GetIO().KeyCtrl) - communicator.SelectTab.Invoke(TabType.Mods, mod); + communicator.SelectTab.Invoke(new SelectTab.Arguments(TabType.Mods, mod)); ImGuiUtil.HoverTooltip( $"{resourceNode.FullPath.ToPath()}\n\nClick to copy to clipboard.{(hasMod ? "\nControl + Right-Click to jump to mod." : string.Empty)}{GetAdditionalDataSuffix(resourceNode.AdditionalData)}"); diff --git a/Penumbra/UI/ChangedItemDrawer.cs b/Penumbra/UI/ChangedItemDrawer.cs index 25797f1e..97aec626 100644 --- a/Penumbra/UI/ChangedItemDrawer.cs +++ b/Penumbra/UI/ChangedItemDrawer.cs @@ -10,6 +10,7 @@ using OtterGui.Classes; using OtterGui.Raii; using OtterGui.Text; using Penumbra.Api.Enums; +using Penumbra.Communication; using Penumbra.GameData.Data; using Penumbra.Services; using Penumbra.UI.Classes; @@ -122,7 +123,7 @@ public class ChangedItemDrawer : IDisposable, Luna.IUiService ret = ImGui.IsItemClicked(ImGuiMouseButton.Right) ? MouseButton.Right : ret; ret = ImGui.IsItemClicked(ImGuiMouseButton.Middle) ? MouseButton.Middle : ret; if (ret != MouseButton.None) - _communicator.ChangedItemClick.Invoke(ret, data); + _communicator.ChangedItemClick.Invoke(new ChangedItemClick.Arguments(ret, data)); if (!ImGui.IsItemHovered()) return; @@ -134,7 +135,7 @@ public class ChangedItemDrawer : IDisposable, Luna.IUiService ImGui.SetCursorPosY(ImGui.GetCursorPosY() + 3 * ImUtf8.GlobalScale); ImGui.Separator(); ImGui.SetCursorPosY(ImGui.GetCursorPosY() + 3 * ImUtf8.GlobalScale); - _communicator.ChangedItemHover.Invoke(data); + _communicator.ChangedItemHover.Invoke(new ChangedItemHover.Arguments(data)); } /// Draw the model information, right-justified. diff --git a/Penumbra/UI/CollectionTab/CollectionSelector.cs b/Penumbra/UI/CollectionTab/CollectionSelector.cs index 79254090..c5709dd6 100644 --- a/Penumbra/UI/CollectionTab/CollectionSelector.cs +++ b/Penumbra/UI/CollectionTab/CollectionSelector.cs @@ -34,9 +34,9 @@ public sealed class CollectionSelector : ItemSelector, IDisposabl _communicator.CollectionChange.Subscribe(OnCollectionChange, CollectionChange.Priority.CollectionSelector); // Set items. - OnCollectionChange(CollectionType.Inactive, null, null, string.Empty); + OnCollectionChange(new CollectionChange.Arguments(CollectionType.Inactive, null, null, string.Empty)); // Set selection. - OnCollectionChange(CollectionType.Current, null, _active.Current, string.Empty); + OnCollectionChange(new CollectionChange.Arguments(CollectionType.Current, null, _active.Current, string.Empty)); } protected override bool OnDelete(int idx) @@ -85,7 +85,7 @@ public sealed class CollectionSelector : ItemSelector, IDisposabl if (source) { _dragging = Items[idx]; - ImGui.SetDragDropPayload(PayloadString, null, 0); + ImGui.SetDragDropPayload(PayloadString, null); ImGui.TextUnformatted($"Assigning {Name(_dragging)} to..."); } @@ -123,14 +123,14 @@ public sealed class CollectionSelector : ItemSelector, IDisposabl SetCurrent(_active.Current); } - private void OnCollectionChange(CollectionType type, ModCollection? old, ModCollection? @new, string _3) + private void OnCollectionChange(in CollectionChange.Arguments arguments) { - switch (type) + switch (arguments.Type) { case CollectionType.Temporary: return; case CollectionType.Current: - if (@new != null) - SetCurrent(@new); + if (arguments.NewCollection is not null) + SetCurrent(arguments.NewCollection); SetFilterDirty(); return; case CollectionType.Inactive: diff --git a/Penumbra/UI/CollectionTab/IndividualAssignmentUi.cs b/Penumbra/UI/CollectionTab/IndividualAssignmentUi.cs index b7f6ce3f..e0b42b35 100644 --- a/Penumbra/UI/CollectionTab/IndividualAssignmentUi.cs +++ b/Penumbra/UI/CollectionTab/IndividualAssignmentUi.cs @@ -135,9 +135,9 @@ public class IndividualAssignmentUi : IDisposable _ready = true; } - private void UpdateIdentifiers(CollectionType type, ModCollection? _1, ModCollection? _2, string _3) + private void UpdateIdentifiers(in CollectionChange.Arguments arguments) { - if (type == CollectionType.Individual) + if (arguments.Type is CollectionType.Individual) UpdateIdentifiersInternal(); } diff --git a/Penumbra/UI/FileDialogService.cs b/Penumbra/UI/FileDialogService.cs index b6d7dcdd..7ae7b56c 100644 --- a/Penumbra/UI/FileDialogService.cs +++ b/Penumbra/UI/FileDialogService.cs @@ -140,18 +140,18 @@ public class FileDialogService : IDisposable, IUiService } /// Update the Root Directory link on changes. - private void OnModDirectoryChange(string directory, bool valid) + private void OnModDirectoryChange(in ModDirectoryChanged.Arguments arguments) { var idx = _manager.CustomSideBarItems.IndexOf(t => t.Name == "Root Directory"); if (idx >= 0) _manager.CustomSideBarItems.RemoveAt(idx); - if (!valid) + if (!arguments.Valid) return; if (idx >= 0) - _manager.CustomSideBarItems.Insert(idx, ("Root Directory", directory, FontAwesomeIcon.Gamepad, 0)); + _manager.CustomSideBarItems.Insert(idx, ("Root Directory", arguments.Directory, FontAwesomeIcon.Gamepad, 0)); else - _manager.CustomSideBarItems.Add(("Root Directory", directory, FontAwesomeIcon.Gamepad, 0)); + _manager.CustomSideBarItems.Add(("Root Directory", arguments.Directory, FontAwesomeIcon.Gamepad, 0)); } } diff --git a/Penumbra/UI/ModsTab/ModFileSystemSelector.cs b/Penumbra/UI/ModsTab/ModFileSystemSelector.cs index 84c71b20..c8f67539 100644 --- a/Penumbra/UI/ModsTab/ModFileSystemSelector.cs +++ b/Penumbra/UI/ModsTab/ModFileSystemSelector.cs @@ -10,7 +10,6 @@ using OtterGui.FileSystem.Selector; using OtterGui.Raii; using OtterGui.Text; using OtterGui.Text.Widget; -using Penumbra.Api.Enums; using Penumbra.Collections; using Penumbra.Collections.Manager; using Penumbra.Communication; @@ -23,7 +22,7 @@ using MessageService = Penumbra.Services.MessageService; namespace Penumbra.UI.ModsTab; -public sealed class ModFileSystemSelector : FileSystemSelector, Luna.IUiService +public sealed class ModFileSystemSelector : FileSystemSelector, IUiService { private readonly CommunicatorService _communicator; private readonly Configuration _config; @@ -507,13 +506,13 @@ public sealed class ModFileSystemSelector : FileSystemSelector Apply the string filters. - private bool ApplyStringFilters(ModFileSystem.Leaf leaf, Mod mod) + private bool ApplyStringFilters(ModFileSystem.Leaf leaf, Mod _) => !_filter.IsVisible(leaf); /// Only get the text color for a mod if no filters are set. diff --git a/Penumbra/UI/ModsTab/ModPanel.cs b/Penumbra/UI/ModsTab/ModPanel.cs index 4681b879..fe594d4b 100644 --- a/Penumbra/UI/ModsTab/ModPanel.cs +++ b/Penumbra/UI/ModsTab/ModPanel.cs @@ -25,7 +25,7 @@ public class ModPanel : IDisposable, Luna.IUiService _multiModPanel = multiModPanel; _header = new ModPanelHeader(pi, communicator); _selection.Subscribe(OnSelectionChange, ModSelection.Priority.ModPanel); - OnSelectionChange(null, _selection.Mod); + OnSelectionChange(new ModSelection.Arguments(null, _selection.Mod)); } public void Draw() @@ -59,10 +59,10 @@ public class ModPanel : IDisposable, Luna.IUiService private bool _valid; private Mod _mod = null!; - private void OnSelectionChange(Mod? old, Mod? mod) + private void OnSelectionChange(in ModSelection.Arguments arguments) { _resetCursor = true; - if (mod == null || _selection.Mod == null) + if (arguments.NewSelection is null || _selection.Mod is null) { _editWindow.IsOpen = false; _valid = false; @@ -70,9 +70,9 @@ public class ModPanel : IDisposable, Luna.IUiService else { if (_editWindow.IsOpen) - _editWindow.ChangeMod(mod); + _editWindow.ChangeMod(arguments.NewSelection); _valid = true; - _mod = mod; + _mod = arguments.NewSelection; _header.ChangeMod(_mod); _tabs.Settings.Reset(); _tabs.Edit.Reset(); diff --git a/Penumbra/UI/ModsTab/ModPanelHeader.cs b/Penumbra/UI/ModsTab/ModPanelHeader.cs index b42ac680..f979aea8 100644 --- a/Penumbra/UI/ModsTab/ModPanelHeader.cs +++ b/Penumbra/UI/ModsTab/ModPanelHeader.cs @@ -47,7 +47,7 @@ public class ModPanelHeader : IDisposable DrawSecondRow(offset); } - _communicator.PreSettingsTabBarDraw.Invoke(_mod.Identifier, ImGui.GetItemRectSize().X, _nameWidth); + _communicator.PreSettingsTabBarDraw.Invoke(new PreSettingsTabBarDraw.Arguments(_mod, ImGui.GetItemRectSize().X, _nameWidth)); _lastPreSettingsHeight = ImGui.GetCursorPosY(); } @@ -260,10 +260,10 @@ public class ModPanelHeader : IDisposable } /// Just update the data when any relevant field changes. - private void OnModDataChange(ModDataChangeType changeType, Mod mod, string? _2) + private void OnModDataChange(in ModDataChanged.Arguments arguments) { const ModDataChangeType relevantChanges = ModDataChangeType.Author | ModDataChangeType.Name | ModDataChangeType.Website | ModDataChangeType.Version; - _dirty = (changeType & relevantChanges) != 0; + _dirty = (arguments.Type & relevantChanges) is not 0; } } diff --git a/Penumbra/UI/ModsTab/ModPanelSettingsTab.cs b/Penumbra/UI/ModsTab/ModPanelSettingsTab.cs index d3561ae2..20ac87f0 100644 --- a/Penumbra/UI/ModsTab/ModPanelSettingsTab.cs +++ b/Penumbra/UI/ModsTab/ModPanelSettingsTab.cs @@ -4,6 +4,7 @@ using OtterGui.Text; using OtterGui.Widgets; using Penumbra.UI.Classes; using Penumbra.Collections.Manager; +using Penumbra.Communication; using Penumbra.Mods; using Penumbra.Mods.Manager; using Penumbra.Services; @@ -51,7 +52,7 @@ public class ModPanelSettingsTab( DrawTemporaryWarning(); DrawInheritedWarning(); ImGui.Dummy(Vector2.Zero); - communicator.PreSettingsPanelDraw.Invoke(selection.Mod!.Identifier); + communicator.PreSettingsPanelDraw.Invoke(new PreSettingsPanelDraw.Arguments(selection.Mod!)); DrawEnabledInput(); tutorial.OpenTutorial(BasicTutorialSteps.EnablingMods); ImGui.SameLine(); @@ -60,11 +61,11 @@ public class ModPanelSettingsTab( DrawRemoveSettings(); ImGui.TableNextColumn(); - communicator.PostEnabledDraw.Invoke(selection.Mod!.Identifier); + communicator.PostEnabledDraw.Invoke(new PostEnabledDraw.Arguments(selection.Mod!)); modGroupDrawer.Draw(selection.Mod!, selection.Settings, selection.TemporarySettings); UiHelpers.DefaultLineSpace(); - communicator.PostSettingsPanelDraw.Invoke(selection.Mod!.Identifier); + communicator.PostSettingsPanelDraw.Invoke(new PostSettingsPanelDraw.Arguments(selection.Mod!)); } /// Draw a big tinted bar if the current setting is temporary. @@ -195,7 +196,7 @@ public class ModPanelSettingsTab( { (true, false) => ImUtf8.ButtonEx("Inherit Settings"u8, "Remove current settings from this collection so that it can inherit them.\n"u8 - + "If no inherited collection has settings for this mod, it will be disabled."u8, default, false), + + "If no inherited collection has settings for this mod, it will be disabled."u8), (false, false) => ImUtf8.ButtonEx("Inherit Settings"u8, $"Remove current settings from this collection so that it can inherit them.\nHold {config.DeleteModModifier} to inherit.", default, true), diff --git a/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs b/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs index 642f6aef..e21a8179 100644 --- a/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs +++ b/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs @@ -295,16 +295,16 @@ public sealed class ResourceWatcher : IDisposable, ITab, Luna.IUiService _newRecords.Enqueue(record); } - private unsafe void OnResourceDestroyed(ResourceHandle* resource) + private unsafe void OnResourceDestroyed(in ResourceHandleDestructor.Arguments arguments) { - if (_ephemeral.EnableResourceLogging && FilterMatch(resource->FileName(), out var match)) + if (_ephemeral.EnableResourceLogging && FilterMatch(arguments.ResourceHandle->FileName(), out var match)) Penumbra.Log.Information( - $"[ResourceLoader] [DEST] [{resource->FileType}] Destroyed {match} at 0x{(ulong)resource:X}."); + $"[ResourceLoader] [DEST] [{arguments.ResourceHandle->FileType}] Destroyed {match} at 0x{(ulong)arguments.ResourceHandle:X}."); if (!_ephemeral.EnableResourceWatcher) return; - var record = Record.CreateDestruction(resource); + var record = Record.CreateDestruction(arguments.ResourceHandle); if (!_ephemeral.OnlyAddMatchingResources || _table.WouldBeVisible(record)) _newRecords.Enqueue(record); } diff --git a/Penumbra/UI/Tabs/ChangedItemsTab.cs b/Penumbra/UI/Tabs/ChangedItemsTab.cs index 20ad1b55..9813846a 100644 --- a/Penumbra/UI/Tabs/ChangedItemsTab.cs +++ b/Penumbra/UI/Tabs/ChangedItemsTab.cs @@ -6,6 +6,7 @@ using OtterGui.Text; using OtterGui.Widgets; using Penumbra.Api.Enums; using Penumbra.Collections.Manager; +using Penumbra.Communication; using Penumbra.GameData.Data; using Penumbra.Mods; using Penumbra.Mods.Editor; @@ -103,7 +104,7 @@ public class ChangedItemsTab( if (ImUtf8.Selectable(first.Name.Text, false, ImGuiSelectableFlags.None, _buttonSize with { X = 0 }) && ImGui.GetIO().KeyCtrl && first is Mod mod) - communicator.SelectTab.Invoke(TabType.Mods, mod); + communicator.SelectTab.Invoke(new SelectTab.Arguments(TabType.Mods, mod)); if (!ImGui.IsItemHovered()) return; diff --git a/Penumbra/UI/Tabs/ConfigTabBar.cs b/Penumbra/UI/Tabs/ConfigTabBar.cs index 416f7584..52a95940 100644 --- a/Penumbra/UI/Tabs/ConfigTabBar.cs +++ b/Penumbra/UI/Tabs/ConfigTabBar.cs @@ -1,7 +1,7 @@ using Dalamud.Bindings.ImGui; using OtterGui.Widgets; using Penumbra.Api.Enums; -using Penumbra.Mods; +using Penumbra.Communication; using Penumbra.Services; using Penumbra.UI.Tabs.Debug; using Watcher = Penumbra.UI.ResourceWatcher.ResourceWatcher; @@ -104,10 +104,10 @@ public class ConfigTabBar : IDisposable, Luna.IUiService return TabType.None; } - private void OnSelectTab(TabType tab, Mod? mod) + private void OnSelectTab(in SelectTab.Arguments arguments) { - SelectTab = tab; - if (mod != null) - Mods.SelectMod = mod; + SelectTab = arguments.Tab; + if (arguments.Mod is not null) + Mods.SelectMod = arguments.Mod; } }