refactor + add resiliency against penumbra/api shutdowns
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using System.Diagnostics;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||||
@@ -15,18 +16,31 @@ namespace MareSynchronos.Factories
|
|||||||
{
|
{
|
||||||
private readonly DalamudUtil _dalamudUtil;
|
private readonly DalamudUtil _dalamudUtil;
|
||||||
private readonly IpcManager _ipcManager;
|
private readonly IpcManager _ipcManager;
|
||||||
private readonly FileReplacementFactory _factory;
|
|
||||||
|
|
||||||
public CharacterDataFactory(DalamudUtil dalamudUtil, IpcManager ipcManager, FileReplacementFactory factory)
|
public CharacterDataFactory(DalamudUtil dalamudUtil, IpcManager ipcManager)
|
||||||
{
|
{
|
||||||
Logger.Debug("Creating " + nameof(CharacterDataFactory));
|
Logger.Debug("Creating " + nameof(CharacterDataFactory));
|
||||||
|
|
||||||
_dalamudUtil = dalamudUtil;
|
_dalamudUtil = dalamudUtil;
|
||||||
_ipcManager = ipcManager;
|
_ipcManager = ipcManager;
|
||||||
_factory = factory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe CharacterData BuildCharacterData()
|
private FileReplacement CreateBaseFileReplacement()
|
||||||
|
{
|
||||||
|
return new FileReplacement(_ipcManager.PenumbraModDirectory()!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharacterData BuildCharacterData()
|
||||||
|
{
|
||||||
|
if (!_dalamudUtil.IsPlayerPresent || !_ipcManager.Initialized)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Player is not present or Penumbra is not connected");
|
||||||
|
}
|
||||||
|
|
||||||
|
return CreateCharacterData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe CharacterData CreateCharacterData()
|
||||||
{
|
{
|
||||||
Stopwatch st = Stopwatch.StartNew();
|
Stopwatch st = Stopwatch.StartNew();
|
||||||
var cache = new CharacterData();
|
var cache = new CharacterData();
|
||||||
@@ -47,7 +61,7 @@ namespace MareSynchronos.Factories
|
|||||||
|
|
||||||
var mdlPath = new Utf8String(mdl->ResourceHandle->FileName()).ToString();
|
var mdlPath = new Utf8String(mdl->ResourceHandle->FileName()).ToString();
|
||||||
|
|
||||||
FileReplacement cachedMdlResource = _factory.Create();
|
FileReplacement cachedMdlResource = CreateBaseFileReplacement();
|
||||||
cachedMdlResource.GamePaths = _ipcManager.PenumbraReverseResolvePath(mdlPath, _dalamudUtil.PlayerName);
|
cachedMdlResource.GamePaths = _ipcManager.PenumbraReverseResolvePath(mdlPath, _dalamudUtil.PlayerName);
|
||||||
cachedMdlResource.SetResolvedPath(mdlPath);
|
cachedMdlResource.SetResolvedPath(mdlPath);
|
||||||
//PluginLog.Verbose("Resolving for model " + mdlPath);
|
//PluginLog.Verbose("Resolving for model " + mdlPath);
|
||||||
@@ -59,10 +73,10 @@ namespace MareSynchronos.Factories
|
|||||||
var mtrl = (Material*)mdl->Materials[mtrlIdx];
|
var mtrl = (Material*)mdl->Materials[mtrlIdx];
|
||||||
if (mtrl == null) continue;
|
if (mtrl == null) continue;
|
||||||
|
|
||||||
//var mtrlFileResource = factory.Create();
|
//var mtrlFileResource = factory.CreateBaseFileReplacement();
|
||||||
var mtrlPath = new Utf8String(mtrl->ResourceHandle->FileName()).ToString().Split("|")[2];
|
var mtrlPath = new Utf8String(mtrl->ResourceHandle->FileName()).ToString().Split("|")[2];
|
||||||
//PluginLog.Verbose("Resolving for material " + mtrlPath);
|
//PluginLog.Verbose("Resolving for material " + mtrlPath);
|
||||||
var cachedMtrlResource = _factory.Create();
|
var cachedMtrlResource = CreateBaseFileReplacement();
|
||||||
cachedMtrlResource.GamePaths = _ipcManager.PenumbraReverseResolvePath(mtrlPath, _dalamudUtil.PlayerName);
|
cachedMtrlResource.GamePaths = _ipcManager.PenumbraReverseResolvePath(mtrlPath, _dalamudUtil.PlayerName);
|
||||||
cachedMtrlResource.SetResolvedPath(mtrlPath);
|
cachedMtrlResource.SetResolvedPath(mtrlPath);
|
||||||
cache.AddAssociatedResource(cachedMtrlResource, cachedMdlResource, null!);
|
cache.AddAssociatedResource(cachedMtrlResource, cachedMdlResource, null!);
|
||||||
@@ -74,7 +88,7 @@ namespace MareSynchronos.Factories
|
|||||||
|
|
||||||
if (string.IsNullOrEmpty(texPath.ToString())) continue;
|
if (string.IsNullOrEmpty(texPath.ToString())) continue;
|
||||||
|
|
||||||
var cachedTexResource = _factory.Create();
|
var cachedTexResource = CreateBaseFileReplacement();
|
||||||
cachedTexResource.GamePaths = new[] { texPath };
|
cachedTexResource.GamePaths = new[] { texPath };
|
||||||
cachedTexResource.SetResolvedPath(_ipcManager.PenumbraResolvePath(texPath, _dalamudUtil.PlayerName)!);
|
cachedTexResource.SetResolvedPath(_ipcManager.PenumbraResolvePath(texPath, _dalamudUtil.PlayerName)!);
|
||||||
if (!cachedTexResource.HasFileReplacement)
|
if (!cachedTexResource.HasFileReplacement)
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
using MareSynchronos.Managers;
|
|
||||||
using MareSynchronos.Models;
|
|
||||||
using MareSynchronos.Utils;
|
|
||||||
|
|
||||||
namespace MareSynchronos.Factories
|
|
||||||
{
|
|
||||||
public class FileReplacementFactory
|
|
||||||
{
|
|
||||||
private readonly IpcManager _ipcManager;
|
|
||||||
|
|
||||||
public FileReplacementFactory(IpcManager ipcManager)
|
|
||||||
{
|
|
||||||
Logger.Debug("Creating " + nameof(FileReplacementFactory));
|
|
||||||
|
|
||||||
this._ipcManager = ipcManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileReplacement Create()
|
|
||||||
{
|
|
||||||
if (!_ipcManager.CheckPenumbraApi())
|
|
||||||
{
|
|
||||||
throw new System.Exception();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new FileReplacement(_ipcManager.PenumbraModDirectory()!);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -37,6 +37,46 @@ public class CharacterCacheManager : IDisposable
|
|||||||
_apiController = apiController;
|
_apiController = apiController;
|
||||||
_dalamudUtil = dalamudUtil;
|
_dalamudUtil = dalamudUtil;
|
||||||
_ipcManager = ipcManager;
|
_ipcManager = ipcManager;
|
||||||
|
|
||||||
|
_clientState.Login += ClientStateOnLogin;
|
||||||
|
_clientState.Logout += ClientStateOnLogout;
|
||||||
|
|
||||||
|
_apiController.CharacterReceived += ApiControllerOnCharacterReceived;
|
||||||
|
_apiController.PairedClientOnline += ApiControllerOnPairedClientOnline;
|
||||||
|
_apiController.PairedClientOffline += ApiControllerOnPairedClientOffline;
|
||||||
|
_apiController.PairedWithOther += ApiControllerOnPairedWithOther;
|
||||||
|
_apiController.UnpairedFromOther += ApiControllerOnUnpairedFromOther;
|
||||||
|
_apiController.Disconnected += ApiControllerOnDisconnected;
|
||||||
|
_ipcManager.PenumbraDisposed += IpcManagerOnPenumbraDisposed;
|
||||||
|
|
||||||
|
if (clientState.IsLoggedIn)
|
||||||
|
{
|
||||||
|
ClientStateOnLogin(null, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IpcManagerOnPenumbraDisposed(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
foreach (var character in _onlineCachedPlayers.ToList())
|
||||||
|
{
|
||||||
|
RestoreCharacter(character);
|
||||||
|
character.IsVisible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApiControllerOnDisconnected(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
RestoreAllCharacters();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClientStateOnLogin(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_framework.Update += FrameworkOnUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClientStateOnLogout(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_framework.Update -= FrameworkOnUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddInitialPairs(List<string> apiTaskResult)
|
public void AddInitialPairs(List<string> apiTaskResult)
|
||||||
@@ -55,8 +95,15 @@ public class CharacterCacheManager : IDisposable
|
|||||||
_apiController.PairedClientOffline -= ApiControllerOnPairedClientOffline;
|
_apiController.PairedClientOffline -= ApiControllerOnPairedClientOffline;
|
||||||
_apiController.PairedWithOther -= ApiControllerOnPairedWithOther;
|
_apiController.PairedWithOther -= ApiControllerOnPairedWithOther;
|
||||||
_apiController.UnpairedFromOther -= ApiControllerOnUnpairedFromOther;
|
_apiController.UnpairedFromOther -= ApiControllerOnUnpairedFromOther;
|
||||||
|
_ipcManager.PenumbraDisposed -= ApiControllerOnDisconnected;
|
||||||
_framework.Update -= FrameworkOnUpdate;
|
_framework.Update -= FrameworkOnUpdate;
|
||||||
|
_clientState.Login -= ClientStateOnLogin;
|
||||||
|
_clientState.Logout -= ClientStateOnLogout;
|
||||||
|
RestoreAllCharacters();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RestoreAllCharacters()
|
||||||
|
{
|
||||||
foreach (var character in _onlineCachedPlayers.ToList())
|
foreach (var character in _onlineCachedPlayers.ToList())
|
||||||
{
|
{
|
||||||
RestoreCharacter(character);
|
RestoreCharacter(character);
|
||||||
@@ -65,18 +112,6 @@ public class CharacterCacheManager : IDisposable
|
|||||||
_onlineCachedPlayers.Clear();
|
_onlineCachedPlayers.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize()
|
|
||||||
{
|
|
||||||
_onlineCachedPlayers.Clear();
|
|
||||||
|
|
||||||
_apiController.CharacterReceived += ApiControllerOnCharacterReceived;
|
|
||||||
_apiController.PairedClientOnline += ApiControllerOnPairedClientOnline;
|
|
||||||
_apiController.PairedClientOffline += ApiControllerOnPairedClientOffline;
|
|
||||||
_apiController.PairedWithOther += ApiControllerOnPairedWithOther;
|
|
||||||
_apiController.UnpairedFromOther += ApiControllerOnUnpairedFromOther;
|
|
||||||
_framework.Update += FrameworkOnUpdate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task UpdatePlayersFromService(Dictionary<string, int> playerJobIds)
|
public async Task UpdatePlayersFromService(Dictionary<string, int> playerJobIds)
|
||||||
{
|
{
|
||||||
await _apiController.GetCharacterData(playerJobIds);
|
await _apiController.GetCharacterData(playerJobIds);
|
||||||
@@ -190,6 +225,7 @@ public class CharacterCacheManager : IDisposable
|
|||||||
if (DateTime.Now < _lastPlayerObjectCheck.AddSeconds(2)) return;
|
if (DateTime.Now < _lastPlayerObjectCheck.AddSeconds(2)) return;
|
||||||
|
|
||||||
_localVisiblePlayers.Clear();
|
_localVisiblePlayers.Clear();
|
||||||
|
if (!_ipcManager.Initialized) return;
|
||||||
foreach (var obj in _objectTable)
|
foreach (var obj in _objectTable)
|
||||||
{
|
{
|
||||||
if (obj.ObjectKind != Dalamud.Game.ClientState.Objects.Enums.ObjectKind.Player) continue;
|
if (obj.ObjectKind != Dalamud.Game.ClientState.Objects.Enums.ObjectKind.Player) continue;
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ namespace MareSynchronos.Managers
|
|||||||
{
|
{
|
||||||
var apiTask = _apiController.SendCharacterName(_dalamudUtil.PlayerNameHashed);
|
var apiTask = _apiController.SendCharacterName(_dalamudUtil.PlayerNameHashed);
|
||||||
_lastSentHash = string.Empty;
|
_lastSentHash = string.Empty;
|
||||||
_characterCacheManager.Initialize();
|
|
||||||
|
|
||||||
Task.WaitAll(apiTask);
|
Task.WaitAll(apiTask);
|
||||||
|
|
||||||
@@ -81,8 +80,6 @@ namespace MareSynchronos.Managers
|
|||||||
|
|
||||||
private void ApiController_Disconnected(object? sender, EventArgs args)
|
private void ApiController_Disconnected(object? sender, EventArgs args)
|
||||||
{
|
{
|
||||||
_characterCacheManager.Dispose();
|
|
||||||
|
|
||||||
Logger.Debug(nameof(ApiController_Disconnected));
|
Logger.Debug(nameof(ApiController_Disconnected));
|
||||||
|
|
||||||
_ipcManager.PenumbraRedrawEvent -= IpcManager_PenumbraRedrawEvent;
|
_ipcManager.PenumbraRedrawEvent -= IpcManager_PenumbraRedrawEvent;
|
||||||
@@ -126,6 +123,12 @@ namespace MareSynchronos.Managers
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_ipcManager.Initialized)
|
||||||
|
{
|
||||||
|
PluginLog.Warning("Penumbra not active, doing nothing.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_playerChangedTask = Task.Run(async () =>
|
_playerChangedTask = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
Stopwatch st = Stopwatch.StartNew();
|
Stopwatch st = Stopwatch.StartNew();
|
||||||
@@ -152,28 +155,21 @@ namespace MareSynchronos.Managers
|
|||||||
Logger.Debug("Watcher Player Changed");
|
Logger.Debug("Watcher Player Changed");
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
try
|
// fix for redraw from anamnesis
|
||||||
|
while (!_dalamudUtil.IsPlayerPresent)
|
||||||
{
|
{
|
||||||
// fix for redraw from anamnesis
|
Logger.Debug("Waiting Until Player is Present");
|
||||||
while (!_dalamudUtil.IsPlayerPresent)
|
Thread.Sleep(100);
|
||||||
{
|
|
||||||
Logger.Debug("Waiting Until Player is Present");
|
|
||||||
Thread.Sleep(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actor.Name.ToString() == _dalamudUtil.PlayerName)
|
|
||||||
{
|
|
||||||
Logger.Debug("Watcher: PlayerChanged");
|
|
||||||
PlayerChanged(actor.Name.ToString());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Debug("PlayerChanged: " + actor.Name.ToString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
|
if (actor.Name.ToString() == _dalamudUtil.PlayerName)
|
||||||
{
|
{
|
||||||
PluginLog.Error(ex, "Actor was null or broken " + actor);
|
Logger.Debug("Watcher: PlayerChanged");
|
||||||
|
PlayerChanged(actor.Name.ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.Debug("PlayerChanged: " + actor.Name.ToString());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,17 +26,32 @@ namespace MareSynchronos.Managers
|
|||||||
_ipcManager = ipcManager;
|
_ipcManager = ipcManager;
|
||||||
_pluginConfiguration = pluginConfiguration;
|
_pluginConfiguration = pluginConfiguration;
|
||||||
|
|
||||||
if (_ipcManager.CheckPenumbraApi()
|
StartWatchersAndScan();
|
||||||
&& _pluginConfiguration.AcceptedAgreement
|
|
||||||
&& !string.IsNullOrEmpty(_pluginConfiguration.CacheFolder)
|
_ipcManager.PenumbraInitialized += IpcManagerOnPenumbraInitialized;
|
||||||
&& _pluginConfiguration.ClientSecret.ContainsKey(_pluginConfiguration.ApiUri)
|
_ipcManager.PenumbraDisposed += IpcManagerOnPenumbraDisposed;
|
||||||
&& !string.IsNullOrEmpty(_ipcManager.PenumbraModDirectory()))
|
}
|
||||||
|
|
||||||
|
private void StartWatchersAndScan()
|
||||||
|
{
|
||||||
|
if (_ipcManager.Initialized && _pluginConfiguration.HasValidSetup)
|
||||||
{
|
{
|
||||||
|
Logger.Debug("Penumbra is active, configuration is valid, starting watchers and scan");
|
||||||
StartWatchers();
|
StartWatchers();
|
||||||
StartInitialScan();
|
StartInitialScan();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void IpcManagerOnPenumbraInitialized(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
StartWatchersAndScan();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IpcManagerOnPenumbraDisposed(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
StopWatchersAndScan();
|
||||||
|
}
|
||||||
|
|
||||||
public long CurrentFileProgress { get; private set; }
|
public long CurrentFileProgress { get; private set; }
|
||||||
public long FileCacheSize { get; set; }
|
public long FileCacheSize { get; set; }
|
||||||
public bool IsScanRunning => !_scanTask?.IsCompleted ?? false;
|
public bool IsScanRunning => !_scanTask?.IsCompleted ?? false;
|
||||||
@@ -68,6 +83,14 @@ namespace MareSynchronos.Managers
|
|||||||
{
|
{
|
||||||
Logger.Debug("Disposing " + nameof(FileCacheManager));
|
Logger.Debug("Disposing " + nameof(FileCacheManager));
|
||||||
|
|
||||||
|
_ipcManager.PenumbraInitialized -= IpcManagerOnPenumbraInitialized;
|
||||||
|
_ipcManager.PenumbraDisposed -= IpcManagerOnPenumbraDisposed;
|
||||||
|
|
||||||
|
StopWatchersAndScan();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopWatchersAndScan()
|
||||||
|
{
|
||||||
_cacheDirWatcher?.Dispose();
|
_cacheDirWatcher?.Dispose();
|
||||||
_penumbraDirWatcher?.Dispose();
|
_penumbraDirWatcher?.Dispose();
|
||||||
_scanCancellationTokenSource?.Cancel();
|
_scanCancellationTokenSource?.Cancel();
|
||||||
@@ -81,6 +104,7 @@ namespace MareSynchronos.Managers
|
|||||||
|
|
||||||
public void StartWatchers()
|
public void StartWatchers()
|
||||||
{
|
{
|
||||||
|
if (!_ipcManager.Initialized || !_pluginConfiguration.HasValidSetup) return;
|
||||||
Logger.Debug("Starting File System Watchers");
|
Logger.Debug("Starting File System Watchers");
|
||||||
_penumbraDirWatcher?.Dispose();
|
_penumbraDirWatcher?.Dispose();
|
||||||
_cacheDirWatcher?.Dispose();
|
_cacheDirWatcher?.Dispose();
|
||||||
@@ -91,7 +115,6 @@ namespace MareSynchronos.Managers
|
|||||||
InternalBufferSize = 65536
|
InternalBufferSize = 65536
|
||||||
};
|
};
|
||||||
_penumbraDirWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size;
|
_penumbraDirWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size;
|
||||||
//_penumbraDirWatcher.Created += OnCreated;
|
|
||||||
_penumbraDirWatcher.Deleted += OnDeleted;
|
_penumbraDirWatcher.Deleted += OnDeleted;
|
||||||
_penumbraDirWatcher.Changed += OnModified;
|
_penumbraDirWatcher.Changed += OnModified;
|
||||||
_penumbraDirWatcher.Filters.Add("*.mtrl");
|
_penumbraDirWatcher.Filters.Add("*.mtrl");
|
||||||
@@ -107,7 +130,6 @@ namespace MareSynchronos.Managers
|
|||||||
InternalBufferSize = 65536
|
InternalBufferSize = 65536
|
||||||
};
|
};
|
||||||
_cacheDirWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size;
|
_cacheDirWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size;
|
||||||
//_cacheDirWatcher.Created += OnCreated;
|
|
||||||
_cacheDirWatcher.Deleted += OnDeleted;
|
_cacheDirWatcher.Deleted += OnDeleted;
|
||||||
_cacheDirWatcher.Changed += OnModified;
|
_cacheDirWatcher.Changed += OnModified;
|
||||||
_cacheDirWatcher.Filters.Add("*.mtrl");
|
_cacheDirWatcher.Filters.Add("*.mtrl");
|
||||||
@@ -134,49 +156,6 @@ namespace MareSynchronos.Managers
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnCreated(object sender, FileSystemEventArgs e)
|
|
||||||
{
|
|
||||||
var fi = new FileInfo(e.FullPath);
|
|
||||||
using var db = new FileCacheContext();
|
|
||||||
var ext = fi.Extension.ToLower();
|
|
||||||
if (ext is ".mdl" or ".tex" or ".mtrl")
|
|
||||||
{
|
|
||||||
Logger.Debug("File created: " + e.FullPath);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var createdFileCache = Create(fi.FullName.ToLower());
|
|
||||||
db.Add(createdFileCache);
|
|
||||||
}
|
|
||||||
catch (FileLoadException)
|
|
||||||
{
|
|
||||||
Logger.Debug("File was still being written to.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (Directory.Exists(e.FullPath))
|
|
||||||
{
|
|
||||||
Logger.Debug("Folder added: " + e.FullPath);
|
|
||||||
var newFiles = Directory.EnumerateFiles(e.FullPath, "*.*", SearchOption.AllDirectories)
|
|
||||||
.Where(f => f.EndsWith(".tex", StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
f.EndsWith(".mdl", StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
f.EndsWith(".mtrl", StringComparison.OrdinalIgnoreCase)).ToList();
|
|
||||||
foreach (var file in newFiles)
|
|
||||||
{
|
|
||||||
Logger.Debug("Adding " + file);
|
|
||||||
db.Add(Create(file));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
db.SaveChanges();
|
|
||||||
|
|
||||||
if (e.FullPath.Contains(_pluginConfiguration.CacheFolder, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Task.Run(RecalculateFileCacheSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDeleted(object sender, FileSystemEventArgs e)
|
private void OnDeleted(object sender, FileSystemEventArgs e)
|
||||||
{
|
{
|
||||||
var fi = new FileInfo(e.FullPath);
|
var fi = new FileInfo(e.FullPath);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ namespace MareSynchronos.Managers
|
|||||||
private readonly ICallGateSubscriber<string, string, bool, (int, string)> _penumbraCreateTemporaryCollection;
|
private readonly ICallGateSubscriber<string, string, bool, (int, string)> _penumbraCreateTemporaryCollection;
|
||||||
private readonly ICallGateSubscriber<string, string> _penumbraGetMetaManipulations;
|
private readonly ICallGateSubscriber<string, string> _penumbraGetMetaManipulations;
|
||||||
private readonly ICallGateSubscriber<object> _penumbraInit;
|
private readonly ICallGateSubscriber<object> _penumbraInit;
|
||||||
|
private readonly ICallGateSubscriber<object> _penumbraDispose;
|
||||||
private readonly ICallGateSubscriber<IntPtr, int, object?> _penumbraObjectIsRedrawn;
|
private readonly ICallGateSubscriber<IntPtr, int, object?> _penumbraObjectIsRedrawn;
|
||||||
private readonly ICallGateSubscriber<string, int, object>? _penumbraRedraw;
|
private readonly ICallGateSubscriber<string, int, object>? _penumbraRedraw;
|
||||||
private readonly ICallGateSubscriber<string, int> _penumbraRemoveTemporaryCollection;
|
private readonly ICallGateSubscriber<string, int> _penumbraRemoveTemporaryCollection;
|
||||||
@@ -30,6 +31,7 @@ namespace MareSynchronos.Managers
|
|||||||
Logger.Debug("Creating " + nameof(IpcManager));
|
Logger.Debug("Creating " + nameof(IpcManager));
|
||||||
|
|
||||||
_penumbraInit = pi.GetIpcSubscriber<object>("Penumbra.Initialized");
|
_penumbraInit = pi.GetIpcSubscriber<object>("Penumbra.Initialized");
|
||||||
|
_penumbraDispose = pi.GetIpcSubscriber<object>("Penumbra.Disposed");
|
||||||
_penumbraResolvePath = pi.GetIpcSubscriber<string, string, string>("Penumbra.ResolveCharacterPath");
|
_penumbraResolvePath = pi.GetIpcSubscriber<string, string, string>("Penumbra.ResolveCharacterPath");
|
||||||
_penumbraResolveModDir = pi.GetIpcSubscriber<string>("Penumbra.GetModDirectory");
|
_penumbraResolveModDir = pi.GetIpcSubscriber<string>("Penumbra.GetModDirectory");
|
||||||
_penumbraRedraw = pi.GetIpcSubscriber<string, int, object>("Penumbra.RedrawObjectByName");
|
_penumbraRedraw = pi.GetIpcSubscriber<string, int, object>("Penumbra.RedrawObjectByName");
|
||||||
@@ -44,7 +46,8 @@ namespace MareSynchronos.Managers
|
|||||||
pi.GetIpcSubscriber<string, string>("Penumbra.GetMetaManipulations");
|
pi.GetIpcSubscriber<string, string>("Penumbra.GetMetaManipulations");
|
||||||
|
|
||||||
_penumbraObjectIsRedrawn.Subscribe(RedrawEvent);
|
_penumbraObjectIsRedrawn.Subscribe(RedrawEvent);
|
||||||
_penumbraInit.Subscribe(RedrawSelf);
|
_penumbraInit.Subscribe(PenumbraInit);
|
||||||
|
_penumbraDispose.Subscribe(PenumbraDispose);
|
||||||
|
|
||||||
_penumbraSetTemporaryMod =
|
_penumbraSetTemporaryMod =
|
||||||
pi
|
pi
|
||||||
@@ -56,12 +59,17 @@ namespace MareSynchronos.Managers
|
|||||||
_penumbraRemoveTemporaryCollection =
|
_penumbraRemoveTemporaryCollection =
|
||||||
pi.GetIpcSubscriber<string, int>("Penumbra.RemoveTemporaryCollection");
|
pi.GetIpcSubscriber<string, int>("Penumbra.RemoveTemporaryCollection");
|
||||||
|
|
||||||
Initialized = true;
|
if (Initialized)
|
||||||
|
{
|
||||||
|
PenumbraInitialized?.Invoke(null, EventArgs.Empty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public event EventHandler? PenumbraInitialized;
|
||||||
|
public event EventHandler? PenumbraDisposed;
|
||||||
public event EventHandler? PenumbraRedrawEvent;
|
public event EventHandler? PenumbraRedrawEvent;
|
||||||
|
|
||||||
public bool Initialized { get; private set; } = false;
|
public bool Initialized => CheckPenumbraApi();
|
||||||
public bool CheckGlamourerApi()
|
public bool CheckGlamourerApi()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -78,18 +86,22 @@ namespace MareSynchronos.Managers
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return _penumbraApiVersion.InvokeFunc() >= 4;
|
return _penumbraApiVersion.InvokeFunc() >= 5;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Logger.Debug("Disposing " + nameof(IpcManager));
|
Logger.Debug("Disposing " + nameof(IpcManager));
|
||||||
|
|
||||||
Uninitialize();
|
_penumbraDispose.Unsubscribe(PenumbraDispose);
|
||||||
|
_penumbraInit.Unsubscribe(PenumbraInit);
|
||||||
|
_penumbraObjectIsRedrawn.Unsubscribe(RedrawEvent);
|
||||||
|
Logger.Debug("IPC Manager disposed");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GlamourerApplyCharacterCustomization(string customization, string characterName)
|
public void GlamourerApplyCharacterCustomization(string customization, string characterName)
|
||||||
@@ -174,17 +186,15 @@ namespace MareSynchronos.Managers
|
|||||||
PenumbraRedrawEvent?.Invoke(objectTableIndex, EventArgs.Empty);
|
PenumbraRedrawEvent?.Invoke(objectTableIndex, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RedrawSelf()
|
private void PenumbraInit()
|
||||||
{
|
{
|
||||||
|
PenumbraInitialized?.Invoke(null, EventArgs.Empty);
|
||||||
_penumbraRedraw!.InvokeAction("self", 0);
|
_penumbraRedraw!.InvokeAction("self", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Uninitialize()
|
private void PenumbraDispose()
|
||||||
{
|
{
|
||||||
_penumbraInit.Unsubscribe(RedrawSelf);
|
PenumbraDisposed?.Invoke(null, EventArgs.Empty);
|
||||||
_penumbraObjectIsRedrawn.Unsubscribe(RedrawEvent);
|
|
||||||
Initialized = false;
|
|
||||||
Logger.Debug("IPC Manager disposed");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ namespace MareSynchronos
|
|||||||
private readonly ApiController _apiController;
|
private readonly ApiController _apiController;
|
||||||
private readonly ClientState _clientState;
|
private readonly ClientState _clientState;
|
||||||
private readonly CommandManager _commandManager;
|
private readonly CommandManager _commandManager;
|
||||||
|
private readonly Framework _framework;
|
||||||
private readonly Configuration _configuration;
|
private readonly Configuration _configuration;
|
||||||
private readonly FileCacheManager _fileCacheManager;
|
private readonly FileCacheManager _fileCacheManager;
|
||||||
private readonly IntroUi _introUi;
|
private readonly IntroUi _introUi;
|
||||||
@@ -32,7 +33,7 @@ namespace MareSynchronos
|
|||||||
private readonly WindowSystem _windowSystem;
|
private readonly WindowSystem _windowSystem;
|
||||||
private CharacterManager? _characterManager;
|
private CharacterManager? _characterManager;
|
||||||
private readonly DalamudUtil _dalamudUtil;
|
private readonly DalamudUtil _dalamudUtil;
|
||||||
private readonly CharacterCacheManager _characterCacheManager;
|
private CharacterCacheManager? _characterCacheManager;
|
||||||
private readonly IPlayerWatcher _playerWatcher;
|
private readonly IPlayerWatcher _playerWatcher;
|
||||||
private readonly DownloadUi _downloadUi;
|
private readonly DownloadUi _downloadUi;
|
||||||
|
|
||||||
@@ -42,6 +43,7 @@ namespace MareSynchronos
|
|||||||
Logger.Debug("Launching " + Name);
|
Logger.Debug("Launching " + Name);
|
||||||
_pluginInterface = pluginInterface;
|
_pluginInterface = pluginInterface;
|
||||||
_commandManager = commandManager;
|
_commandManager = commandManager;
|
||||||
|
_framework = framework;
|
||||||
_objectTable = objectTable;
|
_objectTable = objectTable;
|
||||||
_clientState = clientState;
|
_clientState = clientState;
|
||||||
_configuration = _pluginInterface.GetPluginConfig() as Configuration ?? new Configuration();
|
_configuration = _pluginInterface.GetPluginConfig() as Configuration ?? new Configuration();
|
||||||
@@ -49,18 +51,16 @@ namespace MareSynchronos
|
|||||||
|
|
||||||
_windowSystem = new WindowSystem("MareSynchronos");
|
_windowSystem = new WindowSystem("MareSynchronos");
|
||||||
|
|
||||||
|
new FileCacheContext().Dispose(); // make sure db is initialized I guess
|
||||||
|
|
||||||
|
// those can be initialized outside of game login
|
||||||
_apiController = new ApiController(_configuration);
|
_apiController = new ApiController(_configuration);
|
||||||
_ipcManager = new IpcManager(_pluginInterface);
|
_ipcManager = new IpcManager(_pluginInterface);
|
||||||
|
|
||||||
_fileCacheManager = new FileCacheManager(_ipcManager, _configuration);
|
_fileCacheManager = new FileCacheManager(_ipcManager, _configuration);
|
||||||
_dalamudUtil = new DalamudUtil(_clientState, _objectTable);
|
|
||||||
_characterCacheManager = new CharacterCacheManager(_clientState, framework, _objectTable, _apiController,
|
|
||||||
_dalamudUtil, _ipcManager);
|
|
||||||
_playerWatcher = PlayerWatchFactory.Create(framework, _clientState, _objectTable);
|
|
||||||
_playerWatcher.Enable();
|
|
||||||
|
|
||||||
var uiSharedComponent =
|
var uiSharedComponent =
|
||||||
new UiShared(_ipcManager, _apiController, _fileCacheManager, _configuration);
|
new UiShared(_ipcManager, _apiController, _fileCacheManager, _configuration);
|
||||||
|
|
||||||
_pluginUi = new PluginUi(_windowSystem, uiSharedComponent, _configuration, _apiController);
|
_pluginUi = new PluginUi(_windowSystem, uiSharedComponent, _configuration, _apiController);
|
||||||
_introUi = new IntroUi(_windowSystem, uiSharedComponent, _configuration, _fileCacheManager);
|
_introUi = new IntroUi(_windowSystem, uiSharedComponent, _configuration, _fileCacheManager);
|
||||||
_introUi.FinishedRegistration += (_, _) =>
|
_introUi.FinishedRegistration += (_, _) =>
|
||||||
@@ -71,7 +71,9 @@ namespace MareSynchronos
|
|||||||
};
|
};
|
||||||
_downloadUi = new DownloadUi(_windowSystem, _configuration, _apiController);
|
_downloadUi = new DownloadUi(_windowSystem, _configuration, _apiController);
|
||||||
|
|
||||||
new FileCacheContext().Dispose(); // make sure db is initialized I guess
|
_dalamudUtil = new DalamudUtil(_clientState, _objectTable);
|
||||||
|
_playerWatcher = PlayerWatchFactory.Create(framework, _clientState, _objectTable);
|
||||||
|
_playerWatcher.Enable();
|
||||||
|
|
||||||
clientState.Login += ClientState_Login;
|
clientState.Login += ClientState_Login;
|
||||||
clientState.Logout += ClientState_Logout;
|
clientState.Logout += ClientState_Logout;
|
||||||
@@ -87,8 +89,8 @@ namespace MareSynchronos
|
|||||||
{
|
{
|
||||||
_pluginUi.IsOpen = false;
|
_pluginUi.IsOpen = false;
|
||||||
_introUi.IsOpen = true;
|
_introUi.IsOpen = true;
|
||||||
_characterCacheManager.Dispose();
|
_characterCacheManager?.Dispose();
|
||||||
_characterManager!.Dispose();
|
_characterManager?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name => "Mare Synchronos";
|
public string Name => "Mare Synchronos";
|
||||||
@@ -102,7 +104,6 @@ namespace MareSynchronos
|
|||||||
_clientState.Login -= ClientState_Login;
|
_clientState.Login -= ClientState_Login;
|
||||||
_clientState.Logout -= ClientState_Logout;
|
_clientState.Logout -= ClientState_Logout;
|
||||||
|
|
||||||
|
|
||||||
_pluginUi?.Dispose();
|
_pluginUi?.Dispose();
|
||||||
_introUi?.Dispose();
|
_introUi?.Dispose();
|
||||||
_downloadUi?.Dispose();
|
_downloadUi?.Dispose();
|
||||||
@@ -110,7 +111,7 @@ namespace MareSynchronos
|
|||||||
_fileCacheManager?.Dispose();
|
_fileCacheManager?.Dispose();
|
||||||
_ipcManager?.Dispose();
|
_ipcManager?.Dispose();
|
||||||
_characterManager?.Dispose();
|
_characterManager?.Dispose();
|
||||||
_characterCacheManager.Dispose();
|
_characterCacheManager?.Dispose();
|
||||||
_playerWatcher.Disable();
|
_playerWatcher.Disable();
|
||||||
_playerWatcher.Dispose();
|
_playerWatcher.Dispose();
|
||||||
}
|
}
|
||||||
@@ -139,6 +140,7 @@ namespace MareSynchronos
|
|||||||
private void ClientState_Logout(object? sender, EventArgs e)
|
private void ClientState_Logout(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Logger.Debug("Client logout");
|
Logger.Debug("Client logout");
|
||||||
|
_characterCacheManager?.Dispose();
|
||||||
_characterManager?.Dispose();
|
_characterManager?.Dispose();
|
||||||
_pluginInterface.UiBuilder.Draw -= Draw;
|
_pluginInterface.UiBuilder.Draw -= Draw;
|
||||||
_pluginInterface.UiBuilder.OpenConfigUi -= OpenConfigUi;
|
_pluginInterface.UiBuilder.OpenConfigUi -= OpenConfigUi;
|
||||||
@@ -159,7 +161,9 @@ namespace MareSynchronos
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var characterCacheFactory =
|
var characterCacheFactory =
|
||||||
new CharacterDataFactory(_dalamudUtil, _ipcManager, new FileReplacementFactory(_ipcManager));
|
new CharacterDataFactory(_dalamudUtil, _ipcManager);
|
||||||
|
_characterCacheManager = new CharacterCacheManager(_clientState, _framework, _objectTable,
|
||||||
|
_apiController, _dalamudUtil, _ipcManager);
|
||||||
_characterManager = new CharacterManager(_apiController, _objectTable, _ipcManager,
|
_characterManager = new CharacterManager(_apiController, _objectTable, _ipcManager,
|
||||||
characterCacheFactory, _characterCacheManager, _dalamudUtil, _playerWatcher);
|
characterCacheFactory, _characterCacheManager, _dalamudUtil, _playerWatcher);
|
||||||
_characterManager.StartWatchingPlayer();
|
_characterManager.StartWatchingPlayer();
|
||||||
|
|||||||
@@ -31,6 +31,11 @@ namespace MareSynchronos.Utils
|
|||||||
|
|
||||||
public Dictionary<string, PlayerCharacter> GetLocalPlayers()
|
public Dictionary<string, PlayerCharacter> GetLocalPlayers()
|
||||||
{
|
{
|
||||||
|
if (!_clientState.IsLoggedIn)
|
||||||
|
{
|
||||||
|
return new Dictionary<string, PlayerCharacter>();
|
||||||
|
}
|
||||||
|
|
||||||
Dictionary<string, PlayerCharacter> allLocalPlayers = new();
|
Dictionary<string, PlayerCharacter> allLocalPlayers = new();
|
||||||
foreach (var obj in _objectTable)
|
foreach (var obj in _objectTable)
|
||||||
{
|
{
|
||||||
@@ -46,6 +51,8 @@ namespace MareSynchronos.Utils
|
|||||||
|
|
||||||
public unsafe void WaitWhileCharacterIsDrawing(IntPtr characterAddress)
|
public unsafe void WaitWhileCharacterIsDrawing(IntPtr characterAddress)
|
||||||
{
|
{
|
||||||
|
if (!_clientState.IsLoggedIn) return;
|
||||||
|
|
||||||
var obj = (GameObject*)characterAddress;
|
var obj = (GameObject*)characterAddress;
|
||||||
|
|
||||||
// ReSharper disable once LoopVariableIsNeverChangedInsideLoop
|
// ReSharper disable once LoopVariableIsNeverChangedInsideLoop
|
||||||
@@ -59,6 +66,6 @@ namespace MareSynchronos.Utils
|
|||||||
Thread.Sleep(500);
|
Thread.Sleep(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WaitWhileSelfIsDrawing() => WaitWhileCharacterIsDrawing(_clientState.LocalPlayer!.Address);
|
public void WaitWhileSelfIsDrawing() => WaitWhileCharacterIsDrawing(_clientState.LocalPlayer?.Address ?? new IntPtr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ namespace MareSynchronos.WebAPI
|
|||||||
public ConcurrentDictionary<string, (long, long)> CurrentDownloads { get; } = new();
|
public ConcurrentDictionary<string, (long, long)> CurrentDownloads { get; } = new();
|
||||||
public ConcurrentDictionary<string, (long, long)> CurrentUploads { get; } = new();
|
public ConcurrentDictionary<string, (long, long)> CurrentUploads { get; } = new();
|
||||||
public bool IsConnected => !string.IsNullOrEmpty(UID);
|
public bool IsConnected => !string.IsNullOrEmpty(UID);
|
||||||
public bool IsDownloading { get; private set; } = false;
|
public bool IsDownloading { get; private set; }
|
||||||
public bool IsUploading { get; private set; } = false;
|
public bool IsUploading { get; private set; }
|
||||||
public List<ClientPairDto> PairedClients { get; set; } = new();
|
public List<ClientPairDto> PairedClients { get; set; } = new();
|
||||||
public string SecretKey => _pluginConfiguration.ClientSecret.ContainsKey(ApiUri) ? _pluginConfiguration.ClientSecret[ApiUri] : "-";
|
public string SecretKey => _pluginConfiguration.ClientSecret.ContainsKey(ApiUri) ? _pluginConfiguration.ClientSecret[ApiUri] : "-";
|
||||||
public bool ServerAlive =>
|
public bool ServerAlive =>
|
||||||
@@ -95,7 +95,6 @@ namespace MareSynchronos.WebAPI
|
|||||||
|
|
||||||
public async Task<byte[]> DownloadFile(string hash)
|
public async Task<byte[]> DownloadFile(string hash)
|
||||||
{
|
{
|
||||||
IsDownloading = true;
|
|
||||||
var reader = await _fileHub!.StreamAsChannelAsync<byte[]>("DownloadFile", hash);
|
var reader = await _fileHub!.StreamAsChannelAsync<byte[]>("DownloadFile", hash);
|
||||||
List<byte> downloadedData = new();
|
List<byte> downloadedData = new();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -108,12 +107,13 @@ namespace MareSynchronos.WebAPI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IsDownloading = false;
|
|
||||||
return downloadedData.ToArray();
|
return downloadedData.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DownloadFiles(List<FileReplacementDto> fileReplacementDto)
|
public async Task DownloadFiles(List<FileReplacementDto> fileReplacementDto)
|
||||||
{
|
{
|
||||||
|
IsDownloading = true;
|
||||||
|
|
||||||
foreach (var file in fileReplacementDto)
|
foreach (var file in fileReplacementDto)
|
||||||
{
|
{
|
||||||
var fileSize = await _fileHub!.InvokeAsync<long>("GetFileSize", file.Hash);
|
var fileSize = await _fileHub!.InvokeAsync<long>("GetFileSize", file.Hash);
|
||||||
@@ -149,6 +149,7 @@ namespace MareSynchronos.WebAPI
|
|||||||
}
|
}
|
||||||
|
|
||||||
CurrentDownloads.Clear();
|
CurrentDownloads.Clear();
|
||||||
|
IsDownloading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task GetCharacterData(Dictionary<string, int> hashedCharacterNames)
|
public async Task GetCharacterData(Dictionary<string, int> hashedCharacterNames)
|
||||||
|
|||||||
Reference in New Issue
Block a user