mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-16 05:34:16 +01:00
Compare commits
20 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8334836b6a | ||
|
|
2d096d9b33 | ||
|
|
e100ec2abd | ||
|
|
71b0a757e9 | ||
|
|
0b55dc3e10 | ||
|
|
a39763f161 | ||
|
|
201c9cfcf2 | ||
|
|
e07bda7e58 | ||
|
|
b88a6bb616 | ||
|
|
e53ccdbcc0 | ||
|
|
97df73acea | ||
|
|
2806e59dba | ||
|
|
24caa1cb18 | ||
|
|
5d08170333 | ||
|
|
d0110f7251 | ||
|
|
8ed1af30df | ||
|
|
c45c6aafe1 | ||
|
|
2029a0f8a6 | ||
|
|
8cced4c1d7 | ||
|
|
b18b8b40e5 |
18 changed files with 248 additions and 82 deletions
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
<PropertyGroup Label="Feature">
|
<PropertyGroup Label="Feature">
|
||||||
<Description>XIV Launcher addon framework</Description>
|
<Description>XIV Launcher addon framework</Description>
|
||||||
<DalamudVersion>13.0.0.13</DalamudVersion>
|
<DalamudVersion>13.0.0.16</DalamudVersion>
|
||||||
<AssemblyVersion>$(DalamudVersion)</AssemblyVersion>
|
<AssemblyVersion>$(DalamudVersion)</AssemblyVersion>
|
||||||
<Version>$(DalamudVersion)</Version>
|
<Version>$(DalamudVersion)</Version>
|
||||||
<FileVersion>$(DalamudVersion)</FileVersion>
|
<FileVersion>$(DalamudVersion)</FileVersion>
|
||||||
|
|
|
||||||
|
|
@ -82,8 +82,13 @@ internal sealed class DataManager : IInternalDisposableService, IDataManager
|
||||||
var tsInfo =
|
var tsInfo =
|
||||||
JsonConvert.DeserializeObject<LauncherTroubleshootingInfo>(
|
JsonConvert.DeserializeObject<LauncherTroubleshootingInfo>(
|
||||||
dalamud.StartInfo.TroubleshootingPackData);
|
dalamud.StartInfo.TroubleshootingPackData);
|
||||||
this.HasModifiedGameDataFiles =
|
|
||||||
tsInfo?.IndexIntegrity is LauncherTroubleshootingInfo.IndexIntegrityResult.Failed or LauncherTroubleshootingInfo.IndexIntegrityResult.Exception;
|
// Don't fail for IndexIntegrityResult.Exception, since the check during launch has a very small timeout
|
||||||
|
// this.HasModifiedGameDataFiles =
|
||||||
|
// tsInfo?.IndexIntegrity is LauncherTroubleshootingInfo.IndexIntegrityResult.Failed;
|
||||||
|
|
||||||
|
// TODO: Put above back when check in XL is fixed
|
||||||
|
this.HasModifiedGameDataFiles = false;
|
||||||
|
|
||||||
if (this.HasModifiedGameDataFiles)
|
if (this.HasModifiedGameDataFiles)
|
||||||
Log.Verbose("Game data integrity check failed!\n{TsData}", dalamud.StartInfo.TroubleshootingPackData);
|
Log.Verbose("Game data integrity check failed!\n{TsData}", dalamud.StartInfo.TroubleshootingPackData);
|
||||||
|
|
|
||||||
|
|
@ -305,7 +305,8 @@ internal class GameInventory : IInternalDisposableService
|
||||||
private GameInventoryItem[] CreateItemsArray(int length)
|
private GameInventoryItem[] CreateItemsArray(int length)
|
||||||
{
|
{
|
||||||
var items = new GameInventoryItem[length];
|
var items = new GameInventoryItem[length];
|
||||||
items.Initialize();
|
foreach (ref var item in items.AsSpan())
|
||||||
|
item = new();
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
using Dalamud.Bindings.ImGui;
|
using Dalamud.Bindings.ImGui;
|
||||||
|
using Dalamud.Console;
|
||||||
using Dalamud.Memory;
|
using Dalamud.Memory;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
|
|
||||||
|
|
@ -37,6 +38,8 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler
|
||||||
private readonly WndProcDelegate wndProcDelegate;
|
private readonly WndProcDelegate wndProcDelegate;
|
||||||
private readonly nint platformNamePtr;
|
private readonly nint platformNamePtr;
|
||||||
|
|
||||||
|
private readonly IConsoleVariable<bool> cvLogMouseEvents;
|
||||||
|
|
||||||
private ViewportHandler viewportHandler;
|
private ViewportHandler viewportHandler;
|
||||||
|
|
||||||
private int mouseButtonsDown;
|
private int mouseButtonsDown;
|
||||||
|
|
@ -87,6 +90,11 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler
|
||||||
this.cursors[(int)ImGuiMouseCursor.ResizeNwse] = LoadCursorW(default, IDC.IDC_SIZENWSE);
|
this.cursors[(int)ImGuiMouseCursor.ResizeNwse] = LoadCursorW(default, IDC.IDC_SIZENWSE);
|
||||||
this.cursors[(int)ImGuiMouseCursor.Hand] = LoadCursorW(default, IDC.IDC_HAND);
|
this.cursors[(int)ImGuiMouseCursor.Hand] = LoadCursorW(default, IDC.IDC_HAND);
|
||||||
this.cursors[(int)ImGuiMouseCursor.NotAllowed] = LoadCursorW(default, IDC.IDC_NO);
|
this.cursors[(int)ImGuiMouseCursor.NotAllowed] = LoadCursorW(default, IDC.IDC_NO);
|
||||||
|
|
||||||
|
this.cvLogMouseEvents = Service<ConsoleManager>.Get().AddVariable(
|
||||||
|
"imgui.log_mouse_events",
|
||||||
|
"Log mouse events to console for debugging",
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -267,11 +275,23 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler
|
||||||
case WM.WM_XBUTTONDOWN:
|
case WM.WM_XBUTTONDOWN:
|
||||||
case WM.WM_XBUTTONDBLCLK:
|
case WM.WM_XBUTTONDBLCLK:
|
||||||
{
|
{
|
||||||
|
if (this.cvLogMouseEvents.Value)
|
||||||
|
{
|
||||||
|
Log.Verbose(
|
||||||
|
"Handle MouseDown {Btn} WantCaptureMouse: {Want} mouseButtonsDown: {Down}",
|
||||||
|
GetButton(msg, wParam),
|
||||||
|
io.WantCaptureMouse,
|
||||||
|
this.mouseButtonsDown);
|
||||||
|
}
|
||||||
|
|
||||||
var button = GetButton(msg, wParam);
|
var button = GetButton(msg, wParam);
|
||||||
if (io.WantCaptureMouse)
|
if (io.WantCaptureMouse)
|
||||||
{
|
{
|
||||||
if (this.mouseButtonsDown == 0 && GetCapture() == nint.Zero)
|
if (this.mouseButtonsDown == 0 && GetCapture() == nint.Zero)
|
||||||
|
{
|
||||||
SetCapture(hWndCurrent);
|
SetCapture(hWndCurrent);
|
||||||
|
}
|
||||||
|
|
||||||
this.mouseButtonsDown |= 1 << button;
|
this.mouseButtonsDown |= 1 << button;
|
||||||
io.AddMouseButtonEvent(button, true);
|
io.AddMouseButtonEvent(button, true);
|
||||||
return default(LRESULT);
|
return default(LRESULT);
|
||||||
|
|
@ -288,12 +308,28 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler
|
||||||
case WM.WM_MBUTTONUP:
|
case WM.WM_MBUTTONUP:
|
||||||
case WM.WM_XBUTTONUP:
|
case WM.WM_XBUTTONUP:
|
||||||
{
|
{
|
||||||
|
if (this.cvLogMouseEvents.Value)
|
||||||
|
{
|
||||||
|
Log.Verbose(
|
||||||
|
"Handle MouseUp {Btn} WantCaptureMouse: {Want} mouseButtonsDown: {Down}",
|
||||||
|
GetButton(msg, wParam),
|
||||||
|
io.WantCaptureMouse,
|
||||||
|
this.mouseButtonsDown);
|
||||||
|
}
|
||||||
|
|
||||||
var button = GetButton(msg, wParam);
|
var button = GetButton(msg, wParam);
|
||||||
if (io.WantCaptureMouse)
|
|
||||||
|
// Need to check if we captured the button event away from the game here, otherwise the game might get
|
||||||
|
// a down event but no up event, causing the cursor to get stuck.
|
||||||
|
// Can happen if WantCaptureMouse becomes true in between down and up
|
||||||
|
if (io.WantCaptureMouse && (this.mouseButtonsDown & (1 << button)) != 0)
|
||||||
{
|
{
|
||||||
this.mouseButtonsDown &= ~(1 << button);
|
this.mouseButtonsDown &= ~(1 << button);
|
||||||
if (this.mouseButtonsDown == 0 && GetCapture() == hWndCurrent)
|
if (this.mouseButtonsDown == 0 && GetCapture() == hWndCurrent)
|
||||||
|
{
|
||||||
ReleaseCapture();
|
ReleaseCapture();
|
||||||
|
}
|
||||||
|
|
||||||
io.AddMouseButtonEvent(button, false);
|
io.AddMouseButtonEvent(button, false);
|
||||||
return default(LRESULT);
|
return default(LRESULT);
|
||||||
}
|
}
|
||||||
|
|
@ -458,7 +494,12 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler
|
||||||
// (This is the position you can get with ::GetCursorPos() or WM_MOUSEMOVE + ::ClientToScreen(). In theory adding viewport->Pos to a client position would also be the same.)
|
// (This is the position you can get with ::GetCursorPos() or WM_MOUSEMOVE + ::ClientToScreen(). In theory adding viewport->Pos to a client position would also be the same.)
|
||||||
var mousePos = mouseScreenPos;
|
var mousePos = mouseScreenPos;
|
||||||
if ((io.ConfigFlags & ImGuiConfigFlags.ViewportsEnable) == 0)
|
if ((io.ConfigFlags & ImGuiConfigFlags.ViewportsEnable) == 0)
|
||||||
ClientToScreen(focusedWindow, &mousePos);
|
{
|
||||||
|
// Use game window, otherwise, positions are calculated based on the focused window which might not be the game.
|
||||||
|
// Leads to offsets.
|
||||||
|
ClientToScreen(this.hWnd, &mousePos);
|
||||||
|
}
|
||||||
|
|
||||||
io.AddMousePosEvent(mousePos.x, mousePos.y);
|
io.AddMousePosEvent(mousePos.x, mousePos.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,7 @@ internal class SeStringRenderer : IServiceType
|
||||||
|
|
||||||
// This also does argument validation for drawParams. Do it here.
|
// This also does argument validation for drawParams. Do it here.
|
||||||
// `using var` makes a struct read-only, but we do want to modify it.
|
// `using var` makes a struct read-only, but we do want to modify it.
|
||||||
var stateStorage = new SeStringDrawState(
|
using var stateStorage = new SeStringDrawState(
|
||||||
sss,
|
sss,
|
||||||
drawParams,
|
drawParams,
|
||||||
ThreadSafety.IsMainThread ? this.colorStackSetMainThread : new(this.colorStackSetMainThread.ColorTypes),
|
ThreadSafety.IsMainThread ? this.colorStackSetMainThread : new(this.colorStackSetMainThread.ColorTypes),
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,9 @@ public record struct SeStringDrawParams
|
||||||
public SeStringReplacementEntity.GetEntityDelegate? GetEntity { get; set; }
|
public SeStringReplacementEntity.GetEntityDelegate? GetEntity { get; set; }
|
||||||
|
|
||||||
/// <summary>Gets or sets the screen offset of the left top corner.</summary>
|
/// <summary>Gets or sets the screen offset of the left top corner.</summary>
|
||||||
/// <value>Screen offset to draw at, or <c>null</c> to use <see cref="ImGui.GetCursorScreenPos()"/>.</value>
|
/// <value>Screen offset to draw at, or <c>null</c> to use <see cref="ImGui.GetCursorScreenPos()"/>, if no <see cref="TargetDrawList"/>
|
||||||
|
/// is specified. Otherwise, you must specify it (for example, by passing <see cref="ImGui.GetCursorScreenPos()"/> when passing the window
|
||||||
|
/// draw list.</value>
|
||||||
public Vector2? ScreenOffset { get; set; }
|
public Vector2? ScreenOffset { get; set; }
|
||||||
|
|
||||||
/// <summary>Gets or sets the font to use.</summary>
|
/// <summary>Gets or sets the font to use.</summary>
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
|
|
||||||
using Lumina.Text.Payloads;
|
using Lumina.Text.Payloads;
|
||||||
using Lumina.Text.ReadOnly;
|
using Lumina.Text.ReadOnly;
|
||||||
|
|
||||||
|
|
@ -17,7 +18,7 @@ namespace Dalamud.Interface.ImGuiSeStringRenderer;
|
||||||
|
|
||||||
/// <summary>Calculated values from <see cref="SeStringDrawParams"/> using ImGui styles.</summary>
|
/// <summary>Calculated values from <see cref="SeStringDrawParams"/> using ImGui styles.</summary>
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public unsafe ref struct SeStringDrawState
|
public unsafe ref struct SeStringDrawState : IDisposable
|
||||||
{
|
{
|
||||||
private static readonly int ChannelCount = Enum.GetValues<SeStringDrawChannel>().Length;
|
private static readonly int ChannelCount = Enum.GetValues<SeStringDrawChannel>().Length;
|
||||||
|
|
||||||
|
|
@ -63,11 +64,12 @@ public unsafe ref struct SeStringDrawState
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.drawList = ssdp.TargetDrawList.Value;
|
this.drawList = ssdp.TargetDrawList.Value;
|
||||||
this.ScreenOffset = Vector2.Zero;
|
this.ScreenOffset = ssdp.ScreenOffset ?? Vector2.Zero;
|
||||||
|
|
||||||
// API14: Remove, always throw
|
// API14: Remove, always throw
|
||||||
if (ThreadSafety.IsMainThread)
|
if (ThreadSafety.IsMainThread)
|
||||||
{
|
{
|
||||||
|
this.ScreenOffset = ssdp.ScreenOffset ?? ImGui.GetCursorScreenPos();
|
||||||
this.FontSize = ssdp.FontSize ?? ImGui.GetFontSize();
|
this.FontSize = ssdp.FontSize ?? ImGui.GetFontSize();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -193,6 +195,9 @@ public unsafe ref struct SeStringDrawState
|
||||||
/// <summary>Gets the text fragments.</summary>
|
/// <summary>Gets the text fragments.</summary>
|
||||||
internal List<TextFragment> Fragments { get; }
|
internal List<TextFragment> Fragments { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose() => this.splitter.ClearFreeMemory();
|
||||||
|
|
||||||
/// <summary>Sets the current channel in the ImGui draw list splitter.</summary>
|
/// <summary>Sets the current channel in the ImGui draw list splitter.</summary>
|
||||||
/// <param name="channelIndex">Channel to switch to.</param>
|
/// <param name="channelIndex">Channel to switch to.</param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
|
|
||||||
|
|
@ -669,6 +669,8 @@ internal class DalamudInterface : IInternalDisposableService
|
||||||
{
|
{
|
||||||
using var barColor = ImRaii.PushColor(ImGuiCol.WindowBg, new Vector4(0.060f, 0.060f, 0.060f, 0.773f));
|
using var barColor = ImRaii.PushColor(ImGuiCol.WindowBg, new Vector4(0.060f, 0.060f, 0.060f, 0.773f));
|
||||||
barColor.Push(ImGuiCol.MenuBarBg, Vector4.Zero);
|
barColor.Push(ImGuiCol.MenuBarBg, Vector4.Zero);
|
||||||
|
barColor.Push(ImGuiCol.Border, Vector4.Zero);
|
||||||
|
barColor.Push(ImGuiCol.BorderShadow, Vector4.Zero);
|
||||||
if (ImGui.BeginMainMenuBar())
|
if (ImGui.BeginMainMenuBar())
|
||||||
{
|
{
|
||||||
var pluginManager = Service<PluginManager>.Get();
|
var pluginManager = Service<PluginManager>.Get();
|
||||||
|
|
|
||||||
|
|
@ -48,12 +48,20 @@ internal class PluginIpcWidget : IDataWindowWidget
|
||||||
|
|
||||||
this.ipcPub.RegisterAction(msg =>
|
this.ipcPub.RegisterAction(msg =>
|
||||||
{
|
{
|
||||||
Log.Information("Data action was called: {Msg}", msg);
|
Log.Information(
|
||||||
|
"Data action was called: {Msg}\n" +
|
||||||
|
" Context: {Context}",
|
||||||
|
msg,
|
||||||
|
this.ipcPub.GetContext());
|
||||||
});
|
});
|
||||||
|
|
||||||
this.ipcPub.RegisterFunc(msg =>
|
this.ipcPub.RegisterFunc(msg =>
|
||||||
{
|
{
|
||||||
Log.Information("Data func was called: {Msg}", msg);
|
Log.Information(
|
||||||
|
"Data func was called: {Msg}\n" +
|
||||||
|
" Context: {Context}",
|
||||||
|
msg,
|
||||||
|
this.ipcPub.GetContext());
|
||||||
return Guid.NewGuid().ToString();
|
return Guid.NewGuid().ToString();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -61,14 +69,8 @@ internal class PluginIpcWidget : IDataWindowWidget
|
||||||
if (this.ipcSub == null)
|
if (this.ipcSub == null)
|
||||||
{
|
{
|
||||||
this.ipcSub = new CallGatePubSub<string, string>("dataDemo1");
|
this.ipcSub = new CallGatePubSub<string, string>("dataDemo1");
|
||||||
this.ipcSub.Subscribe(_ =>
|
this.ipcSub.Subscribe(_ => { Log.Information("PONG1"); });
|
||||||
{
|
this.ipcSub.Subscribe(_ => { Log.Information("PONG2"); });
|
||||||
Log.Information("PONG1");
|
|
||||||
});
|
|
||||||
this.ipcSub.Subscribe(_ =>
|
|
||||||
{
|
|
||||||
Log.Information("PONG2");
|
|
||||||
});
|
|
||||||
this.ipcSub.Subscribe(_ => throw new Exception("PONG3"));
|
this.ipcSub.Subscribe(_ => throw new Exception("PONG3"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,12 +80,21 @@ internal class PluginIpcWidget : IDataWindowWidget
|
||||||
|
|
||||||
this.ipcPubGo.RegisterAction(go =>
|
this.ipcPubGo.RegisterAction(go =>
|
||||||
{
|
{
|
||||||
Log.Information("Data action was called: {Name}", go?.Name);
|
Log.Information(
|
||||||
|
"Data action was called: {Name}" +
|
||||||
|
"\n Context: {Context}",
|
||||||
|
go?.Name,
|
||||||
|
this.ipcPubGo.GetContext());
|
||||||
});
|
});
|
||||||
|
|
||||||
this.ipcPubGo.RegisterFunc(go =>
|
this.ipcPubGo.RegisterFunc(go =>
|
||||||
{
|
{
|
||||||
Log.Information("Data func was called: {Name}", go?.Name);
|
Log.Information(
|
||||||
|
"Data func was called: {Name}\n" +
|
||||||
|
" Context: {Context}",
|
||||||
|
go?.Name,
|
||||||
|
this.ipcPubGo.GetContext());
|
||||||
|
|
||||||
return "test";
|
return "test";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -177,6 +177,24 @@ internal unsafe class SeStringRendererTestWidget : IDataWindowWidget
|
||||||
ImGuiHelpers.SeStringWrapped(this.logkind.Value.Data.Span, this.style);
|
ImGuiHelpers.SeStringWrapped(this.logkind.Value.Data.Span, this.style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ImGui.CollapsingHeader("Draw into drawlist"))
|
||||||
|
{
|
||||||
|
ImGuiHelpers.ScaledDummy(100);
|
||||||
|
ImGui.SetCursorScreenPos(ImGui.GetItemRectMin() + ImGui.GetStyle().FramePadding);
|
||||||
|
var clipMin = ImGui.GetItemRectMin() + ImGui.GetStyle().FramePadding;
|
||||||
|
var clipMax = ImGui.GetItemRectMax() - ImGui.GetStyle().FramePadding;
|
||||||
|
clipMin.Y = MathF.Max(clipMin.Y, ImGui.GetWindowPos().Y);
|
||||||
|
clipMax.Y = MathF.Min(clipMax.Y, ImGui.GetWindowPos().Y + ImGui.GetWindowHeight());
|
||||||
|
|
||||||
|
var dl = ImGui.GetWindowDrawList();
|
||||||
|
dl.PushClipRect(clipMin, clipMax);
|
||||||
|
ImGuiHelpers.CompileSeStringWrapped(
|
||||||
|
"<icon(1)>Test test<icon(1)>",
|
||||||
|
new SeStringDrawParams
|
||||||
|
{ Color = 0xFFFFFFFF, WrapWidth = float.MaxValue, TargetDrawList = dl });
|
||||||
|
dl.PopClipRect();
|
||||||
|
}
|
||||||
|
|
||||||
if (ImGui.CollapsingHeader("Addon Table"u8))
|
if (ImGui.CollapsingHeader("Addon Table"u8))
|
||||||
{
|
{
|
||||||
if (ImGui.BeginTable("Addon Sheet"u8, 3))
|
if (ImGui.BeginTable("Addon Sheet"u8, 3))
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ internal class PresetModel
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether this preset is in the default state.
|
/// Gets a value indicating whether this preset is in the default state.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
public bool IsDefault =>
|
public bool IsDefault =>
|
||||||
!this.IsPinned &&
|
!this.IsPinned &&
|
||||||
!this.IsClickThrough &&
|
!this.IsClickThrough &&
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ public abstract class Window
|
||||||
Click = _ =>
|
Click = _ =>
|
||||||
{
|
{
|
||||||
this.internalIsClickthrough = false;
|
this.internalIsClickthrough = false;
|
||||||
this.presetDirty = false;
|
this.presetDirty = true;
|
||||||
ImGui.OpenPopup(AdditionsPopupName);
|
ImGui.OpenPopup(AdditionsPopupName);
|
||||||
},
|
},
|
||||||
Priority = int.MinValue,
|
Priority = int.MinValue,
|
||||||
|
|
@ -672,16 +672,13 @@ public abstract class Window
|
||||||
Task.FromResult<IDalamudTextureWrap>(tex));
|
Task.FromResult<IDalamudTextureWrap>(tex));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.hasError)
|
|
||||||
{
|
|
||||||
this.PostDraw();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (isErrorStylePushed)
|
if (isErrorStylePushed)
|
||||||
{
|
{
|
||||||
Style.StyleModelV1.DalamudStandard.Pop();
|
Style.StyleModelV1.DalamudStandard.Pop();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.PostDraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.PostHandlePreset(persistence);
|
this.PostHandlePreset(persistence);
|
||||||
|
|
@ -864,7 +861,7 @@ public abstract class Window
|
||||||
foreach (var button in this.allButtons)
|
foreach (var button in this.allButtons)
|
||||||
{
|
{
|
||||||
if (this.internalIsClickthrough && !button.AvailableClickthrough)
|
if (this.internalIsClickthrough && !button.AvailableClickthrough)
|
||||||
return;
|
continue;
|
||||||
|
|
||||||
Vector2 position = new(titleBarRect.Max.X - padR - buttonSize, titleBarRect.Min.Y + style.FramePadding.Y);
|
Vector2 position = new(titleBarRect.Max.X - padR - buttonSize, titleBarRect.Min.Y + style.FramePadding.Y);
|
||||||
padR += buttonSize + style.ItemInnerSpacing.X;
|
padR += buttonSize + style.ItemInnerSpacing.X;
|
||||||
|
|
@ -908,7 +905,7 @@ public abstract class Window
|
||||||
private void DrawErrorMessage()
|
private void DrawErrorMessage()
|
||||||
{
|
{
|
||||||
// TODO: Once window systems are services, offer to reload the plugin
|
// TODO: Once window systems are services, offer to reload the plugin
|
||||||
ImGui.TextColoredWrapped(ImGuiColors.DalamudRed,Loc.Localize("WindowSystemErrorOccurred", "An error occurred while rendering this window. Please contact the developer for details."));
|
ImGui.TextColoredWrapped(ImGuiColors.DalamudRed, Loc.Localize("WindowSystemErrorOccurred", "An error occurred while rendering this window. Please contact the developer for details."));
|
||||||
|
|
||||||
ImGuiHelpers.ScaledDummy(5);
|
ImGuiHelpers.ScaledDummy(5);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -248,75 +248,75 @@ internal sealed class DalamudPluginInterface : IDalamudPluginInterface, IDisposa
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICallGateProvider<TRet> GetIpcProvider<TRet>(string name)
|
public ICallGateProvider<TRet> GetIpcProvider<TRet>(string name)
|
||||||
=> new CallGatePubSub<TRet>(name);
|
=> new CallGatePubSub<TRet>(name, this.plugin);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICallGateProvider<T1, TRet> GetIpcProvider<T1, TRet>(string name)
|
public ICallGateProvider<T1, TRet> GetIpcProvider<T1, TRet>(string name)
|
||||||
=> new CallGatePubSub<T1, TRet>(name);
|
=> new CallGatePubSub<T1, TRet>(name, this.plugin);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICallGateProvider<T1, T2, TRet> GetIpcProvider<T1, T2, TRet>(string name)
|
public ICallGateProvider<T1, T2, TRet> GetIpcProvider<T1, T2, TRet>(string name)
|
||||||
=> new CallGatePubSub<T1, T2, TRet>(name);
|
=> new CallGatePubSub<T1, T2, TRet>(name, this.plugin);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICallGateProvider<T1, T2, T3, TRet> GetIpcProvider<T1, T2, T3, TRet>(string name)
|
public ICallGateProvider<T1, T2, T3, TRet> GetIpcProvider<T1, T2, T3, TRet>(string name)
|
||||||
=> new CallGatePubSub<T1, T2, T3, TRet>(name);
|
=> new CallGatePubSub<T1, T2, T3, TRet>(name, this.plugin);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICallGateProvider<T1, T2, T3, T4, TRet> GetIpcProvider<T1, T2, T3, T4, TRet>(string name)
|
public ICallGateProvider<T1, T2, T3, T4, TRet> GetIpcProvider<T1, T2, T3, T4, TRet>(string name)
|
||||||
=> new CallGatePubSub<T1, T2, T3, T4, TRet>(name);
|
=> new CallGatePubSub<T1, T2, T3, T4, TRet>(name, this.plugin);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICallGateProvider<T1, T2, T3, T4, T5, TRet> GetIpcProvider<T1, T2, T3, T4, T5, TRet>(string name)
|
public ICallGateProvider<T1, T2, T3, T4, T5, TRet> GetIpcProvider<T1, T2, T3, T4, T5, TRet>(string name)
|
||||||
=> new CallGatePubSub<T1, T2, T3, T4, T5, TRet>(name);
|
=> new CallGatePubSub<T1, T2, T3, T4, T5, TRet>(name, this.plugin);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICallGateProvider<T1, T2, T3, T4, T5, T6, TRet> GetIpcProvider<T1, T2, T3, T4, T5, T6, TRet>(string name)
|
public ICallGateProvider<T1, T2, T3, T4, T5, T6, TRet> GetIpcProvider<T1, T2, T3, T4, T5, T6, TRet>(string name)
|
||||||
=> new CallGatePubSub<T1, T2, T3, T4, T5, T6, TRet>(name);
|
=> new CallGatePubSub<T1, T2, T3, T4, T5, T6, TRet>(name, this.plugin);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICallGateProvider<T1, T2, T3, T4, T5, T6, T7, TRet> GetIpcProvider<T1, T2, T3, T4, T5, T6, T7, TRet>(string name)
|
public ICallGateProvider<T1, T2, T3, T4, T5, T6, T7, TRet> GetIpcProvider<T1, T2, T3, T4, T5, T6, T7, TRet>(string name)
|
||||||
=> new CallGatePubSub<T1, T2, T3, T4, T5, T6, T7, TRet>(name);
|
=> new CallGatePubSub<T1, T2, T3, T4, T5, T6, T7, TRet>(name, this.plugin);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICallGateProvider<T1, T2, T3, T4, T5, T6, T7, T8, TRet> GetIpcProvider<T1, T2, T3, T4, T5, T6, T7, T8, TRet>(string name)
|
public ICallGateProvider<T1, T2, T3, T4, T5, T6, T7, T8, TRet> GetIpcProvider<T1, T2, T3, T4, T5, T6, T7, T8, TRet>(string name)
|
||||||
=> new CallGatePubSub<T1, T2, T3, T4, T5, T6, T7, T8, TRet>(name);
|
=> new CallGatePubSub<T1, T2, T3, T4, T5, T6, T7, T8, TRet>(name, this.plugin);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICallGateSubscriber<TRet> GetIpcSubscriber<TRet>(string name)
|
public ICallGateSubscriber<TRet> GetIpcSubscriber<TRet>(string name)
|
||||||
=> new CallGatePubSub<TRet>(name);
|
=> new CallGatePubSub<TRet>(name, this.plugin);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICallGateSubscriber<T1, TRet> GetIpcSubscriber<T1, TRet>(string name)
|
public ICallGateSubscriber<T1, TRet> GetIpcSubscriber<T1, TRet>(string name)
|
||||||
=> new CallGatePubSub<T1, TRet>(name);
|
=> new CallGatePubSub<T1, TRet>(name, this.plugin);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICallGateSubscriber<T1, T2, TRet> GetIpcSubscriber<T1, T2, TRet>(string name)
|
public ICallGateSubscriber<T1, T2, TRet> GetIpcSubscriber<T1, T2, TRet>(string name)
|
||||||
=> new CallGatePubSub<T1, T2, TRet>(name);
|
=> new CallGatePubSub<T1, T2, TRet>(name, this.plugin);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICallGateSubscriber<T1, T2, T3, TRet> GetIpcSubscriber<T1, T2, T3, TRet>(string name)
|
public ICallGateSubscriber<T1, T2, T3, TRet> GetIpcSubscriber<T1, T2, T3, TRet>(string name)
|
||||||
=> new CallGatePubSub<T1, T2, T3, TRet>(name);
|
=> new CallGatePubSub<T1, T2, T3, TRet>(name, this.plugin);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICallGateSubscriber<T1, T2, T3, T4, TRet> GetIpcSubscriber<T1, T2, T3, T4, TRet>(string name)
|
public ICallGateSubscriber<T1, T2, T3, T4, TRet> GetIpcSubscriber<T1, T2, T3, T4, TRet>(string name)
|
||||||
=> new CallGatePubSub<T1, T2, T3, T4, TRet>(name);
|
=> new CallGatePubSub<T1, T2, T3, T4, TRet>(name, this.plugin);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICallGateSubscriber<T1, T2, T3, T4, T5, TRet> GetIpcSubscriber<T1, T2, T3, T4, T5, TRet>(string name)
|
public ICallGateSubscriber<T1, T2, T3, T4, T5, TRet> GetIpcSubscriber<T1, T2, T3, T4, T5, TRet>(string name)
|
||||||
=> new CallGatePubSub<T1, T2, T3, T4, T5, TRet>(name);
|
=> new CallGatePubSub<T1, T2, T3, T4, T5, TRet>(name, this.plugin);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICallGateSubscriber<T1, T2, T3, T4, T5, T6, TRet> GetIpcSubscriber<T1, T2, T3, T4, T5, T6, TRet>(string name)
|
public ICallGateSubscriber<T1, T2, T3, T4, T5, T6, TRet> GetIpcSubscriber<T1, T2, T3, T4, T5, T6, TRet>(string name)
|
||||||
=> new CallGatePubSub<T1, T2, T3, T4, T5, T6, TRet>(name);
|
=> new CallGatePubSub<T1, T2, T3, T4, T5, T6, TRet>(name, this.plugin);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICallGateSubscriber<T1, T2, T3, T4, T5, T6, T7, TRet> GetIpcSubscriber<T1, T2, T3, T4, T5, T6, T7, TRet>(string name)
|
public ICallGateSubscriber<T1, T2, T3, T4, T5, T6, T7, TRet> GetIpcSubscriber<T1, T2, T3, T4, T5, T6, T7, TRet>(string name)
|
||||||
=> new CallGatePubSub<T1, T2, T3, T4, T5, T6, T7, TRet>(name);
|
=> new CallGatePubSub<T1, T2, T3, T4, T5, T6, T7, TRet>(name, this.plugin);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ICallGateSubscriber<T1, T2, T3, T4, T5, T6, T7, T8, TRet> GetIpcSubscriber<T1, T2, T3, T4, T5, T6, T7, T8, TRet>(string name)
|
public ICallGateSubscriber<T1, T2, T3, T4, T5, T6, T7, T8, TRet> GetIpcSubscriber<T1, T2, T3, T4, T5, T6, T7, T8, TRet>(string name)
|
||||||
=> new CallGatePubSub<T1, T2, T3, T4, T5, T6, T7, T8, TRet>(name);
|
=> new CallGatePubSub<T1, T2, T3, T4, T5, T6, T7, T8, TRet>(name, this.plugin);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,9 @@ public interface ICallGateProvider
|
||||||
|
|
||||||
/// <inheritdoc cref="CallGatePubSubBase.UnregisterFunc"/>
|
/// <inheritdoc cref="CallGatePubSubBase.UnregisterFunc"/>
|
||||||
public void UnregisterFunc();
|
public void UnregisterFunc();
|
||||||
|
|
||||||
|
/// <inheritdoc cref="CallGatePubSubBase.GetContext"/>
|
||||||
|
public IpcContext? GetContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="ICallGateProvider"/>
|
/// <inheritdoc cref="ICallGateProvider"/>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@ using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
using Dalamud.Plugin.Internal.Types;
|
||||||
using Dalamud.Plugin.Ipc.Exceptions;
|
using Dalamud.Plugin.Ipc.Exceptions;
|
||||||
using Dalamud.Plugin.Ipc.Internal.Converters;
|
using Dalamud.Plugin.Ipc.Internal.Converters;
|
||||||
|
|
||||||
|
|
@ -16,6 +18,8 @@ namespace Dalamud.Plugin.Ipc.Internal;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class CallGateChannel
|
internal class CallGateChannel
|
||||||
{
|
{
|
||||||
|
private readonly ThreadLocal<IpcContext> ipcExecutionContext = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The actual storage.
|
/// The actual storage.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -145,6 +149,21 @@ internal class CallGateChannel
|
||||||
return (TRet)result;
|
return (TRet)result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void SetInvocationContext(IpcContext ipcContext)
|
||||||
|
{
|
||||||
|
this.ipcExecutionContext.Value = ipcContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal IpcContext? GetInvocationContext()
|
||||||
|
{
|
||||||
|
return this.ipcExecutionContext.IsValueCreated ? this.ipcExecutionContext.Value : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ClearInvocationContext()
|
||||||
|
{
|
||||||
|
this.ipcExecutionContext.Value = null;
|
||||||
|
}
|
||||||
|
|
||||||
private void CheckAndConvertArgs(object?[]? args, MethodInfo methodInfo)
|
private void CheckAndConvertArgs(object?[]? args, MethodInfo methodInfo)
|
||||||
{
|
{
|
||||||
var paramTypes = methodInfo.GetParameters()
|
var paramTypes = methodInfo.GetParameters()
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
using Dalamud.Plugin.Internal.Types;
|
||||||
|
|
||||||
#pragma warning disable SA1402 // File may only contain a single type
|
#pragma warning disable SA1402 // File may only contain a single type
|
||||||
|
|
||||||
namespace Dalamud.Plugin.Ipc.Internal;
|
namespace Dalamud.Plugin.Ipc.Internal;
|
||||||
|
|
@ -5,9 +7,9 @@ namespace Dalamud.Plugin.Ipc.Internal;
|
||||||
/// <inheritdoc cref="CallGatePubSubBase"/>
|
/// <inheritdoc cref="CallGatePubSubBase"/>
|
||||||
internal class CallGatePubSub<TRet> : CallGatePubSubBase, ICallGateProvider<TRet>, ICallGateSubscriber<TRet>
|
internal class CallGatePubSub<TRet> : CallGatePubSubBase, ICallGateProvider<TRet>, ICallGateSubscriber<TRet>
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="CallGatePubSubBase(string)"/>
|
/// <inheritdoc cref="CallGatePubSubBase(string, LocalPlugin?)"/>
|
||||||
public CallGatePubSub(string name)
|
public CallGatePubSub(string name, LocalPlugin? owningPlugin = null)
|
||||||
: base(name)
|
: base(name, owningPlugin)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,9 +45,9 @@ internal class CallGatePubSub<TRet> : CallGatePubSubBase, ICallGateProvider<TRet
|
||||||
/// <inheritdoc cref="CallGatePubSubBase"/>
|
/// <inheritdoc cref="CallGatePubSubBase"/>
|
||||||
internal class CallGatePubSub<T1, TRet> : CallGatePubSubBase, ICallGateProvider<T1, TRet>, ICallGateSubscriber<T1, TRet>
|
internal class CallGatePubSub<T1, TRet> : CallGatePubSubBase, ICallGateProvider<T1, TRet>, ICallGateSubscriber<T1, TRet>
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="CallGatePubSubBase(string)"/>
|
/// <inheritdoc cref="CallGatePubSubBase(string, LocalPlugin?)"/>
|
||||||
public CallGatePubSub(string name)
|
public CallGatePubSub(string name, LocalPlugin? owningPlugin = null)
|
||||||
: base(name)
|
: base(name, owningPlugin)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,9 +83,9 @@ internal class CallGatePubSub<T1, TRet> : CallGatePubSubBase, ICallGateProvider<
|
||||||
/// <inheritdoc cref="CallGatePubSubBase"/>
|
/// <inheritdoc cref="CallGatePubSubBase"/>
|
||||||
internal class CallGatePubSub<T1, T2, TRet> : CallGatePubSubBase, ICallGateProvider<T1, T2, TRet>, ICallGateSubscriber<T1, T2, TRet>
|
internal class CallGatePubSub<T1, T2, TRet> : CallGatePubSubBase, ICallGateProvider<T1, T2, TRet>, ICallGateSubscriber<T1, T2, TRet>
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="CallGatePubSubBase(string)"/>
|
/// <inheritdoc cref="CallGatePubSubBase(string, LocalPlugin?)"/>
|
||||||
public CallGatePubSub(string name)
|
public CallGatePubSub(string name, LocalPlugin? owningPlugin = null)
|
||||||
: base(name)
|
: base(name, owningPlugin)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,9 +121,9 @@ internal class CallGatePubSub<T1, T2, TRet> : CallGatePubSubBase, ICallGateProvi
|
||||||
/// <inheritdoc cref="CallGatePubSubBase"/>
|
/// <inheritdoc cref="CallGatePubSubBase"/>
|
||||||
internal class CallGatePubSub<T1, T2, T3, TRet> : CallGatePubSubBase, ICallGateProvider<T1, T2, T3, TRet>, ICallGateSubscriber<T1, T2, T3, TRet>
|
internal class CallGatePubSub<T1, T2, T3, TRet> : CallGatePubSubBase, ICallGateProvider<T1, T2, T3, TRet>, ICallGateSubscriber<T1, T2, T3, TRet>
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="CallGatePubSubBase(string)"/>
|
/// <inheritdoc cref="CallGatePubSubBase(string, LocalPlugin?)"/>
|
||||||
public CallGatePubSub(string name)
|
public CallGatePubSub(string name, LocalPlugin? owningPlugin = null)
|
||||||
: base(name)
|
: base(name, owningPlugin)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -157,9 +159,9 @@ internal class CallGatePubSub<T1, T2, T3, TRet> : CallGatePubSubBase, ICallGateP
|
||||||
/// <inheritdoc cref="CallGatePubSubBase"/>
|
/// <inheritdoc cref="CallGatePubSubBase"/>
|
||||||
internal class CallGatePubSub<T1, T2, T3, T4, TRet> : CallGatePubSubBase, ICallGateProvider<T1, T2, T3, T4, TRet>, ICallGateSubscriber<T1, T2, T3, T4, TRet>
|
internal class CallGatePubSub<T1, T2, T3, T4, TRet> : CallGatePubSubBase, ICallGateProvider<T1, T2, T3, T4, TRet>, ICallGateSubscriber<T1, T2, T3, T4, TRet>
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="CallGatePubSubBase(string)"/>
|
/// <inheritdoc cref="CallGatePubSubBase(string, LocalPlugin?)"/>
|
||||||
public CallGatePubSub(string name)
|
public CallGatePubSub(string name, LocalPlugin? owningPlugin = null)
|
||||||
: base(name)
|
: base(name, owningPlugin)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -195,9 +197,9 @@ internal class CallGatePubSub<T1, T2, T3, T4, TRet> : CallGatePubSubBase, ICallG
|
||||||
/// <inheritdoc cref="CallGatePubSubBase"/>
|
/// <inheritdoc cref="CallGatePubSubBase"/>
|
||||||
internal class CallGatePubSub<T1, T2, T3, T4, T5, TRet> : CallGatePubSubBase, ICallGateProvider<T1, T2, T3, T4, T5, TRet>, ICallGateSubscriber<T1, T2, T3, T4, T5, TRet>
|
internal class CallGatePubSub<T1, T2, T3, T4, T5, TRet> : CallGatePubSubBase, ICallGateProvider<T1, T2, T3, T4, T5, TRet>, ICallGateSubscriber<T1, T2, T3, T4, T5, TRet>
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="CallGatePubSubBase(string)"/>
|
/// <inheritdoc cref="CallGatePubSubBase(string, LocalPlugin?)"/>
|
||||||
public CallGatePubSub(string name)
|
public CallGatePubSub(string name, LocalPlugin? owningPlugin = null)
|
||||||
: base(name)
|
: base(name, owningPlugin)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -233,9 +235,9 @@ internal class CallGatePubSub<T1, T2, T3, T4, T5, TRet> : CallGatePubSubBase, IC
|
||||||
/// <inheritdoc cref="CallGatePubSubBase"/>
|
/// <inheritdoc cref="CallGatePubSubBase"/>
|
||||||
internal class CallGatePubSub<T1, T2, T3, T4, T5, T6, TRet> : CallGatePubSubBase, ICallGateProvider<T1, T2, T3, T4, T5, T6, TRet>, ICallGateSubscriber<T1, T2, T3, T4, T5, T6, TRet>
|
internal class CallGatePubSub<T1, T2, T3, T4, T5, T6, TRet> : CallGatePubSubBase, ICallGateProvider<T1, T2, T3, T4, T5, T6, TRet>, ICallGateSubscriber<T1, T2, T3, T4, T5, T6, TRet>
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="CallGatePubSubBase(string)"/>
|
/// <inheritdoc cref="CallGatePubSubBase(string, LocalPlugin?)"/>
|
||||||
public CallGatePubSub(string name)
|
public CallGatePubSub(string name, LocalPlugin? owningPlugin = null)
|
||||||
: base(name)
|
: base(name, owningPlugin)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -271,9 +273,9 @@ internal class CallGatePubSub<T1, T2, T3, T4, T5, T6, TRet> : CallGatePubSubBase
|
||||||
/// <inheritdoc cref="CallGatePubSubBase"/>
|
/// <inheritdoc cref="CallGatePubSubBase"/>
|
||||||
internal class CallGatePubSub<T1, T2, T3, T4, T5, T6, T7, TRet> : CallGatePubSubBase, ICallGateProvider<T1, T2, T3, T4, T5, T6, T7, TRet>, ICallGateSubscriber<T1, T2, T3, T4, T5, T6, T7, TRet>
|
internal class CallGatePubSub<T1, T2, T3, T4, T5, T6, T7, TRet> : CallGatePubSubBase, ICallGateProvider<T1, T2, T3, T4, T5, T6, T7, TRet>, ICallGateSubscriber<T1, T2, T3, T4, T5, T6, T7, TRet>
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="CallGatePubSubBase(string)"/>
|
/// <inheritdoc cref="CallGatePubSubBase(string, LocalPlugin?)"/>
|
||||||
public CallGatePubSub(string name)
|
public CallGatePubSub(string name, LocalPlugin? owningPlugin = null)
|
||||||
: base(name)
|
: base(name, owningPlugin)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -309,9 +311,9 @@ internal class CallGatePubSub<T1, T2, T3, T4, T5, T6, T7, TRet> : CallGatePubSub
|
||||||
/// <inheritdoc cref="CallGatePubSubBase"/>
|
/// <inheritdoc cref="CallGatePubSubBase"/>
|
||||||
internal class CallGatePubSub<T1, T2, T3, T4, T5, T6, T7, T8, TRet> : CallGatePubSubBase, ICallGateProvider<T1, T2, T3, T4, T5, T6, T7, T8, TRet>, ICallGateSubscriber<T1, T2, T3, T4, T5, T6, T7, T8, TRet>
|
internal class CallGatePubSub<T1, T2, T3, T4, T5, T6, T7, T8, TRet> : CallGatePubSubBase, ICallGateProvider<T1, T2, T3, T4, T5, T6, T7, T8, TRet>, ICallGateSubscriber<T1, T2, T3, T4, T5, T6, T7, T8, TRet>
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="CallGatePubSubBase(string)"/>
|
/// <inheritdoc cref="CallGatePubSubBase(string, LocalPlugin?)"/>
|
||||||
public CallGatePubSub(string name)
|
public CallGatePubSub(string name, LocalPlugin? owningPlugin = null)
|
||||||
: base(name)
|
: base(name, owningPlugin)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,11 @@
|
||||||
|
using System.Reactive.Disposables;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
using Dalamud.Plugin.Internal.Types;
|
||||||
using Dalamud.Plugin.Ipc.Exceptions;
|
using Dalamud.Plugin.Ipc.Exceptions;
|
||||||
|
using Dalamud.Utility;
|
||||||
|
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
namespace Dalamud.Plugin.Ipc.Internal;
|
namespace Dalamud.Plugin.Ipc.Internal;
|
||||||
|
|
||||||
|
|
@ -11,9 +18,11 @@ internal abstract class CallGatePubSubBase
|
||||||
/// Initializes a new instance of the <see cref="CallGatePubSubBase"/> class.
|
/// Initializes a new instance of the <see cref="CallGatePubSubBase"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">The name of the IPC registration.</param>
|
/// <param name="name">The name of the IPC registration.</param>
|
||||||
protected CallGatePubSubBase(string name)
|
/// <param name="owningPlugin">The plugin that owns this IPC pubsub.</param>
|
||||||
|
protected CallGatePubSubBase(string name, LocalPlugin? owningPlugin)
|
||||||
{
|
{
|
||||||
this.Channel = Service<CallGate>.Get().GetOrCreateChannel(name);
|
this.Channel = Service<CallGate>.Get().GetOrCreateChannel(name);
|
||||||
|
this.OwningPlugin = owningPlugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -39,6 +48,11 @@ internal abstract class CallGatePubSubBase
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected CallGateChannel Channel { get; init; }
|
protected CallGateChannel Channel { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the plugin that owns this pubsub instance.
|
||||||
|
/// </summary>
|
||||||
|
protected LocalPlugin? OwningPlugin { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes the associated Action from this call gate, effectively disabling RPC calls.
|
/// Removes the associated Action from this call gate, effectively disabling RPC calls.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -53,6 +67,16 @@ internal abstract class CallGatePubSubBase
|
||||||
public void UnregisterFunc()
|
public void UnregisterFunc()
|
||||||
=> this.Channel.Func = null;
|
=> this.Channel.Func = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current context for this IPC call. This will only be present when called from within an IPC action
|
||||||
|
/// or function handler, and will be null otherwise.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns a potential IPC context.</returns>
|
||||||
|
public IpcContext? GetContext()
|
||||||
|
{
|
||||||
|
return this.Channel.GetInvocationContext();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Registers a <see cref="Delegate"/> for use by other plugins via RPC. This Delegate must satisfy the constraints
|
/// Registers a <see cref="Delegate"/> for use by other plugins via RPC. This Delegate must satisfy the constraints
|
||||||
/// of an <see cref="Action"/> type as defined by the interface, meaning they may not return a value and must have
|
/// of an <see cref="Action"/> type as defined by the interface, meaning they may not return a value and must have
|
||||||
|
|
@ -105,7 +129,12 @@ internal abstract class CallGatePubSubBase
|
||||||
/// <seealso cref="RegisterAction"/>
|
/// <seealso cref="RegisterAction"/>
|
||||||
/// <seealso cref="UnregisterAction"/>
|
/// <seealso cref="UnregisterAction"/>
|
||||||
private protected void InvokeAction(params object?[]? args)
|
private protected void InvokeAction(params object?[]? args)
|
||||||
=> this.Channel.InvokeAction(args);
|
{
|
||||||
|
using (this.BuildContext())
|
||||||
|
{
|
||||||
|
this.Channel.InvokeAction(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Executes the Function registered for this IPC call gate via <see cref="RegisterFunc"/>. This method is intended
|
/// Executes the Function registered for this IPC call gate via <see cref="RegisterFunc"/>. This method is intended
|
||||||
|
|
@ -120,7 +149,12 @@ internal abstract class CallGatePubSubBase
|
||||||
/// <seealso cref="RegisterFunc"/>
|
/// <seealso cref="RegisterFunc"/>
|
||||||
/// <seealso cref="UnregisterFunc"/>
|
/// <seealso cref="UnregisterFunc"/>
|
||||||
private protected TRet InvokeFunc<TRet>(params object?[]? args)
|
private protected TRet InvokeFunc<TRet>(params object?[]? args)
|
||||||
=> this.Channel.InvokeFunc<TRet>(args);
|
{
|
||||||
|
using (this.BuildContext())
|
||||||
|
{
|
||||||
|
return this.Channel.InvokeFunc<TRet>(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Send the given arguments to all subscribers (through <see cref="Subscribe"/>) of this IPC call gate. This method
|
/// Send the given arguments to all subscribers (through <see cref="Subscribe"/>) of this IPC call gate. This method
|
||||||
|
|
@ -132,4 +166,14 @@ internal abstract class CallGatePubSubBase
|
||||||
/// <param name="args">Delegate arguments.</param>
|
/// <param name="args">Delegate arguments.</param>
|
||||||
private protected void SendMessage(params object?[]? args)
|
private protected void SendMessage(params object?[]? args)
|
||||||
=> this.Channel.SendMessage(args);
|
=> this.Channel.SendMessage(args);
|
||||||
|
|
||||||
|
private IDisposable BuildContext()
|
||||||
|
{
|
||||||
|
this.Channel.SetInvocationContext(new IpcContext
|
||||||
|
{
|
||||||
|
SourcePlugin = this.OwningPlugin != null ? new ExposedPlugin(this.OwningPlugin) : null,
|
||||||
|
});
|
||||||
|
|
||||||
|
return Disposable.Create(() => { this.Channel.ClearInvocationContext(); });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
15
Dalamud/Plugin/Ipc/IpcContext.cs
Normal file
15
Dalamud/Plugin/Ipc/IpcContext.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
namespace Dalamud.Plugin.Ipc;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The context associated for an IPC call. Reads from ThreadLocal.
|
||||||
|
/// </summary>
|
||||||
|
public class IpcContext
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the plugin that initiated this IPC call.
|
||||||
|
/// </summary>
|
||||||
|
public IExposedPlugin? SourcePlugin { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override string ToString() => $"<IpcContext SourcePlugin={this.SourcePlugin?.Name ?? "null"}>";
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue