Initial
This commit is contained in:
136
Penumbra.Api/Helpers/ActionProvider.cs
Normal file
136
Penumbra.Api/Helpers/ActionProvider.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
|
||||
namespace Penumbra.Api.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Specialized disposable Provider for Actions.
|
||||
/// </summary>
|
||||
public sealed class ActionProvider : IDisposable
|
||||
{
|
||||
private ICallGateProvider<object?>? _provider;
|
||||
|
||||
public ActionProvider(IDalamudPluginInterface pi, string label, Action action)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterAction(action);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterAction();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~ActionProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specialized disposable Provider for Actions.
|
||||
/// </summary>
|
||||
public sealed class ActionProvider<T1> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, object?>? _provider;
|
||||
|
||||
public ActionProvider(IDalamudPluginInterface pi, string label, Action<T1> action)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterAction(action);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterAction();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~ActionProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="ActionProvider{T1}"/>
|
||||
/// </summary>
|
||||
public sealed class ActionProvider<T1, T2> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, T2, object?>? _provider;
|
||||
|
||||
public ActionProvider(IDalamudPluginInterface pi, string label, Action<T1, T2> action)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterAction(action);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterAction();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~ActionProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="ActionProvider{T1}"/>
|
||||
/// </summary>
|
||||
public sealed class ActionProvider<T1, T2, T3> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, T2, T3, object?>? _provider;
|
||||
|
||||
public ActionProvider(IDalamudPluginInterface pi, string label, Action<T1, T2, T3> action)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterAction(action);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterAction();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~ActionProvider()
|
||||
=> Dispose();
|
||||
}
|
114
Penumbra.Api/Helpers/ActionSubscriber.cs
Normal file
114
Penumbra.Api/Helpers/ActionSubscriber.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
|
||||
namespace Penumbra.Api.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Specialized subscriber only allowing to invoke actions.
|
||||
/// </summary>
|
||||
public class ActionSubscriber
|
||||
{
|
||||
private readonly ICallGateSubscriber<object?>? _subscriber;
|
||||
|
||||
/// <summary> Whether the subscriber could successfully be created. </summary>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
protected ActionSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Invoke the action. See the source of the subscriber for details.</summary>
|
||||
protected void Invoke()
|
||||
=> _subscriber?.InvokeAction();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber"/>
|
||||
public class ActionSubscriber<T1>
|
||||
{
|
||||
private readonly ICallGateSubscriber<T1, object?>? _subscriber;
|
||||
|
||||
/// <summary> Whether the subscriber could successfully be created. </summary>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
protected ActionSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Invoke the action. See the source of the subscriber for details.</summary>
|
||||
protected void Invoke(T1 a)
|
||||
=> _subscriber?.InvokeAction(a);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber"/>
|
||||
public class ActionSubscriber<T1, T2>
|
||||
{
|
||||
private readonly ICallGateSubscriber<T1, T2, object?>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber{T1}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
protected ActionSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber.Invoke"/>
|
||||
protected void Invoke(T1 a, T2 b)
|
||||
=> _subscriber?.InvokeAction(a, b);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber"/>
|
||||
public class ActionSubscriber<T1, T2, T3>
|
||||
{
|
||||
private readonly ICallGateSubscriber<T1, T2, T3, object?>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber{T1}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
protected ActionSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber.Invoke"/>
|
||||
protected void Invoke(T1 a, T2 b, T3 c)
|
||||
=> _subscriber?.InvokeAction(a, b, c);
|
||||
}
|
152
Penumbra.Api/Helpers/ConvertingDict.cs
Normal file
152
Penumbra.Api/Helpers/ConvertingDict.cs
Normal file
@@ -0,0 +1,152 @@
|
||||
using System.Collections;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Penumbra.Api.Helpers;
|
||||
|
||||
/// <summary> A dictionary that implicitly can be converted to a read-only dictionary with different value type. </summary>
|
||||
/// <typeparam name="TKey"> The type of the keys. </typeparam>
|
||||
/// <typeparam name="TValueFrom"> The actual type of the values. </typeparam>
|
||||
/// <typeparam name="TValueTo"> The read-only type of the values. </typeparam>
|
||||
public abstract class ConvertingDict<TKey, TValueFrom, TValueTo>(IReadOnlyDictionary<TKey, TValueFrom> dict)
|
||||
: IReadOnlyDictionary<TKey, TValueTo>
|
||||
where TKey : notnull
|
||||
{
|
||||
/// <summary> Obtain the original dictionary. </summary>
|
||||
public IReadOnlyDictionary<TKey, TValueFrom> Original
|
||||
=> dict;
|
||||
|
||||
/// <summary> Conversion between values. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected abstract TValueTo ConvertValue(in TValueFrom from);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool ContainsKey(TKey key)
|
||||
=> dict.ContainsKey(key);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryGetValue(TKey key, out TValueTo value)
|
||||
{
|
||||
if (dict.TryGetValue(key, out var v))
|
||||
{
|
||||
value = ConvertValue(v);
|
||||
return true;
|
||||
}
|
||||
|
||||
value = default!;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public TValueTo this[TKey key]
|
||||
=> ConvertValue(dict[key]);
|
||||
|
||||
public IEnumerable<TKey> Keys
|
||||
=> dict.Keys;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<TValueTo> Values
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var value in dict.Values)
|
||||
yield return ConvertValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int Count
|
||||
=> dict.Count;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerator<KeyValuePair<TKey, TValueTo>> GetEnumerator()
|
||||
{
|
||||
foreach (var kvp in dict)
|
||||
yield return new KeyValuePair<TKey, TValueTo>(kvp.Key, ConvertValue(kvp.Value));
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
=> GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary> A dictionary that implicitly can be converted to a read-only dictionary with different value type. </summary>
|
||||
/// <typeparam name="TKeyFrom"> The actual type of the keys. </typeparam>
|
||||
/// <typeparam name="TKeyTo"> The read-only type of the keys. </typeparam>
|
||||
/// <typeparam name="TValueFrom"> The actual type of the values. </typeparam>
|
||||
/// <typeparam name="TValueTo"> The read-only type of the values. </typeparam>
|
||||
public abstract class ConvertingDict<TKeyFrom, TKeyTo, TValueFrom, TValueTo>(IReadOnlyDictionary<TKeyFrom, TValueFrom> dict)
|
||||
: IReadOnlyDictionary<TKeyTo, TValueTo>
|
||||
where TKeyFrom : notnull
|
||||
where TKeyTo : notnull
|
||||
{
|
||||
/// <summary> Obtain the original dictionary. </summary>
|
||||
public IReadOnlyDictionary<TKeyFrom, TValueFrom> Original
|
||||
=> dict;
|
||||
|
||||
/// <summary> Conversion between keys. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected abstract TKeyTo ConvertKey(in TKeyFrom from);
|
||||
|
||||
/// <summary> Conversion between keys. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected abstract TKeyFrom ConvertKeyBack(in TKeyTo from);
|
||||
|
||||
/// <summary> Conversion between values. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected abstract TValueTo ConvertValue(in TValueFrom from);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool ContainsKey(TKeyTo key)
|
||||
=> dict.ContainsKey(ConvertKeyBack(key));
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryGetValue(TKeyTo key, out TValueTo value)
|
||||
{
|
||||
if (dict.TryGetValue(ConvertKeyBack(key), out var v))
|
||||
{
|
||||
value = ConvertValue(v);
|
||||
return true;
|
||||
}
|
||||
|
||||
value = default!;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public TValueTo this[TKeyTo key]
|
||||
=> ConvertValue(dict[ConvertKeyBack(key)]);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<TKeyTo> Keys
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var key in dict.Keys)
|
||||
yield return ConvertKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<TValueTo> Values
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var value in dict.Values)
|
||||
yield return ConvertValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerator<KeyValuePair<TKeyTo, TValueTo>> GetEnumerator()
|
||||
{
|
||||
foreach (var kvp in dict)
|
||||
yield return new KeyValuePair<TKeyTo, TValueTo>(ConvertKey(kvp.Key), ConvertValue(kvp.Value));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
=> GetEnumerator();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int Count
|
||||
=> dict.Count;
|
||||
}
|
53
Penumbra.Api/Helpers/DtoClasses.cs
Normal file
53
Penumbra.Api/Helpers/DtoClasses.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using Penumbra.Api.Enums;
|
||||
|
||||
namespace Penumbra.Api.Helpers;
|
||||
|
||||
/// <summary> Wrapper dictionary. </summary>
|
||||
public sealed class GameResourceDict(IReadOnlyDictionary<nint, (string, string, uint)> dict)
|
||||
: ConvertingDict<nint, (string, string, uint), (string, string, ChangedItemIcon)>(dict)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected override (string, string, ChangedItemIcon) ConvertValue(in (string, string, uint) from)
|
||||
=> (from.Item1, from.Item2, (ChangedItemIcon)from.Item3);
|
||||
|
||||
/// <summary> Create dictionary or null. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static GameResourceDict? Create(IReadOnlyDictionary<nint, (string, string, uint)>? dict)
|
||||
=> dict == null ? null : new GameResourceDict(dict);
|
||||
}
|
||||
|
||||
/// <summary> Wrapper dictionary. </summary>
|
||||
public sealed class AvailableModSettings(IReadOnlyDictionary<string, (string[], int)> dict)
|
||||
: ConvertingDict<string, (string[], int), (string[], GroupType)>(dict)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected override (string[], GroupType) ConvertValue(in (string[], int) from)
|
||||
=> (from.Item1, (GroupType)from.Item2);
|
||||
|
||||
/// <summary> Create dictionary or null. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static AvailableModSettings? Create(IReadOnlyDictionary<string, (string[], int)>? dict)
|
||||
=> dict == null ? null : new AvailableModSettings(dict);
|
||||
}
|
||||
|
||||
public record ResourceNodeDto
|
||||
{
|
||||
public required ResourceType Type { get; init; }
|
||||
public required ChangedItemIcon Icon { get; init; }
|
||||
public required string? Name { get; init; }
|
||||
public required string? GamePath { get; init; }
|
||||
public required string ActualPath { get; init; }
|
||||
public required nint ObjectAddress { get; init; }
|
||||
public required nint ResourceHandle { get; init; }
|
||||
public required List<ResourceNodeDto> Children { get; init; }
|
||||
}
|
||||
|
||||
public record ResourceTreeDto
|
||||
{
|
||||
public required string Name { get; init; }
|
||||
public required ushort RaceCode { get; init; }
|
||||
public required List<ResourceNodeDto> Nodes { get; init; }
|
||||
}
|
465
Penumbra.Api/Helpers/EventProvider.cs
Normal file
465
Penumbra.Api/Helpers/EventProvider.cs
Normal file
@@ -0,0 +1,465 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
using Dalamud.Plugin.Services;
|
||||
|
||||
namespace Penumbra.Api.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Specialized disposable Provider for Events.<para />
|
||||
/// Will execute the unsubscriber action on dispose if any is provided.<para />
|
||||
/// Can only be invoked and disposed.
|
||||
/// </summary>
|
||||
public sealed class EventProvider : IDisposable
|
||||
{
|
||||
private readonly IPluginLog _log;
|
||||
private ICallGateProvider<object?>? _provider;
|
||||
private Delegate? _unsubscriber;
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, (Action<Action> Add, Action<Action> Del)? subscribe = null)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<object?>(label);
|
||||
subscribe?.Add(Invoke);
|
||||
_unsubscriber = subscribe?.Del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, Action<EventProvider> add, Action<EventProvider> del)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<object?>(label);
|
||||
add(this);
|
||||
_unsubscriber = del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Invoke the event.</summary>
|
||||
public void Invoke()
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider?.SendMessage();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception thrown on IPC event:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
switch (_unsubscriber)
|
||||
{
|
||||
case Action<Action> a:
|
||||
a(Invoke);
|
||||
break;
|
||||
case Action<EventProvider> b:
|
||||
b(this);
|
||||
break;
|
||||
}
|
||||
|
||||
_unsubscriber = null;
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~EventProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider"/>
|
||||
public sealed class EventProvider<T1> : IDisposable
|
||||
{
|
||||
private readonly IPluginLog _log;
|
||||
private ICallGateProvider<T1, object?>? _provider;
|
||||
private Delegate? _unsubscriber;
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, (Action<Action<T1>> Add, Action<Action<T1>> Del)? subscribe = null)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, object?>(label);
|
||||
subscribe?.Add(Invoke);
|
||||
_unsubscriber = subscribe?.Del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, Action<EventProvider<T1>> add, Action<EventProvider<T1>> del)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, object?>(label);
|
||||
add(this);
|
||||
_unsubscriber = del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider.Invoke"/>
|
||||
public void Invoke(T1 a)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider?.SendMessage(a);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception thrown on IPC event:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
switch (_unsubscriber)
|
||||
{
|
||||
case Action<Action<T1>> a:
|
||||
a(Invoke);
|
||||
break;
|
||||
case Action<EventProvider<T1>> b:
|
||||
b(this);
|
||||
break;
|
||||
}
|
||||
|
||||
_unsubscriber = null;
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~EventProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider"/>
|
||||
public sealed class EventProvider<T1, T2> : IDisposable
|
||||
{
|
||||
private readonly IPluginLog _log;
|
||||
private ICallGateProvider<T1, T2, object?>? _provider;
|
||||
private Delegate? _unsubscriber;
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label,
|
||||
(Action<Action<T1, T2>> Add, Action<Action<T1, T2>> Del)? subscribe = null)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, object?>(label);
|
||||
subscribe?.Add(Invoke);
|
||||
_unsubscriber = subscribe?.Del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, Action<EventProvider<T1, T2>> add, Action<EventProvider<T1, T2>> del)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, object?>(label);
|
||||
add(this);
|
||||
_unsubscriber = del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider.Invoke"/>
|
||||
public void Invoke(T1 a, T2 b)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider?.SendMessage(a, b);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception thrown on IPC event:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
switch (_unsubscriber)
|
||||
{
|
||||
case Action<Action<T1, T2>> a:
|
||||
a(Invoke);
|
||||
break;
|
||||
case Action<EventProvider<T1, T2>> b:
|
||||
b(this);
|
||||
break;
|
||||
}
|
||||
|
||||
_unsubscriber = null;
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~EventProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider"/>
|
||||
public sealed class EventProvider<T1, T2, T3> : IDisposable
|
||||
{
|
||||
private readonly IPluginLog _log;
|
||||
private ICallGateProvider<T1, T2, T3, object?>? _provider;
|
||||
private Delegate? _unsubscriber;
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label,
|
||||
(Action<Action<T1, T2, T3>> Add, Action<Action<T1, T2, T3>> Del)? subscribe = null)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, object?>(label);
|
||||
subscribe?.Add(Invoke);
|
||||
_unsubscriber = subscribe?.Del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, Action<EventProvider<T1, T2, T3>> add, Action<EventProvider<T1, T2, T3>> del)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, object?>(label);
|
||||
add(this);
|
||||
_unsubscriber = del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider.Invoke"/>
|
||||
public void Invoke(T1 a, T2 b, T3 c)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider?.SendMessage(a, b, c);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception thrown on IPC event:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
switch (_unsubscriber)
|
||||
{
|
||||
case Action<Action<T1, T2, T3>> a:
|
||||
a(Invoke);
|
||||
break;
|
||||
case Action<EventProvider<T1, T2, T3>> b:
|
||||
b(this);
|
||||
break;
|
||||
}
|
||||
|
||||
_unsubscriber = null;
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~EventProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider"/>
|
||||
public sealed class EventProvider<T1, T2, T3, T4> : IDisposable
|
||||
{
|
||||
private readonly IPluginLog _log;
|
||||
private ICallGateProvider<T1, T2, T3, T4, object?>? _provider;
|
||||
private Delegate? _unsubscriber;
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label,
|
||||
(Action<Action<T1, T2, T3, T4>> Add, Action<Action<T1, T2, T3, T4>> Del)? subscribe = null)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, T4, object?>(label);
|
||||
subscribe?.Add(Invoke);
|
||||
_unsubscriber = subscribe?.Del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, Action<EventProvider<T1, T2, T3, T4>> add,
|
||||
Action<EventProvider<T1, T2, T3, T4>> del)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, T4, object?>(label);
|
||||
add(this);
|
||||
_unsubscriber = del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider.Invoke"/>
|
||||
public void Invoke(T1 a, T2 b, T3 c, T4 d)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider?.SendMessage(a, b, c, d);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception thrown on IPC event:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
switch (_unsubscriber)
|
||||
{
|
||||
case Action<Action<T1, T2, T3, T4>> a:
|
||||
a(Invoke);
|
||||
break;
|
||||
case Action<EventProvider<T1, T2, T3, T4>> b:
|
||||
b(this);
|
||||
break;
|
||||
}
|
||||
|
||||
_unsubscriber = null;
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~EventProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider"/>
|
||||
public sealed class EventProvider<T1, T2, T3, T4, T5> : IDisposable
|
||||
{
|
||||
private readonly IPluginLog _log;
|
||||
private ICallGateProvider<T1, T2, T3, T4, T5, object?>? _provider;
|
||||
private Delegate? _unsubscriber;
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label,
|
||||
(Action<Action<T1, T2, T3, T4, T5>> Add, Action<Action<T1, T2, T3, T4, T5>> Del)? subscribe = null)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, T4, T5, object?>(label);
|
||||
subscribe?.Add(Invoke);
|
||||
_unsubscriber = subscribe?.Del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, Action<EventProvider<T1, T2, T3, T4, T5>> add,
|
||||
Action<EventProvider<T1, T2, T3, T4, T5>> del)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, T4, T5, object?>(label);
|
||||
add(this);
|
||||
_unsubscriber = del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider.Invoke"/>
|
||||
public void Invoke(T1 a, T2 b, T3 c, T4 d, T5 e)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider?.SendMessage(a, b, c, d, e);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Error($"Exception thrown on IPC event:\n{ex}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
switch (_unsubscriber)
|
||||
{
|
||||
case Action<Action<T1, T2, T3, T4, T5>> a:
|
||||
a(Invoke);
|
||||
break;
|
||||
case Action<EventProvider<T1, T2, T3, T4, T5>> b:
|
||||
b(this);
|
||||
break;
|
||||
}
|
||||
|
||||
_unsubscriber = null;
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~EventProvider()
|
||||
=> Dispose();
|
||||
}
|
582
Penumbra.Api/Helpers/EventSubscriber.cs
Normal file
582
Penumbra.Api/Helpers/EventSubscriber.cs
Normal file
@@ -0,0 +1,582 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
using Dalamud.Plugin.Services;
|
||||
|
||||
namespace Penumbra.Api.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Specialized disposable Subscriber for Events.<para />
|
||||
/// Subscriptions are wrapped to be individually exception-safe.<para/>
|
||||
/// Can be enabled and disabled.<para/>
|
||||
/// </summary>
|
||||
public sealed class EventSubscriber : IDisposable
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly IPluginLog _log;
|
||||
private readonly Dictionary<Action, Action> _delegates = new();
|
||||
private ICallGateSubscriber<object?>? _subscriber;
|
||||
private bool _disabled;
|
||||
|
||||
public EventSubscriber(IDalamudPluginInterface pi, string label, params Action[] actions)
|
||||
{
|
||||
_label = label;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<object?>(label);
|
||||
foreach (var action in actions)
|
||||
Event += action;
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable all currently subscribed actions registered with this EventSubscriber.
|
||||
/// Does nothing if it is already enabled.
|
||||
/// </summary>
|
||||
public void Enable()
|
||||
{
|
||||
if (_disabled && _subscriber != null)
|
||||
{
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Subscribe(action);
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disable all subscribed actions registered with this EventSubscriber.
|
||||
/// Does nothing if it is already disabled.
|
||||
/// Does not forget the actions, only disables them.
|
||||
/// </summary>
|
||||
public void Disable()
|
||||
{
|
||||
if (!_disabled)
|
||||
{
|
||||
if (_subscriber != null)
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Unsubscribe(action);
|
||||
|
||||
_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add or remove an action to the IPC event, if it is valid.
|
||||
/// </summary>
|
||||
public event Action Event
|
||||
{
|
||||
add
|
||||
{
|
||||
if (_subscriber != null && !_delegates.ContainsKey(value))
|
||||
{
|
||||
void Action()
|
||||
{
|
||||
try
|
||||
{
|
||||
value();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception invoking IPC event {_label}:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
if (_delegates.TryAdd(value, Action) && !_disabled)
|
||||
_subscriber.Subscribe(Action);
|
||||
}
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (_subscriber != null && _delegates.Remove(value, out var action))
|
||||
_subscriber.Unsubscribe(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disable();
|
||||
_subscriber = null;
|
||||
_delegates.Clear();
|
||||
}
|
||||
|
||||
~EventSubscriber()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber"/> </summary>
|
||||
public sealed class EventSubscriber<T1> : IDisposable
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly IPluginLog _log;
|
||||
private readonly Dictionary<Action<T1>, Action<T1>> _delegates = new();
|
||||
private ICallGateSubscriber<T1, object?>? _subscriber;
|
||||
private bool _disabled;
|
||||
|
||||
public EventSubscriber(IDalamudPluginInterface pi, string label, params Action<T1>[] actions)
|
||||
{
|
||||
_label = label;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, object?>(label);
|
||||
foreach (var action in actions)
|
||||
Event += action;
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Enable"/> </summary>
|
||||
public void Enable()
|
||||
{
|
||||
if (_disabled && _subscriber != null)
|
||||
{
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Subscribe(action);
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Disable"/> </summary>
|
||||
public void Disable()
|
||||
{
|
||||
if (!_disabled)
|
||||
{
|
||||
if (_subscriber != null)
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Unsubscribe(action);
|
||||
|
||||
_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Event"/> </summary>
|
||||
public event Action<T1> Event
|
||||
{
|
||||
add
|
||||
{
|
||||
if (_subscriber != null && !_delegates.ContainsKey(value))
|
||||
{
|
||||
void Action(T1 a)
|
||||
{
|
||||
try
|
||||
{
|
||||
value(a);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception invoking IPC event {_label}:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
if (_delegates.TryAdd(value, Action) && !_disabled)
|
||||
_subscriber.Subscribe(Action);
|
||||
}
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (_subscriber != null && _delegates.Remove(value, out var action))
|
||||
_subscriber.Unsubscribe(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disable();
|
||||
_subscriber = null;
|
||||
_delegates.Clear();
|
||||
}
|
||||
|
||||
~EventSubscriber()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber"/> </summary>
|
||||
public sealed class EventSubscriber<T1, T2> : IDisposable
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly IPluginLog _log;
|
||||
private readonly Dictionary<Action<T1, T2>, Action<T1, T2>> _delegates = new();
|
||||
private ICallGateSubscriber<T1, T2, object?>? _subscriber;
|
||||
private bool _disabled;
|
||||
|
||||
public EventSubscriber(IDalamudPluginInterface pi, string label, params Action<T1, T2>[] actions)
|
||||
{
|
||||
_label = label;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, object?>(label);
|
||||
foreach (var action in actions)
|
||||
Event += action;
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Enable"/> </summary>
|
||||
public void Enable()
|
||||
{
|
||||
if (_disabled && _subscriber != null)
|
||||
{
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Subscribe(action);
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Disable"/> </summary>
|
||||
public void Disable()
|
||||
{
|
||||
if (!_disabled)
|
||||
{
|
||||
if (_subscriber != null)
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Unsubscribe(action);
|
||||
|
||||
_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Event"/> </summary>
|
||||
public event Action<T1, T2> Event
|
||||
{
|
||||
add
|
||||
{
|
||||
if (_subscriber != null && !_delegates.ContainsKey(value))
|
||||
{
|
||||
void Action(T1 a, T2 b)
|
||||
{
|
||||
try
|
||||
{
|
||||
value(a, b);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception invoking IPC event {_label}:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
if (_delegates.TryAdd(value, Action) && !_disabled)
|
||||
_subscriber.Subscribe(Action);
|
||||
}
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (_subscriber != null && _delegates.Remove(value, out var action))
|
||||
_subscriber.Unsubscribe(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disable();
|
||||
_subscriber = null;
|
||||
_delegates.Clear();
|
||||
}
|
||||
|
||||
~EventSubscriber()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber"/> </summary>
|
||||
public sealed class EventSubscriber<T1, T2, T3> : IDisposable
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly IPluginLog _log;
|
||||
private readonly Dictionary<Action<T1, T2, T3>, Action<T1, T2, T3>> _delegates = [];
|
||||
private ICallGateSubscriber<T1, T2, T3, object?>? _subscriber;
|
||||
private bool _disabled;
|
||||
|
||||
public EventSubscriber(IDalamudPluginInterface pi, string label, params Action<T1, T2, T3>[] actions)
|
||||
{
|
||||
_label = label;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, object?>(label);
|
||||
foreach (var action in actions)
|
||||
Event += action;
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Enable"/> </summary>
|
||||
public void Enable()
|
||||
{
|
||||
if (_disabled && _subscriber != null)
|
||||
{
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Subscribe(action);
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Disable"/> </summary>
|
||||
public void Disable()
|
||||
{
|
||||
if (!_disabled)
|
||||
{
|
||||
if (_subscriber != null)
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Unsubscribe(action);
|
||||
|
||||
_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Event"/> </summary>
|
||||
public event Action<T1, T2, T3> Event
|
||||
{
|
||||
add
|
||||
{
|
||||
if (_subscriber != null && !_delegates.ContainsKey(value))
|
||||
{
|
||||
void Action(T1 a, T2 b, T3 c)
|
||||
{
|
||||
try
|
||||
{
|
||||
value(a, b, c);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception invoking IPC event {_label}:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
if (_delegates.TryAdd(value, Action) && !_disabled)
|
||||
_subscriber.Subscribe(Action);
|
||||
}
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (_subscriber != null && _delegates.Remove(value, out var action))
|
||||
_subscriber.Unsubscribe(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disable();
|
||||
_subscriber = null;
|
||||
_delegates.Clear();
|
||||
}
|
||||
|
||||
~EventSubscriber()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber"/> </summary>
|
||||
public sealed class EventSubscriber<T1, T2, T3, T4> : IDisposable
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly IPluginLog _log;
|
||||
private readonly Dictionary<Action<T1, T2, T3, T4>, Action<T1, T2, T3, T4>> _delegates = new();
|
||||
private ICallGateSubscriber<T1, T2, T3, T4, object?>? _subscriber;
|
||||
private bool _disabled;
|
||||
|
||||
public EventSubscriber(IDalamudPluginInterface pi, string label, params Action<T1, T2, T3, T4>[] actions)
|
||||
{
|
||||
_label = label;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, T4, object?>(label);
|
||||
foreach (var action in actions)
|
||||
Event += action;
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Enable"/> </summary>
|
||||
public void Enable()
|
||||
{
|
||||
if (_disabled && _subscriber != null)
|
||||
{
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Subscribe(action);
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Disable"/> </summary>
|
||||
public void Disable()
|
||||
{
|
||||
if (!_disabled)
|
||||
{
|
||||
if (_subscriber != null)
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Unsubscribe(action);
|
||||
|
||||
_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Event"/> </summary>
|
||||
public event Action<T1, T2, T3, T4> Event
|
||||
{
|
||||
add
|
||||
{
|
||||
if (_subscriber != null && !_delegates.ContainsKey(value))
|
||||
{
|
||||
void Action(T1 a, T2 b, T3 c, T4 d)
|
||||
{
|
||||
try
|
||||
{
|
||||
value(a, b, c, d);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception invoking IPC event {_label}:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
if (_delegates.TryAdd(value, Action) && !_disabled)
|
||||
_subscriber.Subscribe(Action);
|
||||
}
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (_subscriber != null && _delegates.Remove(value, out var action))
|
||||
_subscriber.Unsubscribe(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disable();
|
||||
_subscriber = null;
|
||||
_delegates.Clear();
|
||||
}
|
||||
|
||||
~EventSubscriber()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber"/> </summary>
|
||||
public sealed class EventSubscriber<T1, T2, T3, T4, T5> : IDisposable
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly IPluginLog _log;
|
||||
private readonly Dictionary<Action<T1, T2, T3, T4, T5>, Action<T1, T2, T3, T4, T5>> _delegates = new();
|
||||
private ICallGateSubscriber<T1, T2, T3, T4, T5, object?>? _subscriber;
|
||||
private bool _disabled;
|
||||
|
||||
public EventSubscriber(IDalamudPluginInterface pi, string label, params Action<T1, T2, T3, T4, T5>[] actions)
|
||||
{
|
||||
_label = label;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, T4, T5, object?>(label);
|
||||
foreach (var action in actions)
|
||||
Event += action;
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Enable"/> </summary>
|
||||
public void Enable()
|
||||
{
|
||||
if (_disabled && _subscriber != null)
|
||||
{
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Subscribe(action);
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Disable"/> </summary>
|
||||
public void Disable()
|
||||
{
|
||||
if (!_disabled)
|
||||
{
|
||||
if (_subscriber != null)
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Unsubscribe(action);
|
||||
|
||||
_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Event"/> </summary>
|
||||
public event Action<T1, T2, T3, T4, T5> Event
|
||||
{
|
||||
add
|
||||
{
|
||||
if (_subscriber != null && !_delegates.ContainsKey(value))
|
||||
{
|
||||
void Action(T1 a, T2 b, T3 c, T4 d, T5 e)
|
||||
{
|
||||
try
|
||||
{
|
||||
value(a, b, c, d, e);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Error($"Exception invoking IPC event {_label}:\n{ex}");
|
||||
}
|
||||
}
|
||||
|
||||
if (_delegates.TryAdd(value, Action) && !_disabled)
|
||||
_subscriber.Subscribe(Action);
|
||||
}
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (_subscriber != null && _delegates.Remove(value, out var action))
|
||||
_subscriber.Unsubscribe(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disable();
|
||||
_subscriber = null;
|
||||
_delegates.Clear();
|
||||
}
|
||||
|
||||
~EventSubscriber()
|
||||
=> Dispose();
|
||||
}
|
223
Penumbra.Api/Helpers/FuncProvider.cs
Normal file
223
Penumbra.Api/Helpers/FuncProvider.cs
Normal file
@@ -0,0 +1,223 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
|
||||
namespace Penumbra.Api.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Specialized disposable Provider for Funcs.
|
||||
/// </summary>
|
||||
public sealed class FuncProvider<TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncProvider{TRet}"/>
|
||||
public sealed class FuncProvider<T1, TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<T1, TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncProvider{TRet}"/>
|
||||
public sealed class FuncProvider<T1, T2, TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, T2, TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<T1, T2, TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncProvider{TRet}"/>
|
||||
public sealed class FuncProvider<T1, T2, T3, TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, T2, T3, TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<T1, T2, T3, TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncProvider{TRet}"/>
|
||||
public sealed class FuncProvider<T1, T2, T3, T4, TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, T2, T3, T4, TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<T1, T2, T3, T4, TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, T4, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncProvider{TRet}"/>
|
||||
public sealed class FuncProvider<T1, T2, T3, T4, T5, TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, T2, T3, T4, T5, TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<T1, T2, T3, T4, T5, TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, T4, T5, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncProvider{TRet}"/>
|
||||
public sealed class FuncProvider<T1, T2, T3, T4, T5, T6, TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, T2, T3, T4, T5, T6, TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<T1, T2, T3, T4, T5, T6, TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, T4, T5, T6, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
217
Penumbra.Api/Helpers/FuncSubscriber.cs
Normal file
217
Penumbra.Api/Helpers/FuncSubscriber.cs
Normal file
@@ -0,0 +1,217 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
using Dalamud.Plugin.Ipc.Exceptions;
|
||||
|
||||
namespace Penumbra.Api.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Specialized subscriber only allowing to invoke functions with a return.
|
||||
/// </summary>
|
||||
public class FuncSubscriber<TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<TRet>? _subscriber;
|
||||
|
||||
/// <summary> Whether the subscriber could successfully be created. </summary>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Invoke the function. See the source of the subscriber for details.</summary>
|
||||
protected TRet Invoke()
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc() : throw new IpcNotReadyError(_label);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
public class FuncSubscriber<T1, TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<T1, TRet>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Invoke"/>
|
||||
protected TRet Invoke(T1 a)
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc(a) : throw new IpcNotReadyError(_label);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
public class FuncSubscriber<T1, T2, TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<T1, T2, TRet>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Invoke"/>
|
||||
protected TRet Invoke(T1 a, T2 b)
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc(a, b) : throw new IpcNotReadyError(_label);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
public class FuncSubscriber<T1, T2, T3, TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<T1, T2, T3, TRet>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Invoke"/>
|
||||
protected TRet Invoke(T1 a, T2 b, T3 c)
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc(a, b, c) : throw new IpcNotReadyError(_label);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
public class FuncSubscriber<T1, T2, T3, T4, TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<T1, T2, T3, T4, TRet>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, T4, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Invoke"/>
|
||||
protected TRet Invoke(T1 a, T2 b, T3 c, T4 d)
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc(a, b, c, d) : throw new IpcNotReadyError(_label);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
public class FuncSubscriber<T1, T2, T3, T4, T5, TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<T1, T2, T3, T4, T5, TRet>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, T4, T5, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Invoke"/>
|
||||
protected TRet Invoke(T1 a, T2 b, T3 c, T4 d, T5 e)
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc(a, b, c, d, e) : throw new IpcNotReadyError(_label);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
public class FuncSubscriber<T1, T2, T3, T4, T5, T6, TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<T1, T2, T3, T4, T5, T6, TRet>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, T4, T5, T6, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Invoke"/>
|
||||
protected TRet Invoke(T1 a, T2 b, T3 c, T4 d, T5 e, T6 f)
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc(a, b, c, d, e, f) : throw new IpcNotReadyError(_label);
|
||||
}
|
26
Penumbra.Api/Helpers/PluginLogHelper.cs
Normal file
26
Penumbra.Api/Helpers/PluginLogHelper.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Dalamud.IoC;
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Services;
|
||||
|
||||
namespace Penumbra.Api.Helpers;
|
||||
|
||||
internal class PluginLogHelper
|
||||
{
|
||||
[PluginService]
|
||||
private static IPluginLog? _log { get; set; }
|
||||
|
||||
private PluginLogHelper(IDalamudPluginInterface pi)
|
||||
=> pi.Inject(this);
|
||||
|
||||
public static void WriteError(IDalamudPluginInterface pi, string errorMessage)
|
||||
=> GetLog(pi).Error(errorMessage);
|
||||
|
||||
public static IPluginLog GetLog(IDalamudPluginInterface pi)
|
||||
{
|
||||
if (_log != null)
|
||||
return _log;
|
||||
|
||||
_ = new PluginLogHelper(pi);
|
||||
return _log!;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user