Files
Craftimizer/Craftimizer/Utils/Ipc.cs
T
JonKazama-Hellion b598c03e9e Apply csharpier reflow across source tree
Reformats the entire Craftimizer source tree with dotnet csharpier 1.2.6
to match the Hellion Forge house style (matches what HellionChat enforces
in its pre-push pipeline). Pure whitespace + using-block sorting; no
semantic changes.

This is a one-time noisy commit. Future code edits in this fork should
land csharpier-clean because the pre-push hook (introduced in the next
commit) runs `dotnet csharpier check Craftimizer/` as Block C of the
preflight gate.

Trade-off acknowledged: this widens the merge gap with upstream
Craftimizer should Asriel ever resume maintenance. Given the upstream
has been dormant since FFXIV 7.4 and the fork is light-rename only
(internal namespaces unchanged), the marginal cost is acceptable.
2026-05-26 20:21:21 +02:00

82 lines
2.9 KiB
C#

using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using Craftimizer.Plugin;
using Dalamud.Plugin;
using DotNext.Collections.Generic;
using DotNext.Reflection;
namespace Craftimizer.Utils;
public sealed class Ipc
{
[AttributeUsage(AttributeTargets.Property)]
private sealed class IPCCallAttribute(string? name) : Attribute
{
public string? Name { get; } = name;
}
public Ipc()
{
foreach (var prop in typeof(Ipc).GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
if (prop.GetCustomAttribute<IPCCallAttribute>() is not { } attr)
continue;
if (prop.GetMethod is not { } getMethod)
throw new InvalidOperationException("Property must have a getter");
if (!getMethod.IsDefined<CompilerGeneratedAttribute>())
throw new InvalidOperationException("Property must have an auto getter");
var type = prop.PropertyType;
if (!typeof(Delegate).IsAssignableFrom(type))
throw new InvalidOperationException("Property type must be a delegate");
if (type.GetMethod("Invoke") is not { } typeMethod)
throw new InvalidOperationException("Delegate type has no Invoke");
var returnsVoid = typeMethod.ReturnType == typeof(void);
var propSubscriber = typeof(IDalamudPluginInterface).GetMethod(
"GetIpcSubscriber",
typeMethod.GetParameters().Length + 1,
[typeof(string)]
);
if (propSubscriber is null)
throw new InvalidOperationException("GetIpcSubscriber method not found");
var callGateSubscriber = propSubscriber
.MakeGenericMethod([
.. typeMethod.GetParameterTypes(),
returnsVoid ? typeof(int) : typeMethod.ReturnType,
])
.Invoke(Service.PluginInterface, [attr.Name ?? prop.Name]);
if (callGateSubscriber is null)
throw new InvalidOperationException("CallGateSubscriber is null");
var invokeFunc = callGateSubscriber
.GetType()
.GetMethod(returnsVoid ? "InvokeAction" : "InvokeFunc");
if (invokeFunc is null)
throw new InvalidOperationException("Subscriber Invoke method not found");
prop.SetValue(this, Delegate.CreateDelegate(type, callGateSubscriber, invokeFunc));
Log.Debug($"Bound {prop.Name} IPC to {type}");
}
}
[IPCCall("MacroMate.IsAvailable")]
public Func<bool> MacroMateIsAvailable { get; private set; } = null!;
[IPCCall("MacroMate.CreateOrUpdateMacro")]
public Func<string, string, string?, uint?, bool> MacroMateCreateMacro { get; private set; } =
null!;
[IPCCall("MacroMate.ValidateGroupPath")]
public Func<string, (bool, string?)> MacroMateValidateGroupPath { get; private set; } = null!;
}