This commit is contained in:
rootdarkarchon
2023-05-01 01:33:35 +02:00
parent dc1e1c044a
commit 7495470dd5
14 changed files with 208 additions and 105 deletions

View File

@@ -169,7 +169,7 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase
private void DalamudUtil_FrameworkUpdate() private void DalamudUtil_FrameworkUpdate()
{ {
_cachedFrameAddresses = _playerRelatedPointers.Select(c => c.CurrentAddress).ToHashSet(); _cachedFrameAddresses = _playerRelatedPointers.Select(c => c.CurrentAddress().GetAwaiter().GetResult()).ToHashSet();
_cachedHandledPaths.Clear(); _cachedHandledPaths.Clear();
foreach (var item in TransientResources.Where(item => !_dalamudUtil.IsGameObjectPresent(item.Key)).Select(i => i.Key).ToList()) foreach (var item in TransientResources.Where(item => !_dalamudUtil.IsGameObjectPresent(item.Key)).Select(i => i.Key).ToList())
{ {

View File

@@ -12,7 +12,6 @@ using Microsoft.Extensions.Logging;
using MareSynchronos.PlayerData.Handlers; using MareSynchronos.PlayerData.Handlers;
using MareSynchronos.Services.Mediator; using MareSynchronos.Services.Mediator;
using MareSynchronos.Services; using MareSynchronos.Services;
using System;
namespace MareSynchronos.Interop; namespace MareSynchronos.Interop;

View File

@@ -9,6 +9,7 @@ using MareSynchronos.PlayerData.Handlers;
using MareSynchronos.Interop; using MareSynchronos.Interop;
using MareSynchronos.Services; using MareSynchronos.Services;
using MareSynchronos.Utils; using MareSynchronos.Utils;
using MareSynchronos.PlayerData.Factories;
namespace MareSynchronos.PlayerData.Export; namespace MareSynchronos.PlayerData.Export;
@@ -17,13 +18,13 @@ public class MareCharaFileManager
private readonly MareConfigService _configService; private readonly MareConfigService _configService;
private readonly DalamudUtilService _dalamudUtil; private readonly DalamudUtilService _dalamudUtil;
private readonly MareCharaFileDataFactory _factory; private readonly MareCharaFileDataFactory _factory;
private readonly Func<ObjectKind, Func<IntPtr>, bool, GameObjectHandler> _gameObjectHandlerFactory; private readonly GameObjectHandlerFactory _gameObjectHandlerFactory;
private readonly IpcManager _ipcManager; private readonly IpcManager _ipcManager;
private readonly ILogger<MareCharaFileManager> _logger; private readonly ILogger<MareCharaFileManager> _logger;
private readonly FileCacheManager _manager; private readonly FileCacheManager _manager;
private int _globalFileCounter = 0; private int _globalFileCounter = 0;
public MareCharaFileManager(ILogger<MareCharaFileManager> logger, Func<ObjectKind, Func<IntPtr>, bool, GameObjectHandler> gameObjectHandlerFactory, public MareCharaFileManager(ILogger<MareCharaFileManager> logger, GameObjectHandlerFactory gameObjectHandlerFactory,
FileCacheManager manager, IpcManager ipcManager, MareConfigService configService, DalamudUtilService dalamudUtil) FileCacheManager manager, IpcManager ipcManager, MareConfigService configService, DalamudUtilService dalamudUtil)
{ {
_factory = new(manager); _factory = new(manager);
@@ -68,7 +69,7 @@ public class MareCharaFileManager
await _ipcManager.PenumbraSetTemporaryMods(_logger, applicationId, charaTarget.Name.TextValue, charaTarget.ObjectTableIndex(), await _ipcManager.PenumbraSetTemporaryMods(_logger, applicationId, charaTarget.Name.TextValue, charaTarget.ObjectTableIndex(),
extractedFiles.Union(fileSwaps).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal), extractedFiles.Union(fileSwaps).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal),
LoadedCharaFile.CharaFileData.ManipulationData).ConfigureAwait(false); LoadedCharaFile.CharaFileData.ManipulationData).ConfigureAwait(false);
using GameObjectHandler tempHandler = _gameObjectHandlerFactory(ObjectKind.Player, () => charaTarget.Address, false); using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Player, () => charaTarget.Address, false).ConfigureAwait(false);
await _ipcManager.GlamourerApplyAll(_logger, tempHandler, LoadedCharaFile.CharaFileData.GlamourerData, applicationId, disposeCts.Token).ConfigureAwait(false); await _ipcManager.GlamourerApplyAll(_logger, tempHandler, LoadedCharaFile.CharaFileData.GlamourerData, applicationId, disposeCts.Token).ConfigureAwait(false);
_dalamudUtil.WaitWhileGposeCharacterIsDrawing(charaTarget.Address, 30000); _dalamudUtil.WaitWhileGposeCharacterIsDrawing(charaTarget.Address, 30000);
await _ipcManager.PenumbraRemoveTemporaryCollection(_logger, applicationId, charaTarget.Name.TextValue).ConfigureAwait(false); await _ipcManager.PenumbraRemoveTemporaryCollection(_logger, applicationId, charaTarget.Name.TextValue).ConfigureAwait(false);

View File

@@ -0,0 +1,46 @@
using MareSynchronos.API.Dto.User;
using MareSynchronos.FileCache;
using MareSynchronos.Interop;
using MareSynchronos.MareConfiguration;
using MareSynchronos.PlayerData.Pairs;
using MareSynchronos.Services;
using MareSynchronos.Services.Mediator;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace MareSynchronos.PlayerData.Factories;
public class CachedPlayerFactory
{
private readonly DalamudUtilService _dalamudUtilService;
private readonly FileCacheManager _fileCacheManager;
private readonly FileDownloadManagerFactory _fileDownloadManagerFactory;
private readonly GameObjectHandlerFactory _gameObjectHandlerFactory;
private readonly IHostApplicationLifetime _hostApplicationLifetime;
private readonly IpcManager _ipcManager;
private readonly ILoggerFactory _loggerFactory;
private readonly MareConfigService _mareConfigService;
private readonly MareMediator _mareMediator;
public CachedPlayerFactory(ILoggerFactory loggerFactory, GameObjectHandlerFactory gameObjectHandlerFactory, IpcManager ipcManager,
FileDownloadManagerFactory fileDownloadManagerFactory, MareConfigService mareConfigService, DalamudUtilService dalamudUtilService,
IHostApplicationLifetime hostApplicationLifetime, FileCacheManager fileCacheManager, MareMediator mareMediator)
{
_loggerFactory = loggerFactory;
_gameObjectHandlerFactory = gameObjectHandlerFactory;
_ipcManager = ipcManager;
_fileDownloadManagerFactory = fileDownloadManagerFactory;
_mareConfigService = mareConfigService;
_dalamudUtilService = dalamudUtilService;
_hostApplicationLifetime = hostApplicationLifetime;
_fileCacheManager = fileCacheManager;
_mareMediator = mareMediator;
}
public CachedPlayer Create(OnlineUserIdentDto onlineUserIdentDto)
{
return new CachedPlayer(_loggerFactory.CreateLogger<CachedPlayer>(), onlineUserIdentDto, _gameObjectHandlerFactory,
_ipcManager, _fileDownloadManagerFactory.Create(), _mareConfigService, _dalamudUtilService, _hostApplicationLifetime,
_fileCacheManager, _mareMediator);
}
}

View File

@@ -0,0 +1,28 @@
using MareSynchronos.FileCache;
using MareSynchronos.Services.Mediator;
using MareSynchronos.WebAPI.Files;
using Microsoft.Extensions.Logging;
namespace MareSynchronos.PlayerData.Factories;
public class FileDownloadManagerFactory
{
private readonly FileCacheManager _fileCacheManager;
private readonly FileTransferOrchestrator _fileTransferOrchestrator;
private readonly ILoggerFactory _loggerFactory;
private readonly MareMediator _mareMediator;
public FileDownloadManagerFactory(ILoggerFactory loggerFactory, MareMediator mareMediator, FileTransferOrchestrator fileTransferOrchestrator,
FileCacheManager fileCacheManager)
{
_loggerFactory = loggerFactory;
_mareMediator = mareMediator;
_fileTransferOrchestrator = fileTransferOrchestrator;
_fileCacheManager = fileCacheManager;
}
public FileDownloadManager Create()
{
return new FileDownloadManager(_loggerFactory.CreateLogger<FileDownloadManager>(), _mareMediator, _fileTransferOrchestrator, _fileCacheManager);
}
}

View File

@@ -0,0 +1,30 @@
using MareSynchronos.API.Data.Enum;
using MareSynchronos.PlayerData.Handlers;
using MareSynchronos.Services;
using MareSynchronos.Services.Mediator;
using Microsoft.Extensions.Logging;
namespace MareSynchronos.PlayerData.Factories;
public class GameObjectHandlerFactory
{
private readonly DalamudUtilService _dalamudUtilService;
private readonly ILoggerFactory _loggerFactory;
private readonly MareMediator _mareMediator;
private readonly PerformanceCollectorService _performanceCollectorService;
public GameObjectHandlerFactory(ILoggerFactory loggerFactory, PerformanceCollectorService performanceCollectorService, MareMediator mareMediator,
DalamudUtilService dalamudUtilService)
{
_loggerFactory = loggerFactory;
_performanceCollectorService = performanceCollectorService;
_mareMediator = mareMediator;
_dalamudUtilService = dalamudUtilService;
}
public async Task<GameObjectHandler> Create(ObjectKind objectKind, Func<nint> getAddressFunc, bool isWatched = false)
{
return await _dalamudUtilService.RunOnFrameworkThread(() => new GameObjectHandler(_loggerFactory.CreateLogger<GameObjectHandler>(),
_performanceCollectorService, _mareMediator, _dalamudUtilService, objectKind, getAddressFunc, isWatched)).ConfigureAwait(false);
}
}

View File

@@ -0,0 +1,28 @@
using MareSynchronos.PlayerData.Pairs;
using MareSynchronos.Services.Mediator;
using MareSynchronos.Services.ServerConfiguration;
using Microsoft.Extensions.Logging;
namespace MareSynchronos.PlayerData.Factories;
public class PairFactory
{
private readonly CachedPlayerFactory _cachedPlayerFactory;
private readonly ILoggerFactory _loggerFactory;
private readonly MareMediator _mareMediator;
private readonly ServerConfigurationManager _serverConfigurationManager;
public PairFactory(ILoggerFactory loggerFactory, CachedPlayerFactory cachedPlayerFactory,
MareMediator mareMediator, ServerConfigurationManager serverConfigurationManager)
{
_loggerFactory = loggerFactory;
_cachedPlayerFactory = cachedPlayerFactory;
_mareMediator = mareMediator;
_serverConfigurationManager = serverConfigurationManager;
}
public Pair Create()
{
return new Pair(_loggerFactory.CreateLogger<Pair>(), _cachedPlayerFactory, _mareMediator, _serverConfigurationManager);
}
}

View File

@@ -84,14 +84,23 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
public IntPtr Address { get; set; } public IntPtr Address { get; set; }
public unsafe Character* Character => (Character*)Address; public unsafe Character* Character => (Character*)Address;
public IntPtr CurrentAddress => _getAddress.Invoke();
public Lazy<Dalamud.Game.ClientState.Objects.Types.GameObject?> GameObjectLazy { get; private set; } public Lazy<Dalamud.Game.ClientState.Objects.Types.GameObject?> GameObjectLazy { get; private set; }
public string Name { get; private set; } public string Name { get; private set; }
public ObjectKind ObjectKind { get; } public ObjectKind ObjectKind { get; }
private byte[] CustomizeData { get; set; } = new byte[26]; private byte[] CustomizeData { get; set; } = new byte[26];
private IntPtr DrawObjectAddress { get; set; } private IntPtr DrawObjectAddress { get; set; }
private byte[] EquipSlotData { get; set; } = new byte[40]; private byte[] EquipSlotData { get; set; } = new byte[40];
public async Task<IntPtr> CurrentAddress()
{
return await _dalamudUtil.RunOnFrameworkThread(_getAddress.Invoke).ConfigureAwait(true);
}
public async Task<bool> IsBeingDrawnRunOnFramework() public async Task<bool> IsBeingDrawnRunOnFramework()
{ {
return await _dalamudUtil.RunOnFrameworkThread(() => return await _dalamudUtil.RunOnFrameworkThread(() =>
@@ -99,7 +108,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
nint curPtr = IntPtr.Zero; nint curPtr = IntPtr.Zero;
try try
{ {
curPtr = CurrentAddress; curPtr = CurrentAddress().GetAwaiter().GetResult();
if (curPtr == IntPtr.Zero) return true; if (curPtr == IntPtr.Zero) return true;
@@ -136,7 +145,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
{ {
if (_haltProcessing) return; if (_haltProcessing) return;
var curPtr = CurrentAddress; var curPtr = CurrentAddress().GetAwaiter().GetResult();
bool drawObjDiff = false; bool drawObjDiff = false;
try try
{ {

View File

@@ -6,6 +6,7 @@ using MareSynchronos.API.Dto.User;
using MareSynchronos.FileCache; using MareSynchronos.FileCache;
using MareSynchronos.Interop; using MareSynchronos.Interop;
using MareSynchronos.MareConfiguration; using MareSynchronos.MareConfiguration;
using MareSynchronos.PlayerData.Factories;
using MareSynchronos.PlayerData.Handlers; using MareSynchronos.PlayerData.Handlers;
using MareSynchronos.Services; using MareSynchronos.Services;
using MareSynchronos.Services.Mediator; using MareSynchronos.Services.Mediator;
@@ -24,7 +25,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
private readonly DalamudUtilService _dalamudUtil; private readonly DalamudUtilService _dalamudUtil;
private readonly FileDownloadManager _downloadManager; private readonly FileDownloadManager _downloadManager;
private readonly FileCacheManager _fileDbManager; private readonly FileCacheManager _fileDbManager;
private readonly Func<ObjectKind, Func<nint>, bool, GameObjectHandler> _gameObjectHandlerFactory; private readonly GameObjectHandlerFactory _gameObjectHandlerFactory;
private readonly IpcManager _ipcManager; private readonly IpcManager _ipcManager;
private readonly IHostApplicationLifetime _lifetime; private readonly IHostApplicationLifetime _lifetime;
private readonly OptionalPluginWarning _pluginWarnings; private readonly OptionalPluginWarning _pluginWarnings;
@@ -40,7 +41,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
private CancellationTokenSource _redrawCts = new(); private CancellationTokenSource _redrawCts = new();
public CachedPlayer(ILogger<CachedPlayer> logger, OnlineUserIdentDto onlineUser, public CachedPlayer(ILogger<CachedPlayer> logger, OnlineUserIdentDto onlineUser,
Func<ObjectKind, Func<nint>, bool, GameObjectHandler> gameObjectHandlerFactory, GameObjectHandlerFactory gameObjectHandlerFactory,
IpcManager ipcManager, FileDownloadManager transferManager, MareConfigService mareConfigService, IpcManager ipcManager, FileDownloadManager transferManager, MareConfigService mareConfigService,
DalamudUtilService dalamudUtil, IHostApplicationLifetime lifetime, FileCacheManager fileDbManager, MareMediator mediator) : base(logger, mediator) DalamudUtilService dalamudUtil, IHostApplicationLifetime lifetime, FileCacheManager fileDbManager, MareMediator mediator) : base(logger, mediator)
{ {
@@ -119,18 +120,6 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
_cachedData = characterData; _cachedData = characterData;
} }
public bool CheckExistence()
{
if (PlayerName == null || _charaHandler == null
|| !string.Equals(PlayerName, _charaHandler.Name, StringComparison.Ordinal)
|| _charaHandler.CurrentAddress == IntPtr.Zero)
{
return false;
}
return true;
}
public override string ToString() public override string ToString()
{ {
return OnlineUser == null return OnlineUser == null
@@ -200,6 +189,14 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
} }
} }
private static void CheckForNameAndThrow(GameObjectHandler handler, string name)
{
if (!string.Equals(handler.Name, name, StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException("Player name not equal to requested name, pointer invalid");
}
}
private async Task ApplyBaseData(Guid applicationId, Dictionary<string, string> moddedPaths, string manipulationData, CancellationToken token) private async Task ApplyBaseData(Guid applicationId, Dictionary<string, string> moddedPaths, string manipulationData, CancellationToken token)
{ {
await _ipcManager.PenumbraRemoveTemporaryCollection(Logger, applicationId, PlayerName!).ConfigureAwait(false); await _ipcManager.PenumbraRemoveTemporaryCollection(Logger, applicationId, PlayerName!).ConfigureAwait(false);
@@ -217,9 +214,9 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
var handler = changes.Key switch var handler = changes.Key switch
{ {
ObjectKind.Player => _charaHandler!, ObjectKind.Player => _charaHandler!,
ObjectKind.Companion => _gameObjectHandlerFactory(changes.Key, () => _dalamudUtil.GetCompanion(ptr).GetAwaiter().GetResult(), false), ObjectKind.Companion => await _gameObjectHandlerFactory.Create(changes.Key, () => _dalamudUtil.GetCompanion(ptr).GetAwaiter().GetResult(), false).ConfigureAwait(false),
ObjectKind.MinionOrMount => _gameObjectHandlerFactory(changes.Key, () => _dalamudUtil.GetMinionOrMount(ptr), false), ObjectKind.MinionOrMount => await _gameObjectHandlerFactory.Create(changes.Key, () => _dalamudUtil.GetMinionOrMount(ptr).GetAwaiter().GetResult(), false).ConfigureAwait(false),
ObjectKind.Pet => _gameObjectHandlerFactory(changes.Key, () => _dalamudUtil.GetPet(ptr).GetAwaiter().GetResult(), false), ObjectKind.Pet => await _gameObjectHandlerFactory.Create(changes.Key, () => _dalamudUtil.GetPet(ptr).GetAwaiter().GetResult(), false).ConfigureAwait(false),
_ => throw new NotSupportedException("ObjectKind not supported: " + changes.Key) _ => throw new NotSupportedException("ObjectKind not supported: " + changes.Key)
}; };
@@ -274,14 +271,6 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
} }
} }
private void CheckForNameAndThrow(GameObjectHandler handler, string name)
{
if (!string.Equals(handler.Name, name, StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException("Player name not equal to requested name, pointer invalid");
}
}
private Dictionary<ObjectKind, HashSet<PlayerChanges>> CheckUpdatedData(CharacterData oldData, CharacterData newData, bool forced) private Dictionary<ObjectKind, HashSet<PlayerChanges>> CheckUpdatedData(CharacterData oldData, CharacterData newData, bool forced)
{ {
var charaDataToUpdate = new Dictionary<ObjectKind, HashSet<PlayerChanges>>(); var charaDataToUpdate = new Dictionary<ObjectKind, HashSet<PlayerChanges>>();
@@ -520,7 +509,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
private void Initialize(string name) private void Initialize(string name)
{ {
PlayerName = name; PlayerName = name;
_charaHandler = _gameObjectHandlerFactory(ObjectKind.Player, () => _dalamudUtil.GetPlayerCharacterFromObjectTableByIdent(OnlineUser.Ident), false); _charaHandler = _gameObjectHandlerFactory.Create(ObjectKind.Player, () => _dalamudUtil.GetPlayerCharacterFromObjectTableByIdent(OnlineUser.Ident), false).GetAwaiter().GetResult();
_originalGlamourerData = _ipcManager.GlamourerGetCharacterCustomization(PlayerCharacter).ConfigureAwait(false).GetAwaiter().GetResult(); _originalGlamourerData = _ipcManager.GlamourerGetCharacterCustomization(PlayerCharacter).ConfigureAwait(false).GetAwaiter().GetResult();
_lastGlamourerData = _originalGlamourerData; _lastGlamourerData = _originalGlamourerData;
@@ -602,7 +591,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
if (objectKind == ObjectKind.Player) if (objectKind == ObjectKind.Player)
{ {
using GameObjectHandler tempHandler = _gameObjectHandlerFactory(ObjectKind.Player, () => address, false); using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Player, () => address, false).ConfigureAwait(false);
CheckForNameAndThrow(tempHandler, name); CheckForNameAndThrow(tempHandler, name);
Logger.LogDebug("[{applicationId}] Restoring Customization and Equipment for {alias}/{name}: {data}", applicationId, OnlineUser.User.AliasOrUID, name, _originalGlamourerData); Logger.LogDebug("[{applicationId}] Restoring Customization and Equipment for {alias}/{name}: {data}", applicationId, OnlineUser.User.AliasOrUID, name, _originalGlamourerData);
await _ipcManager.GlamourerApplyCustomizationAndEquipment(Logger, tempHandler, _originalGlamourerData, _lastGlamourerData, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false); await _ipcManager.GlamourerApplyCustomizationAndEquipment(Logger, tempHandler, _originalGlamourerData, _lastGlamourerData, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false);
@@ -621,10 +610,10 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
} }
else if (objectKind == ObjectKind.MinionOrMount) else if (objectKind == ObjectKind.MinionOrMount)
{ {
var minionOrMount = _dalamudUtil.GetMinionOrMount(address); var minionOrMount = await _dalamudUtil.GetMinionOrMount(address).ConfigureAwait(false);
if (minionOrMount != IntPtr.Zero) if (minionOrMount != IntPtr.Zero)
{ {
using GameObjectHandler tempHandler = _gameObjectHandlerFactory(ObjectKind.MinionOrMount, () => minionOrMount, false); using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.MinionOrMount, () => minionOrMount, false).ConfigureAwait(false);
await _ipcManager.PenumbraRedraw(Logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false); await _ipcManager.PenumbraRedraw(Logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false);
} }
} }
@@ -633,7 +622,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
var pet = await _dalamudUtil.GetPet(address).ConfigureAwait(false); var pet = await _dalamudUtil.GetPet(address).ConfigureAwait(false);
if (pet != IntPtr.Zero) if (pet != IntPtr.Zero)
{ {
using GameObjectHandler tempHandler = _gameObjectHandlerFactory(ObjectKind.Pet, () => pet, false); using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Pet, () => pet, false).ConfigureAwait(false);
await _ipcManager.PenumbraRedraw(Logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false); await _ipcManager.PenumbraRedraw(Logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false);
} }
} }
@@ -642,7 +631,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
var companion = await _dalamudUtil.GetCompanion(address).ConfigureAwait(false); var companion = await _dalamudUtil.GetCompanion(address).ConfigureAwait(false);
if (companion != IntPtr.Zero) if (companion != IntPtr.Zero)
{ {
using GameObjectHandler tempHandler = _gameObjectHandlerFactory(ObjectKind.Pet, () => companion, false); using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Pet, () => companion, false).ConfigureAwait(false);
await _ipcManager.PenumbraRedraw(Logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false); await _ipcManager.PenumbraRedraw(Logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false);
} }
} }
@@ -653,7 +642,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
Stopwatch st = Stopwatch.StartNew(); Stopwatch st = Stopwatch.StartNew();
List<FileReplacementData> missingFiles = new(); List<FileReplacementData> missingFiles = new();
moddedDictionary = new Dictionary<string, string>(StringComparer.Ordinal); moddedDictionary = new Dictionary<string, string>(StringComparer.Ordinal);
ConcurrentDictionary<string, string> outputDict = new ConcurrentDictionary<string, string>(StringComparer.Ordinal); ConcurrentDictionary<string, string> outputDict = new(StringComparer.Ordinal);
try try
{ {
var replacementList = charaData.FileReplacements.SelectMany(k => k.Value.Where(v => string.IsNullOrEmpty(v.FileSwapPath))).ToList(); var replacementList = charaData.FileReplacements.SelectMany(k => k.Value.Where(v => string.IsNullOrEmpty(v.FileSwapPath))).ToList();

View File

@@ -4,6 +4,7 @@ using MareSynchronos.API.Data.Comparer;
using MareSynchronos.API.Data.Extensions; using MareSynchronos.API.Data.Extensions;
using MareSynchronos.API.Dto.Group; using MareSynchronos.API.Dto.Group;
using MareSynchronos.API.Dto.User; using MareSynchronos.API.Dto.User;
using MareSynchronos.PlayerData.Factories;
using MareSynchronos.Services.Mediator; using MareSynchronos.Services.Mediator;
using MareSynchronos.Services.ServerConfiguration; using MareSynchronos.Services.ServerConfiguration;
using MareSynchronos.Utils; using MareSynchronos.Utils;
@@ -13,14 +14,14 @@ namespace MareSynchronos.PlayerData.Pairs;
public class Pair public class Pair
{ {
private readonly Func<OnlineUserIdentDto, CachedPlayer> _cachedPlayerFactory; private readonly CachedPlayerFactory _cachedPlayerFactory;
private readonly SemaphoreSlim _creationSemaphore = new(1); private readonly SemaphoreSlim _creationSemaphore = new(1);
private readonly ILogger<Pair> _logger; private readonly ILogger<Pair> _logger;
private readonly MareMediator _mediator; private readonly MareMediator _mediator;
private readonly ServerConfigurationManager _serverConfigurationManager; private readonly ServerConfigurationManager _serverConfigurationManager;
private OnlineUserIdentDto? _onlineUserIdentDto = null; private OnlineUserIdentDto? _onlineUserIdentDto = null;
public Pair(ILogger<Pair> logger, Func<OnlineUserIdentDto, CachedPlayer> cachedPlayerFactory, public Pair(ILogger<Pair> logger, CachedPlayerFactory cachedPlayerFactory,
MareMediator mediator, ServerConfigurationManager serverConfigurationManager) MareMediator mediator, ServerConfigurationManager serverConfigurationManager)
{ {
_logger = logger; _logger = logger;
@@ -29,7 +30,6 @@ public class Pair
_serverConfigurationManager = serverConfigurationManager; _serverConfigurationManager = serverConfigurationManager;
} }
public bool CachedPlayerExists => CachedPlayer?.CheckExistence() ?? false;
public Dictionary<GroupFullInfoDto, GroupPairFullInfoDto> GroupPair { get; set; } = new(GroupDtoComparer.Instance); public Dictionary<GroupFullInfoDto, GroupPairFullInfoDto> GroupPair { get; set; } = new(GroupDtoComparer.Instance);
public bool HasCachedPlayer => CachedPlayer != null && !string.IsNullOrEmpty(CachedPlayer.PlayerName) && _onlineUserIdentDto != null; public bool HasCachedPlayer => CachedPlayer != null && !string.IsNullOrEmpty(CachedPlayer.PlayerName) && _onlineUserIdentDto != null;
public bool IsOnline => CachedPlayer != null; public bool IsOnline => CachedPlayer != null;
@@ -108,7 +108,7 @@ public class Pair
} }
CachedPlayer?.Dispose(); CachedPlayer?.Dispose();
CachedPlayer = _cachedPlayerFactory(_onlineUserIdentDto!); CachedPlayer = _cachedPlayerFactory.Create(_onlineUserIdentDto!);
} }
finally finally
{ {

View File

@@ -6,6 +6,7 @@ using MareSynchronos.API.Data.Extensions;
using MareSynchronos.API.Dto.Group; using MareSynchronos.API.Dto.Group;
using MareSynchronos.API.Dto.User; using MareSynchronos.API.Dto.User;
using MareSynchronos.MareConfiguration; using MareSynchronos.MareConfiguration;
using MareSynchronos.PlayerData.Factories;
using MareSynchronos.Services.Mediator; using MareSynchronos.Services.Mediator;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Collections.Concurrent; using System.Collections.Concurrent;
@@ -18,11 +19,11 @@ public sealed class PairManager : DisposableMediatorSubscriberBase
private readonly ConcurrentDictionary<GroupData, GroupFullInfoDto> _allGroups = new(GroupDataComparer.Instance); private readonly ConcurrentDictionary<GroupData, GroupFullInfoDto> _allGroups = new(GroupDataComparer.Instance);
private readonly MareConfigService _configurationService; private readonly MareConfigService _configurationService;
private readonly DalamudContextMenu _dalamudContextMenu; private readonly DalamudContextMenu _dalamudContextMenu;
private readonly Func<Pair> _pairFactory; private readonly PairFactory _pairFactory;
private Lazy<List<Pair>> _directPairsInternal; private Lazy<List<Pair>> _directPairsInternal;
private Lazy<Dictionary<GroupFullInfoDto, List<Pair>>> _groupPairsInternal; private Lazy<Dictionary<GroupFullInfoDto, List<Pair>>> _groupPairsInternal;
public PairManager(ILogger<PairManager> logger, Func<Pair> pairFactory, public PairManager(ILogger<PairManager> logger, PairFactory pairFactory,
MareConfigService configurationService, MareMediator mediator, MareConfigService configurationService, MareMediator mediator,
DalamudContextMenu dalamudContextMenu) : base(logger, mediator) DalamudContextMenu dalamudContextMenu) : base(logger, mediator)
{ {
@@ -51,7 +52,7 @@ public sealed class PairManager : DisposableMediatorSubscriberBase
public void AddGroupPair(GroupPairFullInfoDto dto) public void AddGroupPair(GroupPairFullInfoDto dto)
{ {
if (!_allClientPairs.ContainsKey(dto.User)) _allClientPairs[dto.User] = _pairFactory.Invoke(); if (!_allClientPairs.ContainsKey(dto.User)) _allClientPairs[dto.User] = _pairFactory.Create();
var group = _allGroups[dto.Group]; var group = _allGroups[dto.Group];
_allClientPairs[dto.User].GroupPair[group] = dto; _allClientPairs[dto.User].GroupPair[group] = dto;
@@ -62,7 +63,7 @@ public sealed class PairManager : DisposableMediatorSubscriberBase
{ {
if (!_allClientPairs.ContainsKey(dto.User)) if (!_allClientPairs.ContainsKey(dto.User))
{ {
_allClientPairs[dto.User] = _pairFactory.Invoke(); _allClientPairs[dto.User] = _pairFactory.Create();
} }
else else
{ {

View File

@@ -20,7 +20,7 @@ public sealed class CacheCreationService : DisposableMediatorSubscriberBase
private CancellationTokenSource _honorificCts = new(); private CancellationTokenSource _honorificCts = new();
private CancellationTokenSource _palettePlusCts = new(); private CancellationTokenSource _palettePlusCts = new();
public CacheCreationService(ILogger<CacheCreationService> logger, MareMediator mediator, Func<ObjectKind, Func<IntPtr>, bool, GameObjectHandler> gameObjectHandlerFactory, public CacheCreationService(ILogger<CacheCreationService> logger, MareMediator mediator, GameObjectHandlerFactory gameObjectHandlerFactory,
PlayerDataFactory characterDataFactory, DalamudUtilService dalamudUtil) : base(logger, mediator) PlayerDataFactory characterDataFactory, DalamudUtilService dalamudUtil) : base(logger, mediator)
{ {
_characterDataFactory = characterDataFactory; _characterDataFactory = characterDataFactory;
@@ -76,14 +76,14 @@ public sealed class CacheCreationService : DisposableMediatorSubscriberBase
await AddPlayerCacheToCreate().ConfigureAwait(false); await AddPlayerCacheToCreate().ConfigureAwait(false);
}); });
_playerRelatedObjects[ObjectKind.Player] = _playerRelatedObjects[ObjectKind.Player] = gameObjectHandlerFactory.Create(ObjectKind.Player, () => dalamudUtil.PlayerPointer, true)
gameObjectHandlerFactory(ObjectKind.Player, () => dalamudUtil.PlayerPointer, true); .GetAwaiter().GetResult();
_playerRelatedObjects[ObjectKind.MinionOrMount] = _playerRelatedObjects[ObjectKind.MinionOrMount] = gameObjectHandlerFactory.Create(ObjectKind.MinionOrMount, () => dalamudUtil.GetMinionOrMount().GetAwaiter().GetResult(), true)
gameObjectHandlerFactory(ObjectKind.MinionOrMount, () => dalamudUtil.GetMinionOrMount(), true); .GetAwaiter().GetResult();
_playerRelatedObjects[ObjectKind.Pet] = _playerRelatedObjects[ObjectKind.Pet] = gameObjectHandlerFactory.Create(ObjectKind.Pet, () => dalamudUtil.GetPet().GetAwaiter().GetResult(), true)
gameObjectHandlerFactory(ObjectKind.Pet, () => dalamudUtil.GetPet().GetAwaiter().GetResult(), true); .GetAwaiter().GetResult();
_playerRelatedObjects[ObjectKind.Companion] = _playerRelatedObjects[ObjectKind.Companion] = gameObjectHandlerFactory.Create(ObjectKind.Companion, () => dalamudUtil.GetCompanion().GetAwaiter().GetResult(), true)
gameObjectHandlerFactory(ObjectKind.Companion, () => dalamudUtil.GetCompanion().GetAwaiter().GetResult(), true); .GetAwaiter().GetResult();
} }
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)

View File

@@ -9,14 +9,11 @@ using Dalamud.Game.Gui;
using Dalamud.Interface.ImGuiFileDialog; using Dalamud.Interface.ImGuiFileDialog;
using Dalamud.Interface.Windowing; using Dalamud.Interface.Windowing;
using Dalamud.Plugin; using Dalamud.Plugin;
using MareSynchronos.API.Data.Enum;
using MareSynchronos.API.Dto.User;
using MareSynchronos.FileCache; using MareSynchronos.FileCache;
using MareSynchronos.Interop; using MareSynchronos.Interop;
using MareSynchronos.MareConfiguration; using MareSynchronos.MareConfiguration;
using MareSynchronos.PlayerData.Export; using MareSynchronos.PlayerData.Export;
using MareSynchronos.PlayerData.Factories; using MareSynchronos.PlayerData.Factories;
using MareSynchronos.PlayerData.Handlers;
using MareSynchronos.PlayerData.Pairs; using MareSynchronos.PlayerData.Pairs;
using MareSynchronos.PlayerData.Services; using MareSynchronos.PlayerData.Services;
using MareSynchronos.Services; using MareSynchronos.Services;
@@ -70,6 +67,10 @@ public sealed class Plugin : IDalamudPlugin
collection.AddSingleton<MarePlugin>(); collection.AddSingleton<MarePlugin>();
collection.AddSingleton<MareProfileManager>(); collection.AddSingleton<MareProfileManager>();
collection.AddSingleton<UidDisplayHandler>(); collection.AddSingleton<UidDisplayHandler>();
collection.AddSingleton<GameObjectHandlerFactory>();
collection.AddSingleton<FileDownloadManagerFactory>();
collection.AddSingleton<CachedPlayerFactory>();
collection.AddSingleton<PairFactory>();
collection.AddSingleton((s) => new DalamudUtilService(s.GetRequiredService<ILogger<DalamudUtilService>>(), collection.AddSingleton((s) => new DalamudUtilService(s.GetRequiredService<ILogger<DalamudUtilService>>(),
clientState, objectTable, framework, gameGui, condition, gameData, clientState, objectTable, framework, gameGui, condition, gameData,
s.GetRequiredService<MareMediator>(), s.GetRequiredService<PerformanceCollectorService>())); s.GetRequiredService<MareMediator>(), s.GetRequiredService<PerformanceCollectorService>()));
@@ -84,37 +85,6 @@ public sealed class Plugin : IDalamudPlugin
collection.AddSingleton((s) => new ConfigurationMigrator(s.GetRequiredService<ILogger<ConfigurationMigrator>>(), pluginInterface)); collection.AddSingleton((s) => new ConfigurationMigrator(s.GetRequiredService<ILogger<ConfigurationMigrator>>(), pluginInterface));
// func factory method singletons // func factory method singletons
collection.AddSingleton(s =>
new Func<ObjectKind, Func<nint>, bool, GameObjectHandler>((o, f, b)
=> new GameObjectHandler(s.GetRequiredService<ILogger<GameObjectHandler>>(),
s.GetRequiredService<PerformanceCollectorService>(),
s.GetRequiredService<MareMediator>(),
s.GetRequiredService<DalamudUtilService>(),
o, f, b)));
collection.AddSingleton(s =>
new Func<OnlineUserIdentDto, CachedPlayer>((o)
=> new CachedPlayer(s.GetRequiredService<ILogger<CachedPlayer>>(),
o,
s.GetRequiredService<Func<ObjectKind, Func<nint>, bool, GameObjectHandler>>(),
s.GetRequiredService<IpcManager>(),
s.GetRequiredService<Func<FileDownloadManager>>().Invoke(),
s.GetRequiredService<MareConfigService>(),
s.GetRequiredService<DalamudUtilService>(),
s.GetRequiredService<IHostApplicationLifetime>(),
s.GetRequiredService<FileCacheManager>(),
s.GetRequiredService<MareMediator>())));
collection.AddSingleton(s =>
new Func<Pair>(()
=> new Pair(s.GetRequiredService<ILogger<Pair>>(),
s.GetRequiredService<Func<OnlineUserIdentDto, CachedPlayer>>(),
s.GetRequiredService<MareMediator>(),
s.GetRequiredService<ServerConfigurationManager>())));
collection.AddSingleton(s =>
new Func<FileDownloadManager>(()
=> new FileDownloadManager(s.GetRequiredService<ILogger<FileDownloadManager>>(),
s.GetRequiredService<MareMediator>(),
s.GetRequiredService<FileTransferOrchestrator>(),
s.GetRequiredService<FileCacheManager>())));
collection.AddSingleton(s => collection.AddSingleton(s =>
new Func<Pair, StandaloneProfileUi>((pair) => new Func<Pair, StandaloneProfileUi>((pair) =>
new StandaloneProfileUi(s.GetRequiredService<ILogger<StandaloneProfileUi>>(), new StandaloneProfileUi(s.GetRequiredService<ILogger<StandaloneProfileUi>>(),

View File

@@ -12,13 +12,13 @@ using MareSynchronos.Utils;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices;
using GameObject = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject; using GameObject = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject;
namespace MareSynchronos.Services; namespace MareSynchronos.Services;
public class DalamudUtilService : IHostedService public class DalamudUtilService : IHostedService
{ {
private readonly List<uint> _classJobIdsIgnoredForPets = new() { 30 };
private readonly ClientState _clientState; private readonly ClientState _clientState;
private readonly Condition _condition; private readonly Condition _condition;
private readonly Framework _framework; private readonly Framework _framework;
@@ -27,7 +27,6 @@ public class DalamudUtilService : IHostedService
private readonly MareMediator _mediator; private readonly MareMediator _mediator;
private readonly ObjectTable _objectTable; private readonly ObjectTable _objectTable;
private readonly PerformanceCollectorService _performanceCollector; private readonly PerformanceCollectorService _performanceCollector;
private readonly List<uint> ClassJobIdsIgnoredForPets = new() { 30 };
private uint? _classJobId = 0; private uint? _classJobId = 0;
private DateTime _delayedFrameworkUpdateCheck = DateTime.Now; private DateTime _delayedFrameworkUpdateCheck = DateTime.Now;
private Dictionary<string, (string Name, nint Address)> _playerCharas = new(StringComparer.Ordinal); private Dictionary<string, (string Name, nint Address)> _playerCharas = new(StringComparer.Ordinal);
@@ -94,11 +93,9 @@ public class DalamudUtilService : IHostedService
return await RunOnFrameworkThread(() => GetCompanionInternal(playerPointer)).ConfigureAwait(false); return await RunOnFrameworkThread(() => GetCompanionInternal(playerPointer)).ConfigureAwait(false);
} }
public unsafe IntPtr GetMinionOrMount(IntPtr? playerPointer = null) public async Task<IntPtr> GetMinionOrMount(IntPtr? playerPointer = null)
{ {
playerPointer ??= PlayerPointer; return await RunOnFrameworkThread(() => GetMinionOrMountInternal(playerPointer)).ConfigureAwait(false);
if (playerPointer == IntPtr.Zero) return IntPtr.Zero;
return _objectTable.GetObjectAddress(((GameObject*)playerPointer)->ObjectIndex + 1);
} }
public async Task<IntPtr> GetPet(IntPtr? playerPointer = null) public async Task<IntPtr> GetPet(IntPtr? playerPointer = null)
@@ -117,8 +114,7 @@ public class DalamudUtilService : IHostedService
return _objectTable.Any(f => f.Address == key); return _objectTable.Any(f => f.Address == key);
} }
public async Task RunOnFrameworkThread(Action act, [CallerMemberName] string callerMember = "", public async Task RunOnFrameworkThread(Action act)
[CallerFilePath] string callerFilePath = "", [CallerLineNumber] int lineNumber = 0)
{ {
if (!_framework.IsInFrameworkUpdateThread) if (!_framework.IsInFrameworkUpdateThread)
{ {
@@ -133,8 +129,7 @@ public class DalamudUtilService : IHostedService
act(); act();
} }
public async Task<T> RunOnFrameworkThread<T>(Func<T> func, [CallerMemberName] string callerMember = "", public async Task<T> RunOnFrameworkThread<T>(Func<T> func)
[CallerFilePath] string callerFilePath = "", [CallerLineNumber] int lineNumber = 0)
{ {
if (!_framework.IsInFrameworkUpdateThread) if (!_framework.IsInFrameworkUpdateThread)
{ {
@@ -146,8 +141,8 @@ public class DalamudUtilService : IHostedService
} }
return result; return result;
} }
else
return func.Invoke(); return func.Invoke();
} }
public Task StartAsync(CancellationToken cancellationToken) public Task StartAsync(CancellationToken cancellationToken)
@@ -171,7 +166,7 @@ public class DalamudUtilService : IHostedService
public async Task WaitWhileCharacterIsDrawing(ILogger logger, GameObjectHandler handler, Guid redrawId, int timeOut = 5000, CancellationToken? ct = null) public async Task WaitWhileCharacterIsDrawing(ILogger logger, GameObjectHandler handler, Guid redrawId, int timeOut = 5000, CancellationToken? ct = null)
{ {
if (!_clientState.IsLoggedIn || handler.CurrentAddress == IntPtr.Zero) return; if (!_clientState.IsLoggedIn || handler.Address == IntPtr.Zero) return;
logger.LogTrace("[{redrawId}] Starting wait for {handler} to draw", redrawId, handler); logger.LogTrace("[{redrawId}] Starting wait for {handler} to draw", redrawId, handler);
@@ -337,9 +332,16 @@ public class DalamudUtilService : IHostedService
return (IntPtr)mgr->LookupBuddyByOwnerObject((BattleChara*)playerPointer); return (IntPtr)mgr->LookupBuddyByOwnerObject((BattleChara*)playerPointer);
} }
private unsafe IntPtr GetMinionOrMountInternal(IntPtr? playerPointer = null)
{
playerPointer ??= PlayerPointer;
if (playerPointer == IntPtr.Zero) return IntPtr.Zero;
return _objectTable.GetObjectAddress(((GameObject*)playerPointer)->ObjectIndex + 1);
}
private unsafe IntPtr GetPetInternal(IntPtr? playerPointer = null) private unsafe IntPtr GetPetInternal(IntPtr? playerPointer = null)
{ {
if (ClassJobIdsIgnoredForPets.Contains(_classJobId ?? 0)) return IntPtr.Zero; if (_classJobIdsIgnoredForPets.Contains(_classJobId ?? 0)) return IntPtr.Zero;
var mgr = CharacterManager.Instance(); var mgr = CharacterManager.Instance();
playerPointer ??= PlayerPointer; playerPointer ??= PlayerPointer;
if (playerPointer == IntPtr.Zero || (IntPtr)mgr == IntPtr.Zero) return IntPtr.Zero; if (playerPointer == IntPtr.Zero || (IntPtr)mgr == IntPtr.Zero) return IntPtr.Zero;