Initial commit: AetherBags + KamiToolKit for FC Gitea
Debug Build and Test / Build against Latest Dalamud (push) Has been cancelled
Debug Build and Test / Build against Staging Dalamud (push) Has been cancelled

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-08 14:46:31 -05:00
commit 8db4ce6094
375 changed files with 34124 additions and 0 deletions
@@ -0,0 +1,44 @@
using System;
using System.Runtime.InteropServices;
using FFXIVClientStructs.FFXIV.Component.GUI;
using static FFXIVClientStructs.FFXIV.Component.GUI.AtkModuleInterface;
namespace KamiToolKit.Classes;
public unsafe class CustomEventInterface : IDisposable {
private readonly AtkEventInterface* eventInterface;
private AtkEventInterface.Delegates.ReceiveEvent? receiveEventDelegate;
private AtkEventInterface.Delegates.ReceiveEventWithResult? receiveEventWithResultDelegate;
public CustomEventInterface(AtkEventInterface.Delegates.ReceiveEvent eventHandler, AtkEventInterface.Delegates.ReceiveEventWithResult? receiveEventWithResult = null) {
receiveEventDelegate = eventHandler;
receiveEventWithResultDelegate = receiveEventWithResult;
eventInterface = NativeMemoryHelper.UiAlloc<AtkEventInterface>();
eventInterface->VirtualTable = (AtkEventInterface.AtkEventInterfaceVirtualTable*)NativeMemoryHelper.Malloc((ulong)sizeof(void*) * 2);
eventInterface->VirtualTable->ReceiveEvent = (delegate* unmanaged<AtkEventInterface*, AtkValue*, AtkValue*, uint, ulong, AtkValue*>)Marshal.GetFunctionPointerForDelegate(receiveEventDelegate);
if (receiveEventWithResultDelegate is not null) {
eventInterface->VirtualTable->ReceiveEventWithResult = (delegate* unmanaged<AtkEventInterface*, AtkValue*, AtkValue*, uint, ulong, AtkValue*>)Marshal.GetFunctionPointerForDelegate(receiveEventWithResultDelegate);
}
else {
eventInterface->VirtualTable->ReceiveEventWithResult = (delegate* unmanaged<AtkEventInterface*, AtkValue*, AtkValue*, uint, ulong, AtkValue*>)(delegate* unmanaged<void>)&NullSub;
}
}
public void Dispose() {
if (eventInterface is null) return;
NativeMemoryHelper.Free(eventInterface->VirtualTable, (ulong)sizeof(void*) * 2);
NativeMemoryHelper.UiFree(eventInterface);
receiveEventDelegate = null;
receiveEventWithResultDelegate = null;
}
[UnmanagedCallersOnly] private static void NullSub() { }
public static implicit operator AtkEventInterface*(CustomEventInterface listener) => listener.eventInterface;
}