diff --git a/MareSynchronos/FileCache/TransientResourceManager.cs b/MareSynchronos/FileCache/TransientResourceManager.cs index 8e30341..00586a2 100644 --- a/MareSynchronos/FileCache/TransientResourceManager.cs +++ b/MareSynchronos/FileCache/TransientResourceManager.cs @@ -35,13 +35,15 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase DalamudUtil_ClassJobChanged(); } }); - Mediator.Subscribe(this, (msg) => + Mediator.Subscribe(this, (msg) => { - _playerRelatedPointers.Add(msg.Handler); + if (!msg.OwnedObject) return; + _playerRelatedPointers.Add(msg.GameObjectHandler); }); - Mediator.Subscribe(this, (msg) => + Mediator.Subscribe(this, (msg) => { - _playerRelatedPointers.Remove(msg.Handler); + if (!msg.OwnedObject) return; + _playerRelatedPointers.Remove(msg.GameObjectHandler); }); } diff --git a/MareSynchronos/Interop/Ipc/IpcProvider.cs b/MareSynchronos/Interop/Ipc/IpcProvider.cs index 2f95dc3..0483d62 100644 --- a/MareSynchronos/Interop/Ipc/IpcProvider.cs +++ b/MareSynchronos/Interop/Ipc/IpcProvider.cs @@ -2,13 +2,15 @@ using Dalamud.Plugin; using Dalamud.Plugin.Ipc; using MareSynchronos.PlayerData.Export; +using MareSynchronos.PlayerData.Handlers; using MareSynchronos.Services; +using MareSynchronos.Services.Mediator; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace MareSynchronos.Interop.Ipc; -public class IpcProvider : IHostedService +public class IpcProvider : IHostedService, IMediatorSubscriber { private readonly ILogger _logger; private readonly DalamudPluginInterface _pi; @@ -16,14 +18,31 @@ public class IpcProvider : IHostedService private readonly DalamudUtilService _dalamudUtil; private ICallGateProvider? _loadFileProvider; private ICallGateProvider>? _loadFileAsyncProvider; + private ICallGateProvider>? _handledGameAddresses; + private readonly List _activeGameObjectHandlers = []; + + public MareMediator Mediator { get; init; } public IpcProvider(ILogger logger, DalamudPluginInterface pi, - MareCharaFileManager mareCharaFileManager, DalamudUtilService dalamudUtil) + MareCharaFileManager mareCharaFileManager, DalamudUtilService dalamudUtil, + MareMediator mareMediator) { _logger = logger; _pi = pi; _mareCharaFileManager = mareCharaFileManager; _dalamudUtil = dalamudUtil; + Mediator = mareMediator; + + Mediator.Subscribe(this, (msg) => + { + if (msg.OwnedObject) return; + _activeGameObjectHandlers.Add(msg.GameObjectHandler); + }); + Mediator.Subscribe(this, (msg) => + { + if (msg.OwnedObject) return; + _activeGameObjectHandlers.Remove(msg.GameObjectHandler); + }); } public Task StartAsync(CancellationToken cancellationToken) @@ -33,6 +52,8 @@ public class IpcProvider : IHostedService _loadFileProvider.RegisterFunc(LoadMcdf); _loadFileAsyncProvider = _pi.GetIpcProvider>("MareSynchronos.LoadMcdfAsync"); _loadFileAsyncProvider.RegisterFunc(LoadMcdfAsync); + _handledGameAddresses = _pi.GetIpcProvider>("MareSynchronos.GetHandledAddresses"); + _handledGameAddresses.RegisterFunc(GetHandledAddresses); _logger.LogInformation("Started IpcProviderService"); return Task.CompletedTask; } @@ -42,6 +63,8 @@ public class IpcProvider : IHostedService _logger.LogDebug("Stopping IpcProvider Service"); _loadFileProvider?.UnregisterFunc(); _loadFileAsyncProvider?.UnregisterFunc(); + _handledGameAddresses?.UnregisterFunc(); + Mediator.UnsubscribeAll(this); return Task.CompletedTask; } @@ -77,4 +100,9 @@ public class IpcProvider : IHostedService _mareCharaFileManager.ClearMareCharaFile(); } } + + private List GetHandledAddresses() + { + return _activeGameObjectHandlers.Where(g => g.Address != nint.Zero).Select(g => g.Address).Distinct().ToList(); + } } diff --git a/MareSynchronos/PlayerData/Handlers/GameObjectHandler.cs b/MareSynchronos/PlayerData/Handlers/GameObjectHandler.cs index 64a4e1a..8015308 100644 --- a/MareSynchronos/PlayerData/Handlers/GameObjectHandler.cs +++ b/MareSynchronos/PlayerData/Handlers/GameObjectHandler.cs @@ -26,7 +26,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase private CancellationTokenSource _zoningCts = new(); public GameObjectHandler(ILogger logger, PerformanceCollectorService performanceCollector, - MareMediator mediator, DalamudUtilService dalamudUtil, ObjectKind objectKind, Func getAddress, bool watchedObject = true) : base(logger, mediator) + MareMediator mediator, DalamudUtilService dalamudUtil, ObjectKind objectKind, Func getAddress, bool ownedObject = true) : base(logger, mediator) { _performanceCollector = performanceCollector; ObjectKind = objectKind; @@ -36,10 +36,10 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase _dalamudUtil.EnsureIsOnFramework(); return getAddress.Invoke(); }; - _isOwnedObject = watchedObject; + _isOwnedObject = ownedObject; Name = string.Empty; - if (watchedObject) + if (ownedObject) { Mediator.Subscribe(this, (msg) => { @@ -49,7 +49,6 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase Mediator.Publish(new CreateCacheForObjectMessage(this)); } }); - Mediator.Publish(new AddWatchedGameObjectHandler(this)); } Mediator.Subscribe(this, (_) => FrameworkUpdate()); @@ -87,6 +86,8 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase } }); + Mediator.Publish(new GameObjectHandlerCreatedMessage(this, _isOwnedObject)); + _dalamudUtil.RunOnFrameworkThread(CheckAndUpdateObject).GetAwaiter().GetResult(); } @@ -174,8 +175,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase { base.Dispose(disposing); - if (_isOwnedObject) - Mediator.Publish(new RemoveWatchedGameObjectHandler(this)); + Mediator.Publish(new GameObjectHandlerDestroyedMessage(this, _isOwnedObject)); } private unsafe void CheckAndUpdateObject() diff --git a/MareSynchronos/Plugin.cs b/MareSynchronos/Plugin.cs index f49d635..12faadb 100644 --- a/MareSynchronos/Plugin.cs +++ b/MareSynchronos/Plugin.cs @@ -78,7 +78,8 @@ public sealed class Plugin : IDalamudPlugin collection.AddSingleton(); collection.AddSingleton((s) => new IpcProvider(s.GetRequiredService>(), pluginInterface, - s.GetRequiredService(), s.GetRequiredService())); + s.GetRequiredService(), s.GetRequiredService(), + s.GetRequiredService())); collection.AddSingleton(); collection.AddSingleton((s) => new EventAggregator(pluginInterface.ConfigDirectory.FullName, s.GetRequiredService>(), s.GetRequiredService())); diff --git a/MareSynchronos/Services/Mediator/Messages.cs b/MareSynchronos/Services/Mediator/Messages.cs index 4e28d4c..69d34e0 100644 --- a/MareSynchronos/Services/Mediator/Messages.cs +++ b/MareSynchronos/Services/Mediator/Messages.cs @@ -45,8 +45,6 @@ public record HonorificReadyMessage : MessageBase; public record PlayerChangedMessage(CharacterData Data) : MessageBase; public record CharacterChangedMessage(GameObjectHandler GameObjectHandler) : MessageBase; public record TransientResourceChangedMessage(IntPtr Address) : MessageBase; -public record AddWatchedGameObjectHandler(GameObjectHandler Handler) : MessageBase; -public record RemoveWatchedGameObjectHandler(GameObjectHandler Handler) : MessageBase; public record HaltScanMessage(string Source) : MessageBase; public record ResumeScanMessage(string Source) : MessageBase; public record NotificationMessage @@ -86,5 +84,7 @@ public record CombatOrPerformanceEndMessage : MessageBase; public record EventMessage(Event Event) : MessageBase; public record PenumbraDirectoryChangedMessage(string? ModDirectory) : MessageBase; public record PenumbraRedrawCharacterMessage(Character Character) : SameThreadMessage; +public record GameObjectHandlerCreatedMessage(GameObjectHandler GameObjectHandler, bool OwnedObject) : MessageBase; +public record GameObjectHandlerDestroyedMessage(GameObjectHandler GameObjectHandler, bool OwnedObject) : MessageBase; #pragma warning restore S2094 #pragma warning restore MA0048 // File name must match type name \ No newline at end of file