From ae443f1ec4e80674dfecda113573cfe6f8d6f90c Mon Sep 17 00:00:00 2001 From: Stanley Dimant Date: Mon, 20 Feb 2023 08:59:27 +0100 Subject: [PATCH] potentially fix zoning issues --- MareSynchronos/Managers/CachedPlayer.cs | 10 ++--- MareSynchronos/Managers/IpcManager.cs | 10 ++--- MareSynchronos/Mediator/MareMediator.cs | 57 +++++++++++++++++-------- MareSynchronos/Utils/DalamudUtil.cs | 1 + 4 files changed, 50 insertions(+), 28 deletions(-) diff --git a/MareSynchronos/Managers/CachedPlayer.cs b/MareSynchronos/Managers/CachedPlayer.cs index f8251d6..0dbdbf4 100644 --- a/MareSynchronos/Managers/CachedPlayer.cs +++ b/MareSynchronos/Managers/CachedPlayer.cs @@ -230,7 +230,7 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable _currentOtherChara?.Dispose(); _currentOtherChara = null; - if (ptr != IntPtr.Zero) + if (ptr != IntPtr.Zero && !_dalamudUtil.IsZoning) { foreach (var item in _cachedData.FileReplacements) { @@ -462,7 +462,7 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable _logger.LogDebug("[{applicationId}] Restoring Customization for {alias}/{name}: {data}", applicationId, OnlineUser.User.AliasOrUID, name, _originalGlamourerData); await _ipcManager.GlamourerApplyOnlyCustomization(_logger, tempHandler, _originalGlamourerData, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false); _logger.LogDebug("[{applicationId}] Restoring Equipment for {alias}/{name}: {data}", applicationId, OnlineUser.User.AliasOrUID, name, _lastGlamourerData); - await _ipcManager.GlamourerApplyOnlyEquipment(_logger, tempHandler, _lastGlamourerData, applicationId, cancelToken.Token, fireAndForget: true).ConfigureAwait(false); + await _ipcManager.GlamourerApplyOnlyEquipment(_logger, tempHandler, _lastGlamourerData, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false); _logger.LogDebug("[{applicationId}] Restoring Heels for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name); _ipcManager.HeelsRestoreOffsetForPlayer(address); _logger.LogDebug("[{applicationId}] Restoring C+ for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name); @@ -475,7 +475,7 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable if (minionOrMount != IntPtr.Zero) { using GameObjectHandler tempHandler = _gameObjectHandlerFactory.Create(ObjectKind.MinionOrMount, () => minionOrMount, isWatched: false); - await _ipcManager.PenumbraRedraw(_logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: true).ConfigureAwait(false); + await _ipcManager.PenumbraRedraw(_logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false); } } else if (objectKind == ObjectKind.Pet) @@ -484,7 +484,7 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable if (pet != IntPtr.Zero) { using GameObjectHandler tempHandler = _gameObjectHandlerFactory.Create(ObjectKind.Pet, () => pet, isWatched: false); - await _ipcManager.PenumbraRedraw(_logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: true).ConfigureAwait(false); + await _ipcManager.PenumbraRedraw(_logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false); } } else if (objectKind == ObjectKind.Companion) @@ -493,7 +493,7 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable if (companion != IntPtr.Zero) { using GameObjectHandler tempHandler = _gameObjectHandlerFactory.Create(ObjectKind.Pet, () => companion, isWatched: false); - await _ipcManager.PenumbraRedraw(_logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: true).ConfigureAwait(false); + await _ipcManager.PenumbraRedraw(_logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false); } } } diff --git a/MareSynchronos/Managers/IpcManager.cs b/MareSynchronos/Managers/IpcManager.cs index 9d00f78..8d1e579 100644 --- a/MareSynchronos/Managers/IpcManager.cs +++ b/MareSynchronos/Managers/IpcManager.cs @@ -424,7 +424,7 @@ public class IpcManager : MediatorSubscriberBase, IDisposable public async Task GlamourerApplyAll(ILogger logger, GameObjectHandler handler, string? customization, Guid applicationId, CancellationToken token, bool fireAndForget = false) { - if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization)) return; + if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization) || _dalamudUtil.IsZoning) return; var gameObj = _dalamudUtil.CreateGameObject(handler.Address); if (gameObj is Character c) { @@ -434,7 +434,7 @@ public class IpcManager : MediatorSubscriberBase, IDisposable public async Task GlamourerApplyOnlyEquipment(ILogger logger, GameObjectHandler handler, string customization, Guid applicationId, CancellationToken token, bool fireAndForget = false) { - if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization)) return; + if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization) || _dalamudUtil.IsZoning) return; var gameObj = _dalamudUtil.CreateGameObject(handler.Address); if (gameObj is Character c) { @@ -444,7 +444,7 @@ public class IpcManager : MediatorSubscriberBase, IDisposable public async Task GlamourerApplyOnlyCustomization(ILogger logger, GameObjectHandler handler, string customization, Guid applicationId, CancellationToken token, bool fireAndForget = false) { - if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization)) return; + if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization) || _dalamudUtil.IsZoning) return; var gameObj = _dalamudUtil.CreateGameObject(handler.Address); if (gameObj is Character c) { @@ -477,7 +477,7 @@ public class IpcManager : MediatorSubscriberBase, IDisposable public void GlamourerRevertCharacterCustomization(GameObject character) { - if (!CheckGlamourerApi()) return; + if (!CheckGlamourerApi() || _dalamudUtil.IsZoning) return; ActionQueue.Enqueue(() => _glamourerRevertCustomization!.InvokeAction(character)); } @@ -497,7 +497,7 @@ public class IpcManager : MediatorSubscriberBase, IDisposable public async Task PenumbraRedraw(ILogger logger, GameObjectHandler handler, Guid applicationId, CancellationToken token, bool fireAndForget = false) { - if (!CheckPenumbraApi()) return; + if (!CheckPenumbraApi() || _dalamudUtil.IsZoning) return; var gameObj = _dalamudUtil.CreateGameObject(handler.Address); if (gameObj is Character c) { diff --git a/MareSynchronos/Mediator/MareMediator.cs b/MareSynchronos/Mediator/MareMediator.cs index 147a7b7..15a093d 100644 --- a/MareSynchronos/Mediator/MareMediator.cs +++ b/MareSynchronos/Mediator/MareMediator.cs @@ -1,17 +1,27 @@ using MareSynchronos.Utils; using Microsoft.Extensions.Logging; -using System.Diagnostics; using System.Text; namespace MareSynchronos.Mediator; public class MareMediator : IDisposable { - private record MediatorSubscriber(IMediatorSubscriber Subscriber, Action Action); + private class SubscriberAction + { + public IMediatorSubscriber Subscriber { get; } + public Action Action { get; } - private readonly Dictionary> _subscriberDict = new(); + public SubscriberAction(IMediatorSubscriber subscriber, Action action) + { + Subscriber = subscriber; + Action = action; + } + } + + private readonly Dictionary> _subscriberDict = new(); private readonly ILogger _logger; private readonly PerformanceCollector _performanceCollector; + private readonly object _addRemoveLock = new(); public MareMediator(ILogger logger, PerformanceCollector performanceCollector) { @@ -21,30 +31,35 @@ public class MareMediator : IDisposable public void Subscribe(IMediatorSubscriber subscriber, Action action) where T : IMessage { - _subscriberDict.TryAdd(typeof(T), new HashSet()); - - if (!_subscriberDict[typeof(T)].Add(new(subscriber, action))) + lock (_addRemoveLock) { - throw new InvalidOperationException("Already subscribed"); + _subscriberDict.TryAdd(typeof(T), new HashSet()); + + if (!_subscriberDict[typeof(T)].Add(new(subscriber, action))) + { + throw new InvalidOperationException("Already subscribed"); + } } } public void Unsubscribe(IMediatorSubscriber subscriber) where T : IMessage { - if (_subscriberDict.TryGetValue(typeof(T), out var subscribers)) + lock (_addRemoveLock) { - subscribers.RemoveWhere(p => p.Subscriber == subscriber); + if (_subscriberDict.ContainsKey(typeof(T))) + { + _subscriberDict[typeof(T)].RemoveWhere(p => p.Subscriber == subscriber); + } } } public void Publish(IMessage message) { - if (_subscriberDict.TryGetValue(message.GetType(), out var subscribers)) + if (_subscriberDict.TryGetValue(message.GetType(), out HashSet? subscribers) && subscribers != null && subscribers.Any()) { - Stopwatch globalStopwatch = Stopwatch.StartNew(); _performanceCollector.LogPerformance(this, $"Publish>{message.GetType().Name}", () => { - foreach (var subscriber in subscribers.Where(s => s.Subscriber != null).ToList()) + foreach (SubscriberAction subscriber in subscribers?.Where(s => s.Subscriber != null).ToHashSet() ?? new HashSet()) { try { @@ -52,8 +67,11 @@ public class MareMediator : IDisposable } catch (Exception ex) { - _logger.LogCritical(ex, "Error executing {type} for subscriber {subscriber}, removing from Mediator", message.GetType(), subscriber); - _subscriberDict[message.GetType()].RemoveWhere(s => s == subscriber); + lock (_addRemoveLock) + { + var removed = _subscriberDict[message.GetType()].RemoveWhere(s => s == subscriber); + _logger.LogCritical(ex, "Error executing {type} for subscriber {subscriber}, removed from Mediator: {removeCount}", message.GetType(), subscriber, removed); + } } } }); @@ -62,11 +80,14 @@ public class MareMediator : IDisposable internal void UnsubscribeAll(IMediatorSubscriber subscriber) { - foreach (var kvp in _subscriberDict.ToList()) + lock (_subscriberDict) { - var unSubbed = _subscriberDict[kvp.Key].RemoveWhere(p => p.Subscriber == subscriber); - if (unSubbed > 0) - _logger.LogDebug("{sub} unsubscribed from {msg}", subscriber, kvp.Key.Name); + foreach (KeyValuePair> kvp in _subscriberDict.ToList()) + { + int unSubbed = _subscriberDict[kvp.Key]?.RemoveWhere(p => p.Subscriber == subscriber) ?? 0; + if (unSubbed > 0) + _logger.LogDebug("{sub} unsubscribed from {msg}", subscriber, kvp.Key.Name); + } } } diff --git a/MareSynchronos/Utils/DalamudUtil.cs b/MareSynchronos/Utils/DalamudUtil.cs index df8228d..8a7b119 100644 --- a/MareSynchronos/Utils/DalamudUtil.cs +++ b/MareSynchronos/Utils/DalamudUtil.cs @@ -26,6 +26,7 @@ public class DalamudUtil : IDisposable private DateTime _delayedFrameworkUpdateCheck = DateTime.Now; private bool _sentBetweenAreas = false; public bool IsInCutscene { get; private set; } = false; + public bool IsZoning => _condition[ConditionFlag.BetweenAreas] || _condition[ConditionFlag.BetweenAreas51]; public bool IsInGpose { get; private set; } = false; public unsafe bool IsGameObjectPresent(IntPtr key)