fully switch to mediator from events

This commit is contained in:
rootdarkarchon
2023-01-31 01:35:11 +01:00
parent 5e7beb8518
commit 41465c2d49
24 changed files with 166 additions and 239 deletions

View File

@@ -1,3 +0,0 @@
namespace MareSynchronos.Delegates;
public delegate void CharacterDataDelegate(API.Data.CharacterData characterCache);

View File

@@ -1,3 +0,0 @@
namespace MareSynchronos.Delegates;
public delegate void DrawObjectDelegate(IntPtr address, int objTblIdx);

View File

@@ -1,3 +0,0 @@
namespace MareSynchronos.Delegates;
public delegate void FloatDelegate(float change);

View File

@@ -1,3 +0,0 @@
namespace MareSynchronos.Delegates;
public delegate void PenumbraFileResourceDelegate(IntPtr drawObject, string gamePath, string filePath);

View File

@@ -1,3 +0,0 @@
namespace MareSynchronos.Delegates;
public delegate void StringDelegate(string str);

View File

@@ -1,3 +0,0 @@
namespace MareSynchronos.Delegates;
public delegate void VoidDelegate();

View File

@@ -1,6 +1,7 @@
using MareSynchronos.API.Dto.User;
using MareSynchronos.FileCache;
using MareSynchronos.Managers;
using MareSynchronos.Mediator;
using MareSynchronos.Utils;
using MareSynchronos.WebAPI;
@@ -11,16 +12,18 @@ public class CachedPlayerFactory
private readonly IpcManager _ipcManager;
private readonly DalamudUtil _dalamudUtil;
private readonly FileCacheManager _fileCacheManager;
private readonly MareMediator _mediator;
public CachedPlayerFactory(IpcManager ipcManager, DalamudUtil dalamudUtil, FileCacheManager fileCacheManager)
public CachedPlayerFactory(IpcManager ipcManager, DalamudUtil dalamudUtil, FileCacheManager fileCacheManager, MareMediator mediator)
{
_ipcManager = ipcManager;
_dalamudUtil = dalamudUtil;
_fileCacheManager = fileCacheManager;
_mediator = mediator;
}
public CachedPlayer Create(OnlineUserIdentDto dto, ApiController apiController)
{
return new CachedPlayer(dto, _ipcManager, apiController, _dalamudUtil, _fileCacheManager);
return new CachedPlayer(dto, _ipcManager, apiController, _dalamudUtil, _fileCacheManager, _mediator);
}
}

View File

@@ -3,7 +3,6 @@ using MareSynchronos.Managers;
using MareSynchronos.MareConfiguration;
using MareSynchronos.Mediator;
using MareSynchronos.Utils;
using MareSynchronos.WebAPI;
namespace MareSynchronos.FileCache;
@@ -12,51 +11,26 @@ public class PeriodicFileScanner : IDisposable
private readonly IpcManager _ipcManager;
private readonly ConfigurationService _configService;
private readonly FileCacheManager _fileDbManager;
private readonly ApiController _apiController;
private readonly DalamudUtil _dalamudUtil;
private readonly MareMediator _mediator;
private CancellationTokenSource? _scanCancellationTokenSource;
private Task? _fileScannerTask = null;
public ConcurrentDictionary<string, int> haltScanLocks = new(StringComparer.Ordinal);
public PeriodicFileScanner(IpcManager ipcManager, ConfigurationService configService, FileCacheManager fileDbManager, ApiController apiController, DalamudUtil dalamudUtil, MareMediator mediator)
public PeriodicFileScanner(IpcManager ipcManager, ConfigurationService configService, FileCacheManager fileDbManager, MareMediator mediator)
{
Logger.Verbose("Creating " + nameof(PeriodicFileScanner));
_ipcManager = ipcManager;
_configService = configService;
_fileDbManager = fileDbManager;
_apiController = apiController;
_dalamudUtil = dalamudUtil;
_mediator = mediator;
_ipcManager.PenumbraInitialized += StartScan;
_apiController.DownloadStarted += ApiHaltScan;
_apiController.DownloadFinished += ApiResumeScan;
_mediator.Subscribe<ZoneSwitchStartMessage>(this, (_) => ZoneSwitchHaltScan());
_mediator.Subscribe<ZoneSwitchEndMessage>(this, (_) => ZoneSwitchResumeScan());
_mediator.Subscribe<PenumbraInitializedMessage>(this, (_) => StartScan());
_mediator.Subscribe<HaltScanMessage>(this, (msg) => HaltScan(((HaltScanMessage)msg).Source));
_mediator.Subscribe<ResumeScanMessage>(this, (msg) => ResumeScan(((ResumeScanMessage)msg).Source));
_mediator.Subscribe<SwitchToMainUiMessage>(this, (_) => StartScan());
}
private void ApiHaltScan()
{
HaltScan("Download");
}
private void ApiResumeScan()
{
ResumeScan("Download");
}
private void ZoneSwitchHaltScan()
{
HaltScan("Zoning/Gpose");
}
private void ZoneSwitchResumeScan()
{
ResumeScan("Zoning/Gpose");
}
public void ResetLocks()
{
haltScanLocks.Clear();
@@ -106,9 +80,6 @@ public class PeriodicFileScanner : IDisposable
{
Logger.Verbose("Disposing " + nameof(PeriodicFileScanner));
_ipcManager.PenumbraInitialized -= StartScan;
_apiController.DownloadStarted -= ApiHaltScan;
_apiController.DownloadFinished -= ApiResumeScan;
_scanCancellationTokenSource?.Cancel();
}

View File

@@ -4,6 +4,7 @@ using MareSynchronos.API.Data;
using MareSynchronos.API.Data.Enum;
using MareSynchronos.API.Dto.User;
using MareSynchronos.FileCache;
using MareSynchronos.Mediator;
using MareSynchronos.Models;
using MareSynchronos.Utils;
using MareSynchronos.WebAPI;
@@ -16,6 +17,7 @@ public class CachedPlayer : IDisposable
private readonly DalamudUtil _dalamudUtil;
private readonly IpcManager _ipcManager;
private readonly FileCacheManager _fileDbManager;
private readonly MareMediator _mediator;
private API.Data.CharacterData _cachedData = new();
private PlayerRelatedObject? _currentCharacterEquipment;
private CancellationTokenSource? _downloadCancellationTokenSource = new();
@@ -27,13 +29,14 @@ public class CachedPlayer : IDisposable
private Task? _penumbraRedrawEventTask;
public CachedPlayer(OnlineUserIdentDto onlineUser, IpcManager ipcManager, ApiController apiController, DalamudUtil dalamudUtil, FileCacheManager fileDbManager)
public CachedPlayer(OnlineUserIdentDto onlineUser, IpcManager ipcManager, ApiController apiController, DalamudUtil dalamudUtil, FileCacheManager fileDbManager, MareMediator mediator)
{
OnlineUser = onlineUser;
_ipcManager = ipcManager;
_apiController = apiController;
_dalamudUtil = dalamudUtil;
_fileDbManager = fileDbManager;
_mediator = mediator;
}
public bool IsVisible
@@ -197,7 +200,6 @@ public class CachedPlayer : IDisposable
try
{
Logger.Verbose("Restoring state for " + PlayerName);
_ipcManager.PenumbraRedrawEvent -= IpcManagerOnPenumbraRedrawEvent;
_ipcManager.PenumbraRemoveTemporaryCollection(PlayerName);
_downloadCancellationTokenSource?.Cancel();
_downloadCancellationTokenSource?.Dispose();
@@ -216,6 +218,7 @@ public class CachedPlayer : IDisposable
}
finally
{
_mediator.UnsubscribeAll(this);
_cachedData = new();
var tempPlayerName = PlayerName;
PlayerName = string.Empty;
@@ -232,7 +235,7 @@ public class CachedPlayer : IDisposable
PlayerCharacter = character;
Logger.Debug("Initializing Player " + this);
_ipcManager.PenumbraRedrawEvent += IpcManagerOnPenumbraRedrawEvent;
_mediator.Subscribe<PenumbraRedrawMessage>(this, (msg) => IpcManagerOnPenumbraRedrawEvent(((PenumbraRedrawMessage)msg)));
_originalGlamourerData = _ipcManager.GlamourerGetCharacterCustomization(PlayerCharacter);
_currentCharacterEquipment = new PlayerRelatedObject(ObjectKind.Player, IntPtr.Zero, IntPtr.Zero,
() => _dalamudUtil.GetPlayerCharacterFromObjectTableByName(PlayerName)?.Address ?? IntPtr.Zero);
@@ -414,15 +417,15 @@ public class CachedPlayer : IDisposable
});
}
private void IpcManagerOnPenumbraRedrawEvent(IntPtr address, int idx)
private void IpcManagerOnPenumbraRedrawEvent(PenumbraRedrawMessage msg)
{
var player = _dalamudUtil.GetCharacterFromObjectTableByIndex(idx);
var player = _dalamudUtil.GetCharacterFromObjectTableByIndex(msg.ObjTblIdx);
if (player == null || !string.Equals(player.Name.ToString(), PlayerName, StringComparison.OrdinalIgnoreCase)) return;
if (!_penumbraRedrawEventTask?.IsCompleted ?? false) return;
_penumbraRedrawEventTask = Task.Run(() =>
{
PlayerCharacter = address;
PlayerCharacter = msg.Address;
var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(5));
_dalamudUtil.WaitWhileCharacterIsDrawing(PlayerName!, PlayerCharacter, 10000, cts.Token);

View File

@@ -7,7 +7,6 @@ using System.Collections.Concurrent;
using System.Text;
using Penumbra.Api.Enums;
using Penumbra.Api.Helpers;
using MareSynchronos.Delegates;
using MareSynchronos.Mediator;
namespace MareSynchronos.Managers;
@@ -68,6 +67,8 @@ public class IpcManager : IDisposable
{
Logger.Verbose("Creating " + nameof(IpcManager));
_mediator = mediator;
_penumbraInit = Penumbra.Api.Ipc.Initialized.Subscriber(pi, () => PenumbraInit());
_penumbraDispose = Penumbra.Api.Ipc.Disposed.Subscriber(pi, () => PenumbraDispose());
_penumbraResolvePlayer = Penumbra.Api.Ipc.ResolvePlayerPath.Subscriber(pi);
@@ -120,11 +121,10 @@ public class IpcManager : IDisposable
if (Initialized)
{
PenumbraInitialized?.Invoke();
_mediator.Publish(new PenumbraInitializedMessage());
}
_dalamudUtil = dalamudUtil;
_mediator = mediator;
_mediator.Subscribe<FrameworkUpdateMessage>(this, (_) => HandleActionQueue());
_mediator.Subscribe<GposeFrameworkUpdateMessage>(this, (_) => HandleGposeActionQueue());
_mediator.Subscribe<ZoneSwitchEndMessage>(this, (_) => ClearActionQueue());
@@ -147,7 +147,7 @@ public class IpcManager : IDisposable
private void PenumbraModSettingChangedHandler()
{
PenumbraModSettingChanged?.Invoke();
_mediator.Publish(new PenumbraModSettingChangedMessage());
}
private void ClearActionQueue()
@@ -162,7 +162,7 @@ public class IpcManager : IDisposable
{
if (ptr != IntPtr.Zero && string.Compare(arg1, arg2, ignoreCase: true, System.Globalization.CultureInfo.InvariantCulture) != 0)
{
PenumbraResourceLoadEvent?.Invoke(ptr, arg1, arg2);
_mediator.Publish(new PenumbraResourceLoadMessage(ptr, arg1, arg2));
}
});
}
@@ -177,15 +177,6 @@ public class IpcManager : IDisposable
}
}
public event VoidDelegate? PenumbraModSettingChanged;
public event VoidDelegate? PenumbraInitialized;
public event VoidDelegate? PenumbraDisposed;
public event DrawObjectDelegate? PenumbraRedrawEvent;
public event FloatDelegate? HeelsOffsetChangeEvent;
public event PenumbraFileResourceDelegate? PenumbraResourceLoadEvent;
public event StringDelegate? CustomizePlusScaleChange;
public event StringDelegate? PalettePlusPaletteChange;
public bool Initialized => CheckPenumbraApi();
public bool CheckGlamourerApi()
{
@@ -509,31 +500,31 @@ public class IpcManager : IDisposable
private void RedrawEvent(IntPtr objectAddress, int objectTableIndex)
{
PenumbraRedrawEvent?.Invoke(objectAddress, objectTableIndex);
_mediator.Publish(new PenumbraRedrawMessage(objectAddress, objectTableIndex));
}
private void PenumbraInit()
{
PenumbraInitialized?.Invoke();
_mediator.Publish(new PenumbraInitializedMessage());
_penumbraRedraw!.Invoke("self", RedrawType.Redraw);
}
private void HeelsOffsetChange(float offset)
{
HeelsOffsetChangeEvent?.Invoke(offset);
_mediator.Publish(new HeelsOffsetMessage(offset));
}
private void OnCustomizePlusScaleChange(string? scale)
{
if (scale != null) scale = Convert.ToBase64String(Encoding.UTF8.GetBytes(scale));
CustomizePlusScaleChange?.Invoke(scale);
_mediator.Publish(new CustomizePlusMessage(scale));
}
private void OnPalettePlusPaletteChange(Character character, string palette)
{
if (character.Address == 0 || character.Address != _dalamudUtil.PlayerPointer) return;
if (palette != null) palette = Convert.ToBase64String(Encoding.UTF8.GetBytes(palette));
PalettePlusPaletteChange?.Invoke(palette);
_mediator.Publish(new PalettePlusMessage(palette));
}
public void PalettePlusSetPalette(IntPtr character, string palette)
@@ -584,7 +575,7 @@ public class IpcManager : IDisposable
private void PenumbraDispose()
{
PenumbraDisposed?.Invoke();
_mediator.Publish(new PenumbraDisposedMessage());
ActionQueue.Clear();
}
}

View File

@@ -7,16 +7,15 @@ using MareSynchronos.WebAPI;
namespace MareSynchronos.Managers;
public class OnlinePlayerManager : IDisposable
public class OnlinePlayerManager : MediatorSubscriberBase, IDisposable
{
private readonly ApiController _apiController;
private readonly DalamudUtil _dalamudUtil;
private readonly PlayerManager _playerManager;
private readonly FileCacheManager _fileDbManager;
private readonly PairManager _pairManager;
private readonly MareMediator _mediator;
public OnlinePlayerManager(ApiController apiController, DalamudUtil dalamudUtil, PlayerManager playerManager, FileCacheManager fileDbManager, PairManager pairManager, MareMediator mediator)
public OnlinePlayerManager(ApiController apiController, DalamudUtil dalamudUtil, PlayerManager playerManager, FileCacheManager fileDbManager, PairManager pairManager, MareMediator mediator) : base(mediator)
{
Logger.Verbose("Creating " + nameof(OnlinePlayerManager));
@@ -25,41 +24,32 @@ public class OnlinePlayerManager : IDisposable
_playerManager = playerManager;
_fileDbManager = fileDbManager;
_pairManager = pairManager;
_mediator = mediator;
_playerManager.PlayerHasChanged += PlayerManagerOnPlayerHasChanged;
_mediator.Subscribe<DalamudLoginMessage>(this, (_) => DalamudUtilOnLogIn());
_mediator.Subscribe<DalamudLogoutMessage>(this, (_) => DalamudUtilOnLogOut());
if (_dalamudUtil.IsLoggedIn)
{
DalamudUtilOnLogIn();
}
Mediator.Subscribe<PlayerChangedMessage>(this, (msg) => PlayerManagerOnPlayerHasChanged((PlayerChangedMessage)msg));
Mediator.Subscribe<DalamudLoginMessage>(this, (_) => DalamudUtilOnLogIn());
Mediator.Subscribe<DalamudLogoutMessage>(this, (_) => DalamudUtilOnLogOut());
Mediator.Subscribe<DelayedFrameworkUpdateMessage>(this, (_) => FrameworkOnUpdate());
}
private void PlayerManagerOnPlayerHasChanged(CharacterData characterCache)
private void PlayerManagerOnPlayerHasChanged(PlayerChangedMessage msg)
{
PushCharacterData(_pairManager.VisibleUsers);
}
private void DalamudUtilOnLogIn()
{
_mediator.Subscribe<DelayedFrameworkUpdateMessage>(this, (_) => FrameworkOnUpdate());
Mediator.Subscribe<DelayedFrameworkUpdateMessage>(this, (_) => FrameworkOnUpdate());
}
private void DalamudUtilOnLogOut()
{
_mediator.Unsubscribe<DelayedFrameworkUpdateMessage>(this);
Mediator.Unsubscribe<DelayedFrameworkUpdateMessage>(this);
}
public void Dispose()
public override void Dispose()
{
Logger.Verbose("Disposing " + nameof(OnlinePlayerManager));
_playerManager.PlayerHasChanged -= PlayerManagerOnPlayerHasChanged;
_mediator.Unsubscribe<DalamudLoginMessage>(this);
_mediator.Unsubscribe<DalamudLogoutMessage>(this);
_mediator.Unsubscribe<DelayedFrameworkUpdateMessage>(this);
base.Dispose();
}
private void FrameworkOnUpdate()

View File

@@ -3,10 +3,8 @@ using MareSynchronos.Utils;
using MareSynchronos.WebAPI;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using MareSynchronos.Models;
using MareSynchronos.FileCache;
using MareSynchronos.UI;
using MareSynchronos.API.Data.Enum;
using MareSynchronos.Delegates;
using MareSynchronos.Mediator;
#if DEBUG
#endif
@@ -14,17 +12,12 @@ using MareSynchronos.Mediator;
namespace MareSynchronos.Managers;
public class PlayerManager : IDisposable
public class PlayerManager : MediatorSubscriberBase, IDisposable
{
private readonly ApiController _apiController;
private readonly CharacterDataFactory _characterDataFactory;
private readonly DalamudUtil _dalamudUtil;
private readonly TransientResourceManager _transientResourceManager;
private readonly PeriodicFileScanner _periodicFileScanner;
private readonly SettingsUi _settingsUi;
private readonly MareMediator _mediator;
private readonly IpcManager _ipcManager;
public event CharacterDataDelegate? PlayerHasChanged;
public API.Data.CharacterData? LastCreatedCharacterData { get; private set; }
public Models.CharacterData PermanentDataCache { get; private set; } = new();
private readonly Dictionary<ObjectKind, Func<bool>> _objectKindsToUpdate = new();
@@ -35,8 +28,8 @@ public class PlayerManager : IDisposable
private readonly List<PlayerRelatedObject> _playerRelatedObjects = new();
public unsafe PlayerManager(ApiController apiController, IpcManager ipcManager,
CharacterDataFactory characterDataFactory, DalamudUtil dalamudUtil, TransientResourceManager transientResourceManager,
PeriodicFileScanner periodicFileScanner, SettingsUi settingsUi, MareMediator mediator)
CharacterDataFactory characterDataFactory, DalamudUtil dalamudUtil,
MareMediator mediator) : base(mediator)
{
Logger.Verbose("Creating " + nameof(PlayerManager));
@@ -44,19 +37,15 @@ public class PlayerManager : IDisposable
_ipcManager = ipcManager;
_characterDataFactory = characterDataFactory;
_dalamudUtil = dalamudUtil;
_transientResourceManager = transientResourceManager;
_periodicFileScanner = periodicFileScanner;
_settingsUi = settingsUi;
_mediator = mediator;
_apiController.Connected += ApiControllerOnConnected;
_apiController.Disconnected += ApiController_Disconnected;
_transientResourceManager.TransientResourceLoaded += HandleTransientResourceLoad;
_ipcManager.HeelsOffsetChangeEvent += HeelsOffsetChanged;
_ipcManager.CustomizePlusScaleChange += CustomizePlusChanged;
_ipcManager.PalettePlusPaletteChange += PalettePlusChanged;
_mediator.Subscribe<DelayedFrameworkUpdateMessage>(this, (_) => DalamudUtilOnDelayedFrameworkUpdate());
_mediator.Subscribe<FrameworkUpdateMessage>(this, (_) => DalamudUtilOnFrameworkUpdate());
Mediator.Subscribe<CustomizePlusMessage>(this, (msg) => CustomizePlusChanged((CustomizePlusMessage)msg));
Mediator.Subscribe<HeelsOffsetMessage>(this, (msg) => HeelsOffsetChanged((HeelsOffsetMessage)msg));
Mediator.Subscribe<HeelsOffsetMessage>(this, (msg) => PalettePlusChanged((PalettePlusMessage)msg));
Mediator.Subscribe<ConnectedMessage>(this, (_) => ApiControllerOnConnected());
Mediator.Subscribe<DisconnectedMessage>(this, (_) => ApiController_Disconnected());
Mediator.Subscribe<DelayedFrameworkUpdateMessage>(this, (_) => DalamudUtilOnDelayedFrameworkUpdate());
Mediator.Subscribe<FrameworkUpdateMessage>(this, (_) => DalamudUtilOnFrameworkUpdate());
Mediator.Subscribe<TransientResourceChangedMessage>(this, (msg) => HandleTransientResourceLoad((TransientResourceChangedMessage)msg));
Logger.Debug("Watching Player, ApiController is Connected: " + _apiController.IsConnected);
if (_apiController.IsConnected)
@@ -75,14 +64,14 @@ public class PlayerManager : IDisposable
private void DalamudUtilOnFrameworkUpdate()
{
_transientResourceManager.PlayerRelatedPointers = _playerRelatedObjects.Select(f => f.CurrentAddress).ToArray();
Mediator.Publish(new PlayerRelatedObjectPointerUpdateMessage(_playerRelatedObjects.Select(f => f.CurrentAddress).ToArray()));
}
public void HandleTransientResourceLoad(IntPtr gameObj, int idx)
public void HandleTransientResourceLoad(TransientResourceChangedMessage msg)
{
foreach (var obj in _playerRelatedObjects)
{
if (obj.Address == gameObj && !obj.HasUnprocessedUpdate)
if (obj.Address == msg.Address && !obj.HasUnprocessedUpdate)
{
_transientUpdateCts.Cancel();
_transientUpdateCts = new CancellationTokenSource();
@@ -101,19 +90,19 @@ public class PlayerManager : IDisposable
}
}
private void HeelsOffsetChanged(float change)
private void HeelsOffsetChanged(HeelsOffsetMessage change)
{
var player = _playerRelatedObjects.First(f => f.ObjectKind == ObjectKind.Player);
if (LastCreatedCharacterData != null && LastCreatedCharacterData.HeelsOffset != change && !player.IsProcessing)
if (LastCreatedCharacterData != null && LastCreatedCharacterData.HeelsOffset != change.Offset && !player.IsProcessing)
{
Logger.Debug("Heels offset changed to " + change);
Logger.Debug("Heels offset changed to " + change.Offset);
player.HasTransientsUpdate = true;
}
}
private void CustomizePlusChanged(string? change)
private void CustomizePlusChanged(CustomizePlusMessage msg)
{
change ??= string.Empty;
var change = msg.Data ?? string.Empty;
var player = _playerRelatedObjects.First(f => f.ObjectKind == ObjectKind.Player);
if (LastCreatedCharacterData != null && !string.Equals(LastCreatedCharacterData.CustomizePlusData, change, StringComparison.Ordinal) && !player.IsProcessing)
{
@@ -122,9 +111,9 @@ public class PlayerManager : IDisposable
}
}
private void PalettePlusChanged(string? change)
private void PalettePlusChanged(PalettePlusMessage msg)
{
change ??= string.Empty;
var change = msg.Data ?? string.Empty;
var player = _playerRelatedObjects.First(f => f.ObjectKind == ObjectKind.Player);
if (LastCreatedCharacterData != null && !string.Equals(LastCreatedCharacterData.PalettePlusData, change, StringComparison.Ordinal) && !player.IsProcessing)
{
@@ -133,24 +122,13 @@ public class PlayerManager : IDisposable
}
}
public void Dispose()
public override void Dispose()
{
Logger.Verbose("Disposing " + nameof(PlayerManager));
_mediator.Unsubscribe<DelayedFrameworkUpdateMessage>(this);
_mediator.Unsubscribe<FrameworkUpdateMessage>(this);
_apiController.Connected -= ApiControllerOnConnected;
_apiController.Disconnected -= ApiController_Disconnected;
_ipcManager.PenumbraRedrawEvent -= IpcManager_PenumbraRedrawEvent;
_transientResourceManager.TransientResourceLoaded -= HandleTransientResourceLoad;
base.Dispose();
_playerChangedCts?.Cancel();
_ipcManager.HeelsOffsetChangeEvent -= HeelsOffsetChanged;
_ipcManager.CustomizePlusScaleChange -= CustomizePlusChanged;
_ipcManager.PalettePlusPaletteChange -= PalettePlusChanged;
}
private unsafe void DalamudUtilOnDelayedFrameworkUpdate()
@@ -168,14 +146,14 @@ public class PlayerManager : IDisposable
{
Logger.Debug("ApiController Connected");
_ipcManager.PenumbraRedrawEvent += IpcManager_PenumbraRedrawEvent;
Mediator.Subscribe<PenumbraRedrawMessage>(this, (msg) => IpcManager_PenumbraRedrawEvent((PenumbraRedrawMessage)msg));
}
private void ApiController_Disconnected()
{
Logger.Debug(nameof(ApiController_Disconnected));
_ipcManager.PenumbraRedrawEvent -= IpcManager_PenumbraRedrawEvent;
Mediator.Unsubscribe<PenumbraRedrawMessage>(this);
}
private async Task<API.Data.CharacterData?> CreateFullCharacterCacheDto(CancellationToken token)
@@ -210,13 +188,13 @@ public class PlayerManager : IDisposable
return cache;
}
private void IpcManager_PenumbraRedrawEvent(IntPtr address, int idx)
private void IpcManager_PenumbraRedrawEvent(PenumbraRedrawMessage msg)
{
Logger.Verbose("RedrawEvent for addr " + address);
Logger.Verbose("RedrawEvent for addr " + msg.Address);
foreach (var item in _playerRelatedObjects)
{
if (address == item.Address)
if (msg.Address == item.Address)
{
Logger.Debug("Penumbra redraw Event for " + item.ObjectKind);
item.HasUnprocessedUpdate = true;
@@ -264,43 +242,41 @@ public class PlayerManager : IDisposable
Task.Run(async () =>
{
API.Data.CharacterData? cacheDto = null;
API.Data.CharacterData? cacheData = null;
try
{
_periodicFileScanner.HaltScan("Character creation");
Mediator.Publish(new HaltScanMessage("Character creation"));
foreach (var item in unprocessedObjects)
{
_dalamudUtil.WaitWhileCharacterIsDrawing("self " + item.ObjectKind.ToString(), item.Address, item.ObjectKind == ObjectKind.MinionOrMount ? 1000 : 10000, token);
}
cacheDto = (await CreateFullCharacterCacheDto(token).ConfigureAwait(false));
cacheData = (await CreateFullCharacterCacheDto(token).ConfigureAwait(false));
}
catch { }
finally
{
_periodicFileScanner.ResumeScan("Character creation");
Mediator.Publish(new ResumeScanMessage("Character creation"));
}
if (cacheDto == null || token.IsCancellationRequested) return;
_settingsUi.LastCreatedCharacterData = cacheDto;
if (cacheData == null || token.IsCancellationRequested) return;
#if DEBUG
//var json = JsonConvert.SerializeObject(cacheDto, Formatting.Indented);
//Logger.Verbose(json);
#endif
if (string.Equals(LastCreatedCharacterData?.DataHash.Value ?? string.Empty, cacheDto.DataHash.Value, StringComparison.Ordinal))
if (string.Equals(LastCreatedCharacterData?.DataHash.Value ?? string.Empty, cacheData.DataHash.Value, StringComparison.Ordinal))
{
Logger.Debug("Not sending data, already sent");
return;
}
LastCreatedCharacterData = cacheDto;
LastCreatedCharacterData = cacheData;
if (_apiController.IsConnected && !token.IsCancellationRequested && !doNotSendUpdate)
{
Logger.Verbose("Invoking PlayerHasChanged");
PlayerHasChanged?.Invoke(cacheDto);
Mediator.Publish(new PlayerChangedMessage(cacheData));
}
}, token);
}

View File

@@ -1,5 +1,4 @@
using MareSynchronos.API.Data.Enum;
using MareSynchronos.Delegates;
using MareSynchronos.Factories;
using MareSynchronos.MareConfiguration;
using MareSynchronos.Mediator;
@@ -10,14 +9,11 @@ using System.Collections.Concurrent;
namespace MareSynchronos.Managers;
public class TransientResourceManager : IDisposable
public class TransientResourceManager : MediatorSubscriberBase, IDisposable
{
private readonly IpcManager _ipcManager;
private readonly ConfigurationService _configurationService;
private readonly DalamudUtil _dalamudUtil;
private readonly MareMediator _mediator;
public event DrawObjectDelegate? TransientResourceLoaded;
public IntPtr[] PlayerRelatedPointers = Array.Empty<IntPtr>();
private readonly string[] _fileTypesToHandle = new[] { "tmb", "pap", "avfx", "atex", "sklb", "eid", "phyb", "scd", "skp", "shpk" };
[Obsolete]
@@ -26,16 +22,16 @@ public class TransientResourceManager : IDisposable
private ConcurrentDictionary<IntPtr, HashSet<string>> TransientResources { get; } = new();
private ConcurrentDictionary<ObjectKind, HashSet<FileReplacement>> SemiTransientResources { get; } = new();
public TransientResourceManager(IpcManager manager, ConfigurationService configurationService, DalamudUtil dalamudUtil, FileReplacementFactory fileReplacementFactory, MareMediator mediator)
public TransientResourceManager(ConfigurationService configurationService, DalamudUtil dalamudUtil, FileReplacementFactory fileReplacementFactory, MareMediator mediator) : base(mediator)
{
manager.PenumbraResourceLoadEvent += Manager_PenumbraResourceLoadEvent;
manager.PenumbraModSettingChanged += Manager_PenumbraModSettingChanged;
_ipcManager = manager;
_configurationService = configurationService;
_dalamudUtil = dalamudUtil;
_mediator = mediator;
_mediator.Subscribe<FrameworkUpdateMessage>(this, (_) => DalamudUtil_FrameworkUpdate());
_mediator.Subscribe<ClassJobChangedMessage>(this, (_) => DalamudUtil_ClassJobChanged());
mediator.Subscribe<PenumbraResourceLoadMessage>(this, (msg) => Manager_PenumbraResourceLoadEvent((PenumbraResourceLoadMessage)msg));
Mediator.Subscribe<PenumbraModSettingChangedMessage>(this, (_) => Manager_PenumbraModSettingChanged());
Mediator.Subscribe<FrameworkUpdateMessage>(this, (_) => DalamudUtil_FrameworkUpdate());
Mediator.Subscribe<ClassJobChangedMessage>(this, (_) => DalamudUtil_ClassJobChanged());
Mediator.Subscribe<PlayerRelatedObjectPointerUpdateMessage>(this, (msg) => PlayerRelatedPointers = ((PlayerRelatedObjectPointerUpdateMessage)msg).RelatedObjects);
// migrate obsolete data to new format
if (File.Exists(PersistentDataCache))
{
@@ -87,7 +83,7 @@ public class TransientResourceManager : IDisposable
return !verified;
});
if (!successfulValidation)
TransientResourceLoaded?.Invoke(_dalamudUtil.PlayerPointer, -1);
Mediator.Publish(new TransientResourceChangedMessage(_dalamudUtil.PlayerPointer));
}
});
}
@@ -140,8 +136,11 @@ public class TransientResourceManager : IDisposable
return new List<FileReplacement>();
}
private void Manager_PenumbraResourceLoadEvent(IntPtr gameObject, string gamePath, string filePath)
private void Manager_PenumbraResourceLoadEvent(PenumbraResourceLoadMessage msg)
{
var gamePath = msg.GamePath;
var gameObject = msg.GameObject;
var filePath = msg.FilePath;
if (!_fileTypesToHandle.Any(type => gamePath.EndsWith(type, StringComparison.OrdinalIgnoreCase)))
{
return;
@@ -180,7 +179,7 @@ public class TransientResourceManager : IDisposable
{
TransientResources[gameObject].Add(replacedGamePath);
Logger.Debug($"Adding {replacedGamePath} for {gameObject} ({filePath})");
TransientResourceLoaded?.Invoke(gameObject, -1);
Mediator.Publish(new TransientResourceChangedMessage(gameObject));
}
}
@@ -250,12 +249,9 @@ public class TransientResourceManager : IDisposable
TransientResources[gameObject].Clear();
}
public void Dispose()
public override void Dispose()
{
_mediator.Unsubscribe<FrameworkUpdateMessage>(this);
_mediator.Unsubscribe<ClassJobChangedMessage>(this);
_ipcManager.PenumbraResourceLoadEvent -= Manager_PenumbraResourceLoadEvent;
_ipcManager.PenumbraModSettingChanged -= Manager_PenumbraModSettingChanged;
base.Dispose();
TransientResources.Clear();
SemiTransientResources.Clear();
if (SemiTransientResources.ContainsKey(ObjectKind.Player))

View File

@@ -44,6 +44,14 @@ public class MareMediator : IDisposable
}
}
internal void UnsubscribeAll(object subscriber)
{
foreach (var kvp in _subscriberDict)
{
kvp.Value.RemoveWhere(p => p.Subscriber == subscriber);
}
}
public void Dispose()
{
_subscriberDict.Clear();

View File

@@ -20,4 +20,23 @@ public record ZoneSwitchEndMessage : IMessage;
public record GposeStartMessage : IMessage;
public record GposeEndMessage : IMessage;
public record GposeFrameworkUpdateMessage : IMessage;
public record ConnectedMessage : IMessage;
public record DisconnectedMessage : IMessage;
public record DownloadStartedMessage : IMessage;
public record DownloadFinishedMessage : IMessage;
public record PenumbraModSettingChangedMessage : IMessage;
public record PenumbraInitializedMessage : IMessage;
public record PenumbraDisposedMessage : IMessage;
public record PenumbraRedrawMessage(IntPtr Address, int ObjTblIdx) : IMessage;
public record HeelsOffsetMessage(float Offset) : IMessage;
public record PenumbraResourceLoadMessage(IntPtr GameObject, string GamePath, string FilePath) : IMessage;
public record CustomizePlusMessage(string? Data) : IMessage;
public record PalettePlusMessage(string? Data) : IMessage;
public record PlayerChangedMessage(API.Data.CharacterData Data) : IMessage;
public record TransientResourceChangedMessage(IntPtr Address) : IMessage;
public record PlayerRelatedObjectPointerUpdateMessage(IntPtr[] RelatedObjects) : IMessage;
public record HaltScanMessage(string Source) : IMessage;
public record ResumeScanMessage(string Source) : IMessage;
#pragma warning restore MA0048 // File name must match type name

View File

@@ -24,10 +24,9 @@ namespace MareSynchronos;
public sealed class Plugin : IDalamudPlugin
{
private const string _commandName = "/mare";
private IServiceScope? _runtimeServiceServiceScope;
private IServiceScope? _runtimeServiceScope;
private readonly ServiceProvider _serviceProvider;
public Plugin(DalamudPluginInterface pluginInterface, CommandManager commandManager, DataManager gameData,
Framework framework, ObjectTable objectTable, ClientState clientState, Condition condition, ChatGui chatGui)
{
@@ -78,13 +77,11 @@ public sealed class Plugin : IDalamudPlugin
_serviceProvider = collection.BuildServiceProvider(new ServiceProviderOptions() { ValidateOnBuild = true, ValidateScopes = true });
// those can be initialized outside of game login
_serviceProvider.GetRequiredService<Dalamud.Localization>().SetupWithLangCode("en");
_serviceProvider.GetRequiredService<DalamudPluginInterface>().UiBuilder.DisableGposeUiHide = true;
var mediator = _serviceProvider.GetRequiredService<MareMediator>();
mediator.Subscribe<SwitchToMainUiMessage>(this, (_) => ReLaunchCharacterManager());
mediator.Subscribe<SwitchToMainUiMessage>(this, (_) => Task.Run(WaitForPlayerAndLaunchCharacterManager));
mediator.Subscribe<DalamudLoginMessage>(this, (_) => DalamudUtilOnLogIn());
mediator.Subscribe<DalamudLogoutMessage>(this, (_) => DalamudUtilOnLogOut());
@@ -103,13 +100,12 @@ public sealed class Plugin : IDalamudPlugin
_serviceProvider.GetRequiredService<CommandManager>().RemoveHandler(_commandName);
_runtimeServiceServiceScope?.Dispose();
_runtimeServiceScope?.Dispose();
_serviceProvider.Dispose();
Logger.Debug("Shut down");
}
private void DalamudUtilOnLogIn()
{
Logger.Debug("Client login");
@@ -136,7 +132,7 @@ public sealed class Plugin : IDalamudPlugin
private void DalamudUtilOnLogOut()
{
Logger.Debug("Client logout");
_runtimeServiceServiceScope?.Dispose();
_runtimeServiceScope?.Dispose();
var pi = _serviceProvider.GetRequiredService<DalamudPluginInterface>();
pi.UiBuilder.Draw -= Draw;
pi.UiBuilder.OpenConfigUi -= OpenUi;
@@ -145,9 +141,7 @@ public sealed class Plugin : IDalamudPlugin
public void ReLaunchCharacterManager()
{
_runtimeServiceServiceScope?.Dispose();
Task.Run(WaitForPlayerAndLaunchCharacterManager);
}
private async Task WaitForPlayerAndLaunchCharacterManager()
@@ -162,10 +156,11 @@ public sealed class Plugin : IDalamudPlugin
{
Logger.Debug("Launching Managers");
_runtimeServiceServiceScope = _serviceProvider.CreateScope();
_runtimeServiceServiceScope.ServiceProvider.GetRequiredService<TransientResourceManager>();
_runtimeServiceServiceScope.ServiceProvider.GetRequiredService<PlayerManager>();
_runtimeServiceServiceScope.ServiceProvider.GetRequiredService<OnlinePlayerManager>();
_runtimeServiceScope?.Dispose();
_runtimeServiceScope = _serviceProvider.CreateScope();
_runtimeServiceScope.ServiceProvider.GetRequiredService<TransientResourceManager>();
_runtimeServiceScope.ServiceProvider.GetRequiredService<PlayerManager>();
_runtimeServiceScope.ServiceProvider.GetRequiredService<OnlinePlayerManager>();
}
catch (Exception ex)
{

View File

@@ -10,7 +10,6 @@ using Dalamud.Utility;
using ImGuiNET;
using MareSynchronos.API.Data.Extensions;
using MareSynchronos.API.Dto.User;
using MareSynchronos.Delegates;
using MareSynchronos.Managers;
using MareSynchronos.MareConfiguration;
using MareSynchronos.Mediator;
@@ -100,9 +99,8 @@ public class CompactUi : Window, IDisposable
_mediator.Subscribe<SwitchToMainUiMessage>(this, (_) => IsOpen = true);
_mediator.Subscribe<SwitchToIntroUiMessage>(this, (_) => IsOpen = false);
_uiShared.GposeStart += UiShared_GposeStart;
_uiShared.GposeEnd += UiShared_GposeEnd;
_mediator.Subscribe<GposeStartMessage>(this, (_) => UiShared_GposeStart());
_mediator.Subscribe<GposeEndMessage>(this, (_) => UiShared_GposeEnd());
SizeConstraints = new WindowSizeConstraints()
{
@@ -127,8 +125,6 @@ public class CompactUi : Window, IDisposable
public void Dispose()
{
Logger.Verbose("Disposing " + nameof(CompactUi));
_uiShared.GposeStart -= UiShared_GposeStart;
_uiShared.GposeEnd -= UiShared_GposeEnd;
_windowSystem.RemoveWindow(this);
}

View File

@@ -58,8 +58,9 @@ public class SettingsUi : Window, IDisposable
_mediator.Subscribe<OpenSettingsUiMessage>(this, (_) => Toggle());
_mediator.Subscribe<SwitchToIntroUiMessage>(this, (_) => IsOpen = false);
_uiShared.GposeStart += UiShared_GposeStart;
_uiShared.GposeEnd += UiShared_GposeEnd;
_mediator.Subscribe<GposeStartMessage>(this, (_) => UiShared_GposeStart());
_mediator.Subscribe<GposeEndMessage>(this, (_) => UiShared_GposeEnd());
_mediator.Subscribe<PlayerChangedMessage>(this, (msg) => LastCreatedCharacterData = ((PlayerChangedMessage)msg).Data);
windowSystem.AddWindow(this);
}
@@ -79,9 +80,6 @@ public class SettingsUi : Window, IDisposable
{
Logger.Verbose("Disposing " + nameof(SettingsUi));
_uiShared.GposeStart -= UiShared_GposeStart;
_uiShared.GposeEnd -= UiShared_GposeEnd;
_windowSystem.RemoveWindow(this);
}

View File

@@ -9,7 +9,6 @@ using Dalamud.Interface.ImGuiFileDialog;
using Dalamud.Plugin;
using Dalamud.Utility;
using ImGuiNET;
using MareSynchronos.Delegates;
using MareSynchronos.FileCache;
using MareSynchronos.Localization;
using MareSynchronos.Managers;
@@ -35,7 +34,6 @@ public partial class UiShared : IDisposable
private readonly DalamudPluginInterface _pluginInterface;
private readonly Dalamud.Localization _localization;
private readonly ServerConfigurationManager _serverConfigurationManager;
private readonly MareMediator _mediator;
public long FileCacheSize => _cacheScanner.FileCacheSize;
public string PlayerName => _dalamudUtil.PlayerName;
@@ -46,8 +44,6 @@ public partial class UiShared : IDisposable
public ImFontPtr UidFont { get; private set; }
public bool UidFontBuilt { get; private set; }
public bool IsInGpose => _dalamudUtil.IsInGpose;
public event VoidDelegate? GposeStart;
public event VoidDelegate? GposeEnd;
public static bool CtrlPressed() => (GetKeyState(0xA2) & 0x8000) != 0 || (GetKeyState(0xA3) & 0x8000) != 0;
public static bool ShiftPressed() => (GetKeyState(0xA1) & 0x8000) != 0 || (GetKeyState(0xA0) & 0x8000) != 0;
@@ -59,7 +55,7 @@ public partial class UiShared : IDisposable
public UiShared(IpcManager ipcManager, ApiController apiController, PeriodicFileScanner cacheScanner, FileDialogManager fileDialogManager,
ConfigurationService configService, DalamudUtil dalamudUtil, DalamudPluginInterface pluginInterface, Dalamud.Localization localization,
ServerConfigurationManager serverManager, MareMediator mediator)
ServerConfigurationManager serverManager)
{
_ipcManager = ipcManager;
_apiController = apiController;
@@ -70,24 +66,10 @@ public partial class UiShared : IDisposable
_pluginInterface = pluginInterface;
_localization = localization;
_serverConfigurationManager = serverManager;
_mediator = mediator;
_isDirectoryWritable = IsDirectoryWritable(_configService.Current.CacheFolder);
_pluginInterface.UiBuilder.BuildFonts += BuildFont;
_pluginInterface.UiBuilder.RebuildFonts();
_mediator.Subscribe<GposeStartMessage>(this, (_) => DalamudUtil_GposeStart());
_mediator.Subscribe<GposeEndMessage>(this, (_) => DalamudUtil_GposeEnd());
}
private void DalamudUtil_GposeEnd()
{
GposeEnd?.Invoke();
}
private void DalamudUtil_GposeStart()
{
GposeStart?.Invoke();
}
public static float GetWindowContentRegionWidth()

View File

@@ -6,6 +6,7 @@ namespace MareSynchronos.Utils;
public static class Crypto
{
#pragma warning disable SYSLIB0021 // Type or member is obsolete
public static string GetFileHash(this string filePath)
{
using SHA1CryptoServiceProvider cryptoProvider = new();
@@ -29,4 +30,5 @@ public static class Crypto
using SHA256CryptoServiceProvider cryptoProvider = new();
return BitConverter.ToString(cryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(character.Name + character.HomeWorld.Id.ToString()))).Replace("-", "", StringComparison.Ordinal);
}
#pragma warning restore SYSLIB0021 // Type or member is obsolete
}

View File

@@ -107,6 +107,7 @@ public class DalamudUtil : IDisposable
Logger.Debug("Zone switch/Gpose start");
_sentBetweenAreas = true;
_mediator.Publish(new ZoneSwitchStartMessage());
_mediator.Publish(new HaltScanMessage("Zone switch"));
}
if (IsInGpose) _mediator.Publish(new GposeFrameworkUpdateMessage());
@@ -119,6 +120,7 @@ public class DalamudUtil : IDisposable
Logger.Debug("Zone switch/Gpose end");
_sentBetweenAreas = false;
_mediator.Publish(new ZoneSwitchEndMessage());
_mediator.Publish(new ResumeScanMessage("Zone switch"));
}
_mediator.Publish(new FrameworkUpdateMessage());

View File

@@ -0,0 +1,18 @@
using MareSynchronos.Mediator;
namespace MareSynchronos.Utils;
public abstract class MediatorSubscriberBase : IDisposable
{
protected MediatorSubscriberBase(MareMediator mediator)
{
Mediator = mediator;
}
protected MareMediator Mediator;
public virtual void Dispose()
{
Mediator.UnsubscribeAll(this);
}
}

View File

@@ -9,6 +9,7 @@ using LZ4;
using MareSynchronos.API.Data;
using MareSynchronos.API.Dto.Files;
using MareSynchronos.API.Routes;
using MareSynchronos.Mediator;
using MareSynchronos.Utils;
using MareSynchronos.WebAPI.Utils;
using Microsoft.AspNetCore.SignalR.Client;
@@ -185,7 +186,7 @@ public partial class ApiController
public async Task DownloadFiles(int currentDownloadId, List<FileReplacementData> fileReplacementDto, CancellationToken ct)
{
DownloadStarted?.Invoke();
_mediator.Publish(new HaltScanMessage("Download"));
try
{
await DownloadFilesInternal(currentDownloadId, fileReplacementDto, ct).ConfigureAwait(false);
@@ -196,7 +197,7 @@ public partial class ApiController
}
finally
{
DownloadFinished?.Invoke();
_mediator.Publish(new ResumeScanMessage("Download"));
}
}

View File

@@ -11,7 +11,6 @@ using MareSynchronos.API.SignalR;
using MareSynchronos.Managers;
using Dalamud.Utility;
using MareSynchronos.MareConfiguration;
using MareSynchronos.Delegates;
using MareSynchronos.Mediator;
namespace MareSynchronos.WebAPI;
@@ -80,11 +79,6 @@ public partial class ApiController : IDisposable, IMareHubClient
Task.Run(() => CreateConnections(forceGetToken: true));
}
public event VoidDelegate? Connected;
public event VoidDelegate? Disconnected;
public event VoidDelegate? DownloadStarted;
public event VoidDelegate? DownloadFinished;
public ConcurrentDictionary<int, List<DownloadFileTransfer>> CurrentDownloads { get; } = new();
public List<FileTransfer> CurrentUploads { get; } = new();
@@ -309,7 +303,7 @@ public partial class ApiController : IDisposable, IMareHubClient
_ = ClientHealthCheck(_healthCheckTokenSource.Token);
_initialized = true;
Connected?.Invoke();
_mediator.Publish(new ConnectedMessage());
}
public void Dispose()
@@ -346,7 +340,7 @@ public partial class ApiController : IDisposable, IMareHubClient
CurrentDownloads.Clear();
_uploadCancellationTokenSource?.Cancel();
_healthCheckTokenSource?.Cancel();
Disconnected?.Invoke();
_mediator.Publish(new DisconnectedMessage());
_pairManager.ClearPairs();
ServerState = ServerState.Offline;
Logger.Info("Connection closed");
@@ -361,7 +355,7 @@ public partial class ApiController : IDisposable, IMareHubClient
Logger.Warn("Connection closed... Reconnecting");
Logger.Warn(arg?.Message ?? string.Empty);
Logger.Warn(arg?.StackTrace ?? string.Empty);
Disconnected?.Invoke();
_mediator.Publish(new DisconnectedMessage());
_pairManager.ClearPairs();
return Task.CompletedTask;
}
@@ -391,7 +385,7 @@ public partial class ApiController : IDisposable, IMareHubClient
await _mareHub.DisposeAsync().ConfigureAwait(false);
CurrentUploads.Clear();
CurrentDownloads.Clear();
Disconnected?.Invoke();
_mediator.Publish(new DisconnectedMessage());
_pairManager.ClearPairs();
_mareHub = null;
}