using Dalamud.Logging; using Dalamud.Plugin; using Dalamud.Plugin.Ipc; using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Reflection.Metadata; namespace MareSynchronos.Managers { public class IpcManager : IDisposable { private readonly DalamudPluginInterface pluginInterface; private ICallGateSubscriber penumbraInit; private ICallGateSubscriber? penumbraResolvePath; private ICallGateSubscriber? penumbraResolveModDir; private ICallGateSubscriber? glamourerGetCharacterCustomization; private ICallGateSubscriber? glamourerApplyCharacterCustomization; private ICallGateSubscriber penumbraApiVersion; private ICallGateSubscriber glamourerApiVersion; private ICallGateSubscriber penumbraObjectIsRedrawn; private ICallGateSubscriber? penumbraRedraw; private ICallGateSubscriber? penumbraReverseResolvePath; private ICallGateSubscriber glamourerRevertCustomization; private ICallGateSubscriber, List, int, int> penumbraSetTemporaryMod; private ICallGateSubscriber penumbraCreateTemporaryCollection; private ICallGateSubscriber penumbraRemoveTemporaryCollection; public bool Initialized { get; private set; } = false; public event EventHandler? PenumbraRedrawEvent; public IpcManager(DalamudPluginInterface pi) { pluginInterface = pi; penumbraInit = pluginInterface.GetIpcSubscriber("Penumbra.Initialized"); penumbraResolvePath = pluginInterface.GetIpcSubscriber("Penumbra.ResolveCharacterPath"); penumbraResolveModDir = pluginInterface.GetIpcSubscriber("Penumbra.GetModDirectory"); penumbraRedraw = pluginInterface.GetIpcSubscriber("Penumbra.RedrawObjectByName"); glamourerGetCharacterCustomization = pluginInterface.GetIpcSubscriber("Glamourer.GetCharacterCustomization"); glamourerApplyCharacterCustomization = pluginInterface.GetIpcSubscriber("Glamourer.ApplyCharacterCustomization"); penumbraReverseResolvePath = pluginInterface.GetIpcSubscriber("Penumbra.ReverseResolvePath"); penumbraApiVersion = pluginInterface.GetIpcSubscriber("Penumbra.ApiVersion"); glamourerApiVersion = pluginInterface.GetIpcSubscriber("Glamourer.ApiVersion"); glamourerRevertCustomization = pluginInterface.GetIpcSubscriber("Glamourer.RevertCharacterCustomization"); penumbraObjectIsRedrawn = pluginInterface.GetIpcSubscriber("Penumbra.GameObjectRedrawn"); penumbraObjectIsRedrawn.Subscribe(RedrawEvent); penumbraInit.Subscribe(RedrawSelf); penumbraSetTemporaryMod = pluginInterface .GetIpcSubscriber, List, int, int>("Penumbra.AddTemporaryMod"); penumbraCreateTemporaryCollection = pluginInterface.GetIpcSubscriber("Penumbra.CreateTemporaryCollection"); penumbraRemoveTemporaryCollection = pluginInterface.GetIpcSubscriber("Penumbra.RemoveTemporaryCollection"); Initialized = true; } public bool CheckPenumbraAPI() { try { return penumbraApiVersion.InvokeFunc() >= 4; } catch { return false; } } public bool CheckGlamourerAPI() { try { return glamourerApiVersion.InvokeFunc() >= 0; } catch { return false; } } private void RedrawEvent(IntPtr objectAddress, int objectTableIndex) { PenumbraRedrawEvent?.Invoke(objectTableIndex, EventArgs.Empty); } private void RedrawSelf() { penumbraRedraw!.InvokeAction("self", 0); } private void Uninitialize() { penumbraInit.Unsubscribe(RedrawSelf); penumbraObjectIsRedrawn.Unsubscribe(RedrawEvent); penumbraResolvePath = null; penumbraResolveModDir = null; glamourerGetCharacterCustomization = null; glamourerApplyCharacterCustomization = null; penumbraReverseResolvePath = null; Initialized = false; PluginLog.Debug("IPC Manager disposed"); } public string[] PenumbraReverseResolvePath(string path, string characterName) { if (!CheckPenumbraAPI()) return new[] { path }; return penumbraReverseResolvePath!.InvokeFunc(path, characterName); } public string? PenumbraResolvePath(string path, string characterName) { if (!CheckPenumbraAPI()) return null; return penumbraResolvePath!.InvokeFunc(path, characterName); } public string? PenumbraModDirectory() { if (!CheckPenumbraAPI()) return null; return penumbraResolveModDir!.InvokeFunc(); } public string? GlamourerGetCharacterCustomization() { if (!CheckGlamourerAPI()) return null; return glamourerGetCharacterCustomization!.InvokeFunc(); } public void GlamourerApplyCharacterCustomization(string customization, string characterName) { if (!CheckGlamourerAPI()) return; glamourerApplyCharacterCustomization!.InvokeAction(customization, characterName); } public void GlamourerRevertCharacterCustomization(string characterName) { if (!CheckGlamourerAPI()) return; glamourerRevertCustomization!.InvokeAction(characterName); } public void PenumbraRedraw(string actorName) { if (!CheckPenumbraAPI()) return; penumbraRedraw!.InvokeAction(actorName, 0); } public void PenumbraCreateTemporaryCollection(string characterName) { if (!CheckPenumbraAPI()) return; PluginLog.Debug("Creating temp collection for " + characterName); //penumbraCreateTemporaryCollection.InvokeFunc("MareSynchronos", characterName, true); } public void PenumbraRemoveTemporaryCollection(string characterName) { if (!CheckPenumbraAPI()) return; PluginLog.Debug("Removing temp collection for " + characterName); //penumbraRemoveTemporaryCollection.InvokeFunc(characterName); } public void PenumbraSetTemporaryMods(string characterName, IReadOnlyDictionary modPaths) { if (!CheckPenumbraAPI()) return; PluginLog.Debug("Assigning temp mods for " + characterName); try { //var result = penumbraSetTemporaryMod.InvokeFunc("MareSynchronos", characterName, modPaths, new List(), 0); //PluginLog.Debug("Success: " + result); } catch (Exception ex) { PluginLog.Error(ex, "Error during IPC call"); } } public void Dispose() { Uninitialize(); } } }