fix c+ bullshit

This commit is contained in:
Stanley Dimant
2024-06-02 01:17:53 +02:00
parent c4e3e1cf93
commit 7f0f122b75
3 changed files with 474 additions and 474 deletions

View File

@@ -52,7 +52,7 @@ public sealed class IpcCallerCustomize : IIpcCaller
if (gameObj is Character c) if (gameObj is Character c)
{ {
_logger.LogTrace("CustomizePlus reverting for {chara}", c.Address.ToString("X")); _logger.LogTrace("CustomizePlus reverting for {chara}", c.Address.ToString("X"));
_customizePlusRevertCharacter!.InvokeAction(c); _customizePlusRevertCharacter!.InvokeFunc(c);
} }
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
@@ -69,7 +69,7 @@ public sealed class IpcCallerCustomize : IIpcCaller
_logger.LogTrace("CustomizePlus applying for {chara}", c.Address.ToString("X")); _logger.LogTrace("CustomizePlus applying for {chara}", c.Address.ToString("X"));
if (scale.IsNullOrEmpty()) if (scale.IsNullOrEmpty())
{ {
_customizePlusRevertCharacter!.InvokeAction(c); _customizePlusRevertCharacter!.InvokeFunc(c);
return null; return null;
} }
else else

View File

@@ -1,66 +1,66 @@
using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Interface.Internal.Notifications; using Dalamud.Interface.Internal.Notifications;
using Dalamud.Plugin; using Dalamud.Plugin;
using Glamourer.Api.Helpers; using Glamourer.Api.Helpers;
using Glamourer.Api.IpcSubscribers; using Glamourer.Api.IpcSubscribers;
using MareSynchronos.PlayerData.Handlers; using MareSynchronos.PlayerData.Handlers;
using MareSynchronos.Services; using MareSynchronos.Services;
using MareSynchronos.Services.Mediator; using MareSynchronos.Services.Mediator;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace MareSynchronos.Interop.Ipc; namespace MareSynchronos.Interop.Ipc;
public sealed class IpcCallerGlamourer : IIpcCaller public sealed class IpcCallerGlamourer : IIpcCaller
{ {
private readonly ILogger<IpcCallerGlamourer> _logger; private readonly ILogger<IpcCallerGlamourer> _logger;
private readonly DalamudPluginInterface _pi; private readonly DalamudPluginInterface _pi;
private readonly DalamudUtilService _dalamudUtil; private readonly DalamudUtilService _dalamudUtil;
private readonly MareMediator _mareMediator; private readonly MareMediator _mareMediator;
private readonly RedrawManager _redrawManager; private readonly RedrawManager _redrawManager;
private readonly ApiVersion _glamourerApiVersions; private readonly ApiVersion _glamourerApiVersions;
private readonly ApplyState? _glamourerApplyAll; private readonly ApplyState? _glamourerApplyAll;
private readonly GetStateBase64? _glamourerGetAllCustomization; private readonly GetStateBase64? _glamourerGetAllCustomization;
private readonly RevertState _glamourerRevert; private readonly RevertState _glamourerRevert;
private readonly RevertStateName _glamourerRevertByName; private readonly RevertStateName _glamourerRevertByName;
private readonly UnlockState _glamourerUnlock; private readonly UnlockState _glamourerUnlock;
private readonly UnlockStateName _glamourerUnlockByName; private readonly UnlockStateName _glamourerUnlockByName;
private readonly EventSubscriber<nint>? _glamourerStateChanged; private readonly EventSubscriber<nint>? _glamourerStateChanged;
private bool _shownGlamourerUnavailable = false; private bool _shownGlamourerUnavailable = false;
private readonly uint LockCode = 0x6D617265; private readonly uint LockCode = 0x6D617265;
public IpcCallerGlamourer(ILogger<IpcCallerGlamourer> logger, DalamudPluginInterface pi, DalamudUtilService dalamudUtil, MareMediator mareMediator, public IpcCallerGlamourer(ILogger<IpcCallerGlamourer> logger, DalamudPluginInterface pi, DalamudUtilService dalamudUtil, MareMediator mareMediator,
RedrawManager redrawManager) RedrawManager redrawManager)
{ {
_glamourerApiVersions = new ApiVersion(pi); _glamourerApiVersions = new ApiVersion(pi);
_glamourerGetAllCustomization = new GetStateBase64(pi); _glamourerGetAllCustomization = new GetStateBase64(pi);
_glamourerApplyAll = new ApplyState(pi); _glamourerApplyAll = new ApplyState(pi);
_glamourerRevert = new RevertState(pi); _glamourerRevert = new RevertState(pi);
_glamourerRevertByName = new RevertStateName(pi); _glamourerRevertByName = new RevertStateName(pi);
_glamourerUnlock = new UnlockState(pi); _glamourerUnlock = new UnlockState(pi);
_glamourerUnlockByName = new UnlockStateName(pi); _glamourerUnlockByName = new UnlockStateName(pi);
_logger = logger; _logger = logger;
_pi = pi; _pi = pi;
_dalamudUtil = dalamudUtil; _dalamudUtil = dalamudUtil;
_mareMediator = mareMediator; _mareMediator = mareMediator;
_redrawManager = redrawManager; _redrawManager = redrawManager;
CheckAPI(); CheckAPI();
_glamourerStateChanged = StateChanged.Subscriber(pi, GlamourerChanged); _glamourerStateChanged = StateChanged.Subscriber(pi, GlamourerChanged);
_glamourerStateChanged.Enable(); _glamourerStateChanged.Enable();
} }
public bool APIAvailable { get; private set; } public bool APIAvailable { get; private set; }
public void CheckAPI() public void CheckAPI()
{ {
bool apiAvailable = false; bool apiAvailable = false;
try try
{ {
bool versionValid = (_pi.InstalledPlugins bool versionValid = (_pi.InstalledPlugins
.FirstOrDefault(p => string.Equals(p.InternalName, "Glamourer", StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(p => string.Equals(p.InternalName, "Glamourer", StringComparison.OrdinalIgnoreCase))
?.Version ?? new Version(0, 0, 0, 0)) >= new Version(1, 2, 3, 0); ?.Version ?? new Version(0, 0, 0, 0)) >= new Version(1, 2, 3, 0);
try try
{ {
@@ -73,123 +73,123 @@ public sealed class IpcCallerGlamourer : IIpcCaller
catch catch
{ {
// ignore // ignore
} }
_shownGlamourerUnavailable = _shownGlamourerUnavailable && !apiAvailable; _shownGlamourerUnavailable = _shownGlamourerUnavailable && !apiAvailable;
APIAvailable = apiAvailable; APIAvailable = apiAvailable;
} }
catch catch
{ {
APIAvailable = apiAvailable; APIAvailable = apiAvailable;
} }
finally finally
{ {
if (!apiAvailable && !_shownGlamourerUnavailable) if (!apiAvailable && !_shownGlamourerUnavailable)
{ {
_shownGlamourerUnavailable = true; _shownGlamourerUnavailable = true;
_mareMediator.Publish(new NotificationMessage("Glamourer inactive", "Your Glamourer installation is not active or out of date. Update Glamourer to continue to use Mare. If you just updated Glamourer, ignore this message.", _mareMediator.Publish(new NotificationMessage("Glamourer inactive", "Your Glamourer installation is not active or out of date. Update Glamourer to continue to use Mare. If you just updated Glamourer, ignore this message.",
NotificationType.Error)); NotificationType.Error));
} }
} }
} }
public void Dispose() public void Dispose()
{ {
_glamourerStateChanged?.Dispose(); _glamourerStateChanged?.Dispose();
} }
public async Task ApplyAllAsync(ILogger logger, GameObjectHandler handler, string? customization, Guid applicationId, CancellationToken token, bool fireAndForget = false) public async Task ApplyAllAsync(ILogger logger, GameObjectHandler handler, string? customization, Guid applicationId, CancellationToken token, bool fireAndForget = false)
{ {
if (!APIAvailable || string.IsNullOrEmpty(customization) || _dalamudUtil.IsZoning) return; if (!APIAvailable || string.IsNullOrEmpty(customization) || _dalamudUtil.IsZoning) return;
await _redrawManager.RedrawSemaphore.WaitAsync(token).ConfigureAwait(false); await _redrawManager.RedrawSemaphore.WaitAsync(token).ConfigureAwait(false);
try try
{ {
await _redrawManager.PenumbraRedrawInternalAsync(logger, handler, applicationId, (chara) => await _redrawManager.PenumbraRedrawInternalAsync(logger, handler, applicationId, (chara) =>
{ {
try try
{ {
logger.LogDebug("[{appid}] Calling on IPC: GlamourerApplyAll", applicationId); logger.LogDebug("[{appid}] Calling on IPC: GlamourerApplyAll", applicationId);
_glamourerApplyAll!.Invoke(customization, chara.ObjectIndex, LockCode); _glamourerApplyAll!.Invoke(customization, chara.ObjectIndex, LockCode);
} }
catch (Exception ex) catch (Exception ex)
{
logger.LogWarning(ex, "[{appid}] Failed to apply Glamourer data", applicationId);
}
}).ConfigureAwait(false);
}
finally
{
_redrawManager.RedrawSemaphore.Release();
}
}
public async Task<string> GetCharacterCustomizationAsync(IntPtr character)
{
if (!APIAvailable) return string.Empty;
try
{
return await _dalamudUtil.RunOnFrameworkThread(() =>
{
var gameObj = _dalamudUtil.CreateGameObject(character);
if (gameObj is Character c)
{ {
return _glamourerGetAllCustomization!.Invoke(c.ObjectIndex).Item2 ?? string.Empty; logger.LogWarning(ex, "[{appid}] Failed to apply Glamourer data", applicationId);
} }
return string.Empty; }).ConfigureAwait(false);
}).ConfigureAwait(false); }
} finally
catch {
{ _redrawManager.RedrawSemaphore.Release();
return string.Empty; }
} }
}
public async Task<string> GetCharacterCustomizationAsync(IntPtr character)
public async Task RevertAsync(ILogger logger, string name, GameObjectHandler handler, Guid applicationId, CancellationToken token) {
{ if (!APIAvailable) return string.Empty;
if ((!APIAvailable) || _dalamudUtil.IsZoning) return; try
try {
{ return await _dalamudUtil.RunOnFrameworkThread(() =>
await _redrawManager.RedrawSemaphore.WaitAsync(token).ConfigureAwait(false); {
await _redrawManager.PenumbraRedrawInternalAsync(logger, handler, applicationId, (chara) => var gameObj = _dalamudUtil.CreateGameObject(character);
{ if (gameObj is Character c)
try {
return _glamourerGetAllCustomization!.Invoke(c.ObjectIndex).Item2 ?? string.Empty;
}
return string.Empty;
}).ConfigureAwait(false);
}
catch
{
return string.Empty;
}
}
public async Task RevertAsync(ILogger logger, string name, GameObjectHandler handler, Guid applicationId, CancellationToken token)
{
if ((!APIAvailable) || _dalamudUtil.IsZoning) return;
try
{
await _redrawManager.RedrawSemaphore.WaitAsync(token).ConfigureAwait(false);
await _redrawManager.PenumbraRedrawInternalAsync(logger, handler, applicationId, (chara) =>
{
try
{ {
logger.LogDebug("[{appid}] Calling On IPC: GlamourerUnlockName", applicationId); logger.LogDebug("[{appid}] Calling On IPC: GlamourerUnlockName", applicationId);
_glamourerUnlock.Invoke(chara.ObjectIndex, LockCode); _glamourerUnlock.Invoke(chara.ObjectIndex, LockCode);
logger.LogDebug("[{appid}] Calling On IPC: GlamourerRevert", applicationId); logger.LogDebug("[{appid}] Calling On IPC: GlamourerRevert", applicationId);
_glamourerRevert.Invoke(chara.ObjectIndex, LockCode); _glamourerRevert.Invoke(chara.ObjectIndex, LockCode);
logger.LogDebug("[{appid}] Calling On IPC: PenumbraRedraw", applicationId); logger.LogDebug("[{appid}] Calling On IPC: PenumbraRedraw", applicationId);
_mareMediator.Publish(new PenumbraRedrawCharacterMessage(chara)); _mareMediator.Publish(new PenumbraRedrawCharacterMessage(chara));
} }
catch (Exception ex) catch (Exception ex)
{ {
logger.LogWarning(ex, "[{appid}] Error during GlamourerRevert", applicationId); logger.LogWarning(ex, "[{appid}] Error during GlamourerRevert", applicationId);
} }
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
finally finally
{
_redrawManager.RedrawSemaphore.Release();
}
}
public async Task RevertByNameAsync(ILogger logger, string name, Guid applicationId)
{
if ((!APIAvailable) || _dalamudUtil.IsZoning) return;
await _dalamudUtil.RunOnFrameworkThread(() =>
{ {
RevertByName(logger, name, applicationId); _redrawManager.RedrawSemaphore.Release();
}
}).ConfigureAwait(false); }
}
public async Task RevertByNameAsync(ILogger logger, string name, Guid applicationId)
public void RevertByName(ILogger logger, string name, Guid applicationId) {
{ if ((!APIAvailable) || _dalamudUtil.IsZoning) return;
await _dalamudUtil.RunOnFrameworkThread(() =>
{
RevertByName(logger, name, applicationId);
}).ConfigureAwait(false);
}
public void RevertByName(ILogger logger, string name, Guid applicationId)
{
if ((!APIAvailable) || _dalamudUtil.IsZoning) return; if ((!APIAvailable) || _dalamudUtil.IsZoning) return;
try try
@@ -202,11 +202,11 @@ public sealed class IpcCallerGlamourer : IIpcCaller
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogWarning(ex, "Error during Glamourer RevertByName"); _logger.LogWarning(ex, "Error during Glamourer RevertByName");
} }
} }
private void GlamourerChanged(nint address) private void GlamourerChanged(nint address)
{ {
_mareMediator.Publish(new GlamourerChangedMessage(address)); _mareMediator.Publish(new GlamourerChangedMessage(address));
} }
} }

View File

@@ -1,36 +1,36 @@
using Dalamud.Interface.Internal.Notifications; using Dalamud.Interface.Internal.Notifications;
using Dalamud.Plugin; using Dalamud.Plugin;
using MareSynchronos.PlayerData.Handlers; using MareSynchronos.PlayerData.Handlers;
using MareSynchronos.Services; using MareSynchronos.Services;
using MareSynchronos.Services.Mediator; using MareSynchronos.Services.Mediator;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Penumbra.Api.Enums; using Penumbra.Api.Enums;
using Penumbra.Api.Helpers; using Penumbra.Api.Helpers;
using Penumbra.Api.IpcSubscribers; using Penumbra.Api.IpcSubscribers;
using System.Collections.Concurrent; using System.Collections.Concurrent;
namespace MareSynchronos.Interop.Ipc; namespace MareSynchronos.Interop.Ipc;
public sealed class IpcCallerPenumbra : DisposableMediatorSubscriberBase, IIpcCaller public sealed class IpcCallerPenumbra : DisposableMediatorSubscriberBase, IIpcCaller
{ {
private readonly DalamudPluginInterface _pi; private readonly DalamudPluginInterface _pi;
private readonly DalamudUtilService _dalamudUtil; private readonly DalamudUtilService _dalamudUtil;
private readonly MareMediator _mareMediator; private readonly MareMediator _mareMediator;
private readonly RedrawManager _redrawManager; private readonly RedrawManager _redrawManager;
private bool _shownPenumbraUnavailable = false; private bool _shownPenumbraUnavailable = false;
private string? _penumbraModDirectory; private string? _penumbraModDirectory;
public string? ModDirectory public string? ModDirectory
{ {
get => _penumbraModDirectory; get => _penumbraModDirectory;
private set private set
{ {
if (!string.Equals(_penumbraModDirectory, value, StringComparison.Ordinal)) if (!string.Equals(_penumbraModDirectory, value, StringComparison.Ordinal))
{ {
_penumbraModDirectory = value; _penumbraModDirectory = value;
_mareMediator.Publish(new PenumbraDirectoryChangedMessage(_penumbraModDirectory)); _mareMediator.Publish(new PenumbraDirectoryChangedMessage(_penumbraModDirectory));
} }
} }
} }
private readonly ConcurrentDictionary<IntPtr, bool> _penumbraRedrawRequests = new(); private readonly ConcurrentDictionary<IntPtr, bool> _penumbraRedrawRequests = new();
@@ -39,296 +39,296 @@ public sealed class IpcCallerPenumbra : DisposableMediatorSubscriberBase, IIpcCa
private readonly EventSubscriber _penumbraInit; private readonly EventSubscriber _penumbraInit;
private readonly EventSubscriber<ModSettingChange, Guid, string, bool> _penumbraModSettingChanged; private readonly EventSubscriber<ModSettingChange, Guid, string, bool> _penumbraModSettingChanged;
private readonly EventSubscriber<nint, int> _penumbraObjectIsRedrawn; private readonly EventSubscriber<nint, int> _penumbraObjectIsRedrawn;
private readonly AddTemporaryMod _penumbraAddTemporaryMod; private readonly AddTemporaryMod _penumbraAddTemporaryMod;
private readonly AssignTemporaryCollection _penumbraAssignTemporaryCollection; private readonly AssignTemporaryCollection _penumbraAssignTemporaryCollection;
private readonly ConvertTextureFile _penumbraConvertTextureFile; private readonly ConvertTextureFile _penumbraConvertTextureFile;
private readonly CreateTemporaryCollection _penumbraCreateNamedTemporaryCollection; private readonly CreateTemporaryCollection _penumbraCreateNamedTemporaryCollection;
private readonly GetEnabledState _penumbraEnabled; private readonly GetEnabledState _penumbraEnabled;
private readonly GetPlayerMetaManipulations _penumbraGetMetaManipulations; private readonly GetPlayerMetaManipulations _penumbraGetMetaManipulations;
private readonly RedrawObject _penumbraRedraw; private readonly RedrawObject _penumbraRedraw;
private readonly DeleteTemporaryCollection _penumbraRemoveTemporaryCollection; private readonly DeleteTemporaryCollection _penumbraRemoveTemporaryCollection;
private readonly RemoveTemporaryMod _penumbraRemoveTemporaryMod; private readonly RemoveTemporaryMod _penumbraRemoveTemporaryMod;
private readonly GetModDirectory _penumbraResolveModDir; private readonly GetModDirectory _penumbraResolveModDir;
private readonly ResolvePlayerPathsAsync _penumbraResolvePaths; private readonly ResolvePlayerPathsAsync _penumbraResolvePaths;
private readonly GetGameObjectResourcePaths _penumbraResourcePaths; private readonly GetGameObjectResourcePaths _penumbraResourcePaths;
public IpcCallerPenumbra(ILogger<IpcCallerPenumbra> logger, DalamudPluginInterface pi, DalamudUtilService dalamudUtil, public IpcCallerPenumbra(ILogger<IpcCallerPenumbra> logger, DalamudPluginInterface pi, DalamudUtilService dalamudUtil,
MareMediator mareMediator, RedrawManager redrawManager) : base(logger, mareMediator) MareMediator mareMediator, RedrawManager redrawManager) : base(logger, mareMediator)
{ {
_pi = pi; _pi = pi;
_dalamudUtil = dalamudUtil; _dalamudUtil = dalamudUtil;
_mareMediator = mareMediator; _mareMediator = mareMediator;
_redrawManager = redrawManager; _redrawManager = redrawManager;
_penumbraInit = Initialized.Subscriber(pi, PenumbraInit); _penumbraInit = Initialized.Subscriber(pi, PenumbraInit);
_penumbraDispose = Disposed.Subscriber(pi, PenumbraDispose); _penumbraDispose = Disposed.Subscriber(pi, PenumbraDispose);
_penumbraResolveModDir = new GetModDirectory(pi); _penumbraResolveModDir = new GetModDirectory(pi);
_penumbraRedraw = new RedrawObject(pi); _penumbraRedraw = new RedrawObject(pi);
_penumbraObjectIsRedrawn = GameObjectRedrawn.Subscriber(pi, RedrawEvent); _penumbraObjectIsRedrawn = GameObjectRedrawn.Subscriber(pi, RedrawEvent);
_penumbraGetMetaManipulations = new GetPlayerMetaManipulations(pi); _penumbraGetMetaManipulations = new GetPlayerMetaManipulations(pi);
_penumbraRemoveTemporaryMod = new RemoveTemporaryMod(pi); _penumbraRemoveTemporaryMod = new RemoveTemporaryMod(pi);
_penumbraAddTemporaryMod = new AddTemporaryMod(pi); _penumbraAddTemporaryMod = new AddTemporaryMod(pi);
_penumbraCreateNamedTemporaryCollection = new CreateTemporaryCollection(pi); _penumbraCreateNamedTemporaryCollection = new CreateTemporaryCollection(pi);
_penumbraRemoveTemporaryCollection = new DeleteTemporaryCollection(pi); _penumbraRemoveTemporaryCollection = new DeleteTemporaryCollection(pi);
_penumbraAssignTemporaryCollection = new AssignTemporaryCollection(pi); _penumbraAssignTemporaryCollection = new AssignTemporaryCollection(pi);
_penumbraResolvePaths = new ResolvePlayerPathsAsync(pi); _penumbraResolvePaths = new ResolvePlayerPathsAsync(pi);
_penumbraEnabled = new GetEnabledState(pi); _penumbraEnabled = new GetEnabledState(pi);
_penumbraModSettingChanged = ModSettingChanged.Subscriber(pi, (change, arg1, arg, b) => _penumbraModSettingChanged = ModSettingChanged.Subscriber(pi, (change, arg1, arg, b) =>
{ {
if (change == ModSettingChange.EnableState) if (change == ModSettingChange.EnableState)
_mareMediator.Publish(new PenumbraModSettingChangedMessage()); _mareMediator.Publish(new PenumbraModSettingChangedMessage());
}); });
_penumbraConvertTextureFile = new ConvertTextureFile(pi); _penumbraConvertTextureFile = new ConvertTextureFile(pi);
_penumbraResourcePaths = new GetGameObjectResourcePaths(pi); _penumbraResourcePaths = new GetGameObjectResourcePaths(pi);
_penumbraGameObjectResourcePathResolved = GameObjectResourcePathResolved.Subscriber(pi, ResourceLoaded); _penumbraGameObjectResourcePathResolved = GameObjectResourcePathResolved.Subscriber(pi, ResourceLoaded);
CheckAPI(); CheckAPI();
CheckModDirectory(); CheckModDirectory();
Mediator.Subscribe<PenumbraRedrawCharacterMessage>(this, (msg) => Mediator.Subscribe<PenumbraRedrawCharacterMessage>(this, (msg) =>
{ {
_penumbraRedraw.Invoke(msg.Character.ObjectIndex, RedrawType.AfterGPose); _penumbraRedraw.Invoke(msg.Character.ObjectIndex, RedrawType.AfterGPose);
}); });
} }
public bool APIAvailable { get; private set; } = false; public bool APIAvailable { get; private set; } = false;
public void CheckAPI() public void CheckAPI()
{ {
bool penumbraAvailable = false; bool penumbraAvailable = false;
try try
{ {
var penumbraVersion = (_pi.InstalledPlugins var penumbraVersion = (_pi.InstalledPlugins
.FirstOrDefault(p => string.Equals(p.InternalName, "Penumbra", StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(p => string.Equals(p.InternalName, "Penumbra", StringComparison.OrdinalIgnoreCase))
?.Version ?? new Version(0, 0, 0, 0)); ?.Version ?? new Version(0, 0, 0, 0));
penumbraAvailable = penumbraVersion >= new Version(1, 1, 0, 0); penumbraAvailable = penumbraVersion >= new Version(1, 1, 0, 0);
penumbraAvailable &= _penumbraEnabled.Invoke(); penumbraAvailable &= _penumbraEnabled.Invoke();
_shownPenumbraUnavailable = _shownPenumbraUnavailable && !penumbraAvailable; _shownPenumbraUnavailable = _shownPenumbraUnavailable && !penumbraAvailable;
APIAvailable = penumbraAvailable; APIAvailable = penumbraAvailable;
} }
catch catch
{ {
APIAvailable = penumbraAvailable; APIAvailable = penumbraAvailable;
} }
finally finally
{ {
if (!penumbraAvailable && !_shownPenumbraUnavailable) if (!penumbraAvailable && !_shownPenumbraUnavailable)
{ {
_shownPenumbraUnavailable = true; _shownPenumbraUnavailable = true;
_mareMediator.Publish(new NotificationMessage("Penumbra inactive", _mareMediator.Publish(new NotificationMessage("Penumbra inactive",
"Your Penumbra installation is not active or out of date. Update Penumbra and/or the Enable Mods setting in Penumbra to continue to use Mare. If you just updated Penumbra, ignore this message.", "Your Penumbra installation is not active or out of date. Update Penumbra and/or the Enable Mods setting in Penumbra to continue to use Mare. If you just updated Penumbra, ignore this message.",
NotificationType.Error)); NotificationType.Error));
} }
} }
} }
public void CheckModDirectory() public void CheckModDirectory()
{ {
if (!APIAvailable) if (!APIAvailable)
{ {
ModDirectory = string.Empty; ModDirectory = string.Empty;
} }
else else
{ {
ModDirectory = _penumbraResolveModDir!.Invoke().ToLowerInvariant(); ModDirectory = _penumbraResolveModDir!.Invoke().ToLowerInvariant();
} }
} }
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{ {
base.Dispose(disposing); base.Dispose(disposing);
_redrawManager.Cancel(); _redrawManager.Cancel();
_penumbraModSettingChanged.Dispose(); _penumbraModSettingChanged.Dispose();
_penumbraGameObjectResourcePathResolved.Dispose(); _penumbraGameObjectResourcePathResolved.Dispose();
_penumbraDispose.Dispose(); _penumbraDispose.Dispose();
_penumbraInit.Dispose(); _penumbraInit.Dispose();
_penumbraObjectIsRedrawn.Dispose(); _penumbraObjectIsRedrawn.Dispose();
} }
public async Task AssignTemporaryCollectionAsync(ILogger logger, Guid collName, int idx) public async Task AssignTemporaryCollectionAsync(ILogger logger, Guid collName, int idx)
{ {
if (!APIAvailable) return; if (!APIAvailable) return;
await _dalamudUtil.RunOnFrameworkThread(() => await _dalamudUtil.RunOnFrameworkThread(() =>
{ {
var retAssign = _penumbraAssignTemporaryCollection.Invoke(collName, idx, forceAssignment: true); var retAssign = _penumbraAssignTemporaryCollection.Invoke(collName, idx, forceAssignment: true);
logger.LogTrace("Assigning Temp Collection {collName} to index {idx}, Success: {ret}", collName, idx, retAssign); logger.LogTrace("Assigning Temp Collection {collName} to index {idx}, Success: {ret}", collName, idx, retAssign);
return collName; return collName;
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
public async Task ConvertTextureFiles(ILogger logger, Dictionary<string, string[]> textures, IProgress<(string, int)> progress, CancellationToken token) public async Task ConvertTextureFiles(ILogger logger, Dictionary<string, string[]> textures, IProgress<(string, int)> progress, CancellationToken token)
{ {
if (!APIAvailable) return; if (!APIAvailable) return;
_mareMediator.Publish(new HaltScanMessage(nameof(ConvertTextureFiles))); _mareMediator.Publish(new HaltScanMessage(nameof(ConvertTextureFiles)));
int currentTexture = 0; int currentTexture = 0;
foreach (var texture in textures) foreach (var texture in textures)
{ {
if (token.IsCancellationRequested) break; if (token.IsCancellationRequested) break;
progress.Report((texture.Key, ++currentTexture)); progress.Report((texture.Key, ++currentTexture));
logger.LogInformation("Converting Texture {path} to {type}", texture.Key, TextureType.Bc7Tex); logger.LogInformation("Converting Texture {path} to {type}", texture.Key, TextureType.Bc7Tex);
var convertTask = _penumbraConvertTextureFile.Invoke(texture.Key, texture.Key, TextureType.Bc7Tex, mipMaps: true); var convertTask = _penumbraConvertTextureFile.Invoke(texture.Key, texture.Key, TextureType.Bc7Tex, mipMaps: true);
await convertTask.ConfigureAwait(false); await convertTask.ConfigureAwait(false);
if (convertTask.IsCompletedSuccessfully && texture.Value.Any()) if (convertTask.IsCompletedSuccessfully && texture.Value.Any())
{ {
foreach (var duplicatedTexture in texture.Value) foreach (var duplicatedTexture in texture.Value)
{ {
logger.LogInformation("Migrating duplicate {dup}", duplicatedTexture); logger.LogInformation("Migrating duplicate {dup}", duplicatedTexture);
try try
{ {
File.Copy(texture.Key, duplicatedTexture, overwrite: true); File.Copy(texture.Key, duplicatedTexture, overwrite: true);
} }
catch (Exception ex) catch (Exception ex)
{ {
logger.LogError(ex, "Failed to copy duplicate {dup}", duplicatedTexture); logger.LogError(ex, "Failed to copy duplicate {dup}", duplicatedTexture);
} }
} }
} }
} }
_mareMediator.Publish(new ResumeScanMessage(nameof(ConvertTextureFiles))); _mareMediator.Publish(new ResumeScanMessage(nameof(ConvertTextureFiles)));
await _dalamudUtil.RunOnFrameworkThread(async () => await _dalamudUtil.RunOnFrameworkThread(async () =>
{ {
var gameObject = await _dalamudUtil.CreateGameObjectAsync(await _dalamudUtil.GetPlayerPointerAsync().ConfigureAwait(false)).ConfigureAwait(false); var gameObject = await _dalamudUtil.CreateGameObjectAsync(await _dalamudUtil.GetPlayerPointerAsync().ConfigureAwait(false)).ConfigureAwait(false);
_penumbraRedraw.Invoke(gameObject!.ObjectIndex, setting: RedrawType.Redraw); _penumbraRedraw.Invoke(gameObject!.ObjectIndex, setting: RedrawType.Redraw);
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
public async Task<Guid> CreateTemporaryCollectionAsync(ILogger logger, string uid) public async Task<Guid> CreateTemporaryCollectionAsync(ILogger logger, string uid)
{ {
if (!APIAvailable) return Guid.Empty; if (!APIAvailable) return Guid.Empty;
return await _dalamudUtil.RunOnFrameworkThread(() => return await _dalamudUtil.RunOnFrameworkThread(() =>
{ {
var collName = "Mare_" + uid; var collName = "Mare_" + uid;
var collId = _penumbraCreateNamedTemporaryCollection.Invoke(collName); var collId = _penumbraCreateNamedTemporaryCollection.Invoke(collName);
logger.LogTrace("Creating Temp Collection {collName}, GUID: {collId}", collName, collId); logger.LogTrace("Creating Temp Collection {collName}, GUID: {collId}", collName, collId);
return collId; return collId;
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
public async Task<Dictionary<string, HashSet<string>>?> GetCharacterData(ILogger logger, GameObjectHandler handler) public async Task<Dictionary<string, HashSet<string>>?> GetCharacterData(ILogger logger, GameObjectHandler handler)
{ {
if (!APIAvailable) return null; if (!APIAvailable) return null;
return await _dalamudUtil.RunOnFrameworkThread(() => return await _dalamudUtil.RunOnFrameworkThread(() =>
{ {
logger.LogTrace("Calling On IPC: Penumbra.GetGameObjectResourcePaths"); logger.LogTrace("Calling On IPC: Penumbra.GetGameObjectResourcePaths");
var idx = handler.GetGameObject()?.ObjectIndex; var idx = handler.GetGameObject()?.ObjectIndex;
if (idx == null) return null; if (idx == null) return null;
return _penumbraResourcePaths.Invoke(idx.Value)[0]; return _penumbraResourcePaths.Invoke(idx.Value)[0];
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
public string GetMetaManipulations() public string GetMetaManipulations()
{ {
if (!APIAvailable) return string.Empty; if (!APIAvailable) return string.Empty;
return _penumbraGetMetaManipulations.Invoke(); return _penumbraGetMetaManipulations.Invoke();
} }
public async Task RedrawAsync(ILogger logger, GameObjectHandler handler, Guid applicationId, CancellationToken token) public async Task RedrawAsync(ILogger logger, GameObjectHandler handler, Guid applicationId, CancellationToken token)
{ {
if (!APIAvailable || _dalamudUtil.IsZoning) return; if (!APIAvailable || _dalamudUtil.IsZoning) return;
try try
{ {
await _redrawManager.RedrawSemaphore.WaitAsync(token).ConfigureAwait(false); await _redrawManager.RedrawSemaphore.WaitAsync(token).ConfigureAwait(false);
await _redrawManager.PenumbraRedrawInternalAsync(logger, handler, applicationId, (chara) => await _redrawManager.PenumbraRedrawInternalAsync(logger, handler, applicationId, (chara) =>
{ {
logger.LogDebug("[{appid}] Calling on IPC: PenumbraRedraw", applicationId); logger.LogDebug("[{appid}] Calling on IPC: PenumbraRedraw", applicationId);
_penumbraRedraw!.Invoke(chara.ObjectIndex, setting: RedrawType.Redraw); _penumbraRedraw!.Invoke(chara.ObjectIndex, setting: RedrawType.Redraw);
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
finally finally
{ {
_redrawManager.RedrawSemaphore.Release(); _redrawManager.RedrawSemaphore.Release();
} }
} }
public async Task RemoveTemporaryCollectionAsync(ILogger logger, Guid applicationId, Guid collId) public async Task RemoveTemporaryCollectionAsync(ILogger logger, Guid applicationId, Guid collId)
{ {
if (!APIAvailable) return; if (!APIAvailable) return;
await _dalamudUtil.RunOnFrameworkThread(() => await _dalamudUtil.RunOnFrameworkThread(() =>
{ {
logger.LogTrace("[{applicationId}] Removing temp collection for {collId}", applicationId, collId); logger.LogTrace("[{applicationId}] Removing temp collection for {collId}", applicationId, collId);
var ret2 = _penumbraRemoveTemporaryCollection.Invoke(collId); var ret2 = _penumbraRemoveTemporaryCollection.Invoke(collId);
logger.LogTrace("[{applicationId}] RemoveTemporaryCollection: {ret2}", applicationId, ret2); logger.LogTrace("[{applicationId}] RemoveTemporaryCollection: {ret2}", applicationId, ret2);
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
public async Task<(string[] forward, string[][] reverse)> ResolvePathsAsync(string[] forward, string[] reverse) public async Task<(string[] forward, string[][] reverse)> ResolvePathsAsync(string[] forward, string[] reverse)
{ {
return await _penumbraResolvePaths.Invoke(forward, reverse).ConfigureAwait(false); return await _penumbraResolvePaths.Invoke(forward, reverse).ConfigureAwait(false);
} }
public async Task SetManipulationDataAsync(ILogger logger, Guid applicationId, Guid collId, string manipulationData) public async Task SetManipulationDataAsync(ILogger logger, Guid applicationId, Guid collId, string manipulationData)
{ {
if (!APIAvailable) return; if (!APIAvailable) return;
await _dalamudUtil.RunOnFrameworkThread(() => await _dalamudUtil.RunOnFrameworkThread(() =>
{ {
logger.LogTrace("[{applicationId}] Manip: {data}", applicationId, manipulationData); logger.LogTrace("[{applicationId}] Manip: {data}", applicationId, manipulationData);
var retAdd = _penumbraAddTemporaryMod.Invoke("MareChara_Meta", collId, [], manipulationData, 0); var retAdd = _penumbraAddTemporaryMod.Invoke("MareChara_Meta", collId, [], manipulationData, 0);
logger.LogTrace("[{applicationId}] Setting temp meta mod for {collId}, Success: {ret}", applicationId, collId, retAdd); logger.LogTrace("[{applicationId}] Setting temp meta mod for {collId}, Success: {ret}", applicationId, collId, retAdd);
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
public async Task SetTemporaryModsAsync(ILogger logger, Guid applicationId, Guid collId, Dictionary<string, string> modPaths) public async Task SetTemporaryModsAsync(ILogger logger, Guid applicationId, Guid collId, Dictionary<string, string> modPaths)
{ {
if (!APIAvailable) return; if (!APIAvailable) return;
await _dalamudUtil.RunOnFrameworkThread(() => await _dalamudUtil.RunOnFrameworkThread(() =>
{ {
foreach (var mod in modPaths) foreach (var mod in modPaths)
{ {
logger.LogTrace("[{applicationId}] Change: {from} => {to}", applicationId, mod.Key, mod.Value); logger.LogTrace("[{applicationId}] Change: {from} => {to}", applicationId, mod.Key, mod.Value);
} }
var retRemove = _penumbraRemoveTemporaryMod.Invoke("MareChara_Files", collId, 0); var retRemove = _penumbraRemoveTemporaryMod.Invoke("MareChara_Files", collId, 0);
logger.LogTrace("[{applicationId}] Removing temp files mod for {collId}, Success: {ret}", applicationId, collId, retRemove); logger.LogTrace("[{applicationId}] Removing temp files mod for {collId}, Success: {ret}", applicationId, collId, retRemove);
var retAdd = _penumbraAddTemporaryMod.Invoke("MareChara_Files", collId, modPaths, string.Empty, 0); var retAdd = _penumbraAddTemporaryMod.Invoke("MareChara_Files", collId, modPaths, string.Empty, 0);
logger.LogTrace("[{applicationId}] Setting temp files mod for {collId}, Success: {ret}", applicationId, collId, retAdd); logger.LogTrace("[{applicationId}] Setting temp files mod for {collId}, Success: {ret}", applicationId, collId, retAdd);
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
private void RedrawEvent(IntPtr objectAddress, int objectTableIndex) private void RedrawEvent(IntPtr objectAddress, int objectTableIndex)
{ {
bool wasRequested = false; bool wasRequested = false;
if (_penumbraRedrawRequests.TryGetValue(objectAddress, out var redrawRequest) && redrawRequest) if (_penumbraRedrawRequests.TryGetValue(objectAddress, out var redrawRequest) && redrawRequest)
{ {
_penumbraRedrawRequests[objectAddress] = false; _penumbraRedrawRequests[objectAddress] = false;
} }
else else
{ {
_mareMediator.Publish(new PenumbraRedrawMessage(objectAddress, objectTableIndex, wasRequested)); _mareMediator.Publish(new PenumbraRedrawMessage(objectAddress, objectTableIndex, wasRequested));
} }
} }
private void ResourceLoaded(IntPtr ptr, string arg1, string arg2) private void ResourceLoaded(IntPtr ptr, string arg1, string arg2)
{ {
if (ptr != IntPtr.Zero && string.Compare(arg1, arg2, ignoreCase: true, System.Globalization.CultureInfo.InvariantCulture) != 0) if (ptr != IntPtr.Zero && string.Compare(arg1, arg2, ignoreCase: true, System.Globalization.CultureInfo.InvariantCulture) != 0)
{ {
_mareMediator.Publish(new PenumbraResourceLoadMessage(ptr, arg1, arg2)); _mareMediator.Publish(new PenumbraResourceLoadMessage(ptr, arg1, arg2));
} }
} }
private void PenumbraDispose() private void PenumbraDispose()
{ {
_redrawManager.Cancel(); _redrawManager.Cancel();
_mareMediator.Publish(new PenumbraDisposedMessage()); _mareMediator.Publish(new PenumbraDisposedMessage());
} }
private void PenumbraInit() private void PenumbraInit()
{ {
APIAvailable = true; APIAvailable = true;
ModDirectory = _penumbraResolveModDir.Invoke(); ModDirectory = _penumbraResolveModDir.Invoke();
_mareMediator.Publish(new PenumbraInitializedMessage()); _mareMediator.Publish(new PenumbraInitializedMessage());
_penumbraRedraw!.Invoke(0, setting: RedrawType.Redraw); _penumbraRedraw!.Invoke(0, setting: RedrawType.Redraw);
} }
} }