Update for 7.0, part 1
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Version>1.26.4</Version>
|
<Version>1.27.0</Version>
|
||||||
<TargetFramework>net8.0-windows</TargetFramework>
|
<TargetFramework>net8.0-windows</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
@@ -49,14 +49,13 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="DalamudPackager" Version="2.1.12"/>
|
<PackageReference Include="DalamudPackager" Version="2.1.13" />
|
||||||
<PackageReference Include="LiteDB" Version="5.0.19" />
|
<PackageReference Include="LiteDB" Version="5.0.19" />
|
||||||
<PackageReference Include="MessagePack" Version="2.5.140" />
|
<PackageReference Include="MessagePack" Version="2.5.140" />
|
||||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.4" />
|
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.4" />
|
||||||
<PackageReference Include="Pidgin" Version="3.2.2"/>
|
<PackageReference Include="Pidgin" Version="3.2.2"/>
|
||||||
<PackageReference Include="SharpDX.Direct2D1" Version="4.2.0"/>
|
<PackageReference Include="SharpDX.Direct2D1" Version="4.2.0"/>
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.4" />
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.4" />
|
||||||
<PackageReference Include="XivCommon" Version="9.0.0"/>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using Dalamud.Interface.Internal;
|
using Dalamud.Interface.Textures;
|
||||||
|
using Dalamud.Interface.Textures.TextureWraps;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using SixLabors.ImageSharp;
|
using SixLabors.ImageSharp;
|
||||||
@@ -208,7 +209,7 @@ public static class EmoteCache
|
|||||||
if (image.Length <= 0)
|
if (image.Length <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Texture = await Plugin.Interface.UiBuilder.LoadImageAsync(image);
|
Texture = await Plugin.TextureProvider.CreateFromImageAsync(image);
|
||||||
IsLoaded = true;
|
IsLoaded = true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -294,7 +295,7 @@ public static class EmoteCache
|
|||||||
|
|
||||||
var buffer = new byte[4 * frame.Width * frame.Height];
|
var buffer = new byte[4 * frame.Width * frame.Height];
|
||||||
frame.CopyPixelDataTo(buffer);
|
frame.CopyPixelDataTo(buffer);
|
||||||
var tex = await Plugin.Interface.UiBuilder.LoadImageRawAsync(buffer, frame.Width, frame.Height, 4);
|
var tex = await Plugin.TextureProvider.CreateFromRawAsync(RawImageSpecification.Rgba32(frame.Width, frame.Height), buffer);
|
||||||
frames.Add((tex, delay));
|
frames.Add((tex, delay));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ using Dalamud.Hooking;
|
|||||||
using Dalamud.Memory;
|
using Dalamud.Memory;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using Dalamud.Utility.Signatures;
|
using Dalamud.Utility.Signatures;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Network;
|
using FFXIVClientStructs.FFXIV.Application.Network;
|
||||||
using FFXIVClientStructs.FFXIV.Client.System.Framework;
|
using FFXIVClientStructs.FFXIV.Client.System.Framework;
|
||||||
using FFXIVClientStructs.FFXIV.Client.System.String;
|
using FFXIVClientStructs.FFXIV.Client.System.String;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
@@ -32,37 +32,25 @@ internal sealed unsafe class Chat : IDisposable
|
|||||||
[Signature("E8 ?? ?? ?? ?? 48 8D 4D A0 8B F8")]
|
[Signature("E8 ?? ?? ?? ?? 48 8D 4D A0 8B F8")]
|
||||||
private readonly delegate* unmanaged<nint, Utf8String*, nint, uint> GetKeybindNative = null!;
|
private readonly delegate* unmanaged<nint, Utf8String*, nint, uint> GetKeybindNative = null!;
|
||||||
|
|
||||||
[Signature("E8 ?? ?? ?? ?? 48 8D 4D 50 E8 ?? ?? ?? ?? 48 8B 17")]
|
[Signature("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC ?? 48 8D B9 ?? ?? ?? ?? 33 C0")]
|
||||||
private readonly delegate* unmanaged<RaptureLogModule*, ushort, Utf8String*, Utf8String*, ulong, ushort, byte, int, byte, void> PrintTellNative = null!;
|
private readonly delegate* unmanaged<RaptureLogModule*, ushort, Utf8String*, Utf8String*, ulong, ushort, byte, int, byte, void> PrintTellNative = null!;
|
||||||
|
|
||||||
[Signature("E8 ?? ?? ?? ?? 48 8D 4C 24 ?? E8 ?? ?? ?? ?? 48 8D 8C 24 ?? ?? ?? ?? E8 ?? ?? ?? ?? B0 01")]
|
[Signature("E8 ?? ?? ?? ?? 48 8D 4C 24 ?? E8 ?? ?? ?? ?? 48 8D 8C 24 ?? ?? ?? ?? E8 ?? ?? ?? ?? B0 01")]
|
||||||
private readonly delegate* unmanaged<NetworkModule*, ulong, ushort, Utf8String*, Utf8String*, byte, ulong, bool> SendTellNative = null!;
|
private readonly delegate* unmanaged<NetworkModule*, ulong, ushort, Utf8String*, Utf8String*, byte, ulong, bool> SendTellNative = null!;
|
||||||
|
|
||||||
// TODO Replace with CS version after https://github.com/aers/FFXIVClientStructs/pull/911
|
|
||||||
[Signature("E8 ?? ?? ?? ?? EB 0A 48 8D 4C 24 ?? E8 ?? ?? ?? ?? 48 8D 8D")]
|
|
||||||
private readonly delegate* unmanaged<Utf8String*, int, nint, void> SanitiseString = null!;
|
|
||||||
|
|
||||||
// Client::UI::AddonChatLog.OnRefresh
|
// Client::UI::AddonChatLog.OnRefresh
|
||||||
[Signature("40 53 56 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 49 8B F0 8B FA", DetourName = nameof(ChatLogRefreshDetour))]
|
[Signature("40 53 56 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 49 8B F0 8B FA", DetourName = nameof(ChatLogRefreshDetour))]
|
||||||
private Hook<ChatLogRefreshDelegate>? ChatLogRefreshHook { get; init; }
|
private Hook<ChatLogRefreshDelegate>? ChatLogRefreshHook { get; init; }
|
||||||
private delegate byte ChatLogRefreshDelegate(nint log, ushort eventId, AtkValue* value);
|
private delegate byte ChatLogRefreshDelegate(nint log, ushort eventId, AtkValue* value);
|
||||||
|
|
||||||
// TODO Replace all with delegate hooks in API X
|
private Hook<AgentChatLog.Delegates.ChangeChannelName> ChangeChannelNameHook { get; init; }
|
||||||
private Hook<ChangeChannelNameDelegate>? ChangeChannelNameHook { get; init; }
|
private Hook<RaptureShellModule.Delegates.ReplyInSelectedChatMode>? ReplyInSelectedChatModeHook { get; init; }
|
||||||
private delegate nint ChangeChannelNameDelegate(nint agent);
|
private Hook<RaptureShellModule.Delegates.SetContextTellTarget>? SetChatLogTellTargetHook { get; init; }
|
||||||
|
private Hook<RaptureShellModule.Delegates.SetContextTellTargetInForay>? EurekaContextMenuTellHook { get; init; }
|
||||||
private Hook<ReplyInSelectedChatModeDelegate>? ReplyInSelectedChatModeHook { get; init; }
|
|
||||||
private delegate void ReplyInSelectedChatModeDelegate(AgentInterface* agent);
|
|
||||||
|
|
||||||
private Hook<SetChatLogTellTarget>? SetChatLogTellTargetHook { get; init; }
|
|
||||||
private delegate byte SetChatLogTellTarget(nint a1, Utf8String* name, Utf8String* a3, ushort world, ulong contentId, ushort a6, byte a7);
|
|
||||||
|
|
||||||
private Hook<EurekaContextMenuTellDelegate>? EurekaContextMenuTellHook { get; init; }
|
|
||||||
private delegate void EurekaContextMenuTellDelegate(RaptureShellModule* param1, Utf8String* playerName, Utf8String* worldName, ushort world, ulong contentId, ushort param6);
|
|
||||||
|
|
||||||
// Pointers
|
// Pointers
|
||||||
|
|
||||||
[Signature("48 8D 15 ?? ?? ?? ?? 0F B6 C8 48 8D 05", ScanType = ScanType.StaticAddress)]
|
[Signature("48 8D 35 ?? ?? ?? ?? 8B 05", ScanType = ScanType.StaticAddress)]
|
||||||
private readonly char* CurrentCharacter = null!;
|
private readonly char* CurrentCharacter = null!;
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
@@ -91,16 +79,16 @@ internal sealed unsafe class Chat : IDisposable
|
|||||||
|
|
||||||
ChatLogRefreshHook?.Enable();
|
ChatLogRefreshHook?.Enable();
|
||||||
|
|
||||||
ChangeChannelNameHook = Plugin.GameInteropProvider.HookFromAddress<ChangeChannelNameDelegate>(AgentChatLog.Addresses.ChangeChannelName.Value, ChangeChannelNameDetour);
|
ChangeChannelNameHook = Plugin.GameInteropProvider.HookFromAddress<AgentChatLog.Delegates.ChangeChannelName>(AgentChatLog.MemberFunctionPointers.ChangeChannelName, ChangeChannelNameDetour);
|
||||||
ChangeChannelNameHook.Enable();
|
ChangeChannelNameHook.Enable();
|
||||||
|
|
||||||
ReplyInSelectedChatModeHook = Plugin.GameInteropProvider.HookFromAddress<ReplyInSelectedChatModeDelegate>(RaptureShellModule.Addresses.ReplyInSelectedChatMode.Value, ReplyInSelectedChatModeDetour);
|
ReplyInSelectedChatModeHook = Plugin.GameInteropProvider.HookFromAddress<RaptureShellModule.Delegates.ReplyInSelectedChatMode>(RaptureShellModule.MemberFunctionPointers.ReplyInSelectedChatMode, ReplyInSelectedChatModeDetour);
|
||||||
ReplyInSelectedChatModeHook.Enable();
|
ReplyInSelectedChatModeHook.Enable();
|
||||||
|
|
||||||
SetChatLogTellTargetHook = Plugin.GameInteropProvider.HookFromAddress<SetChatLogTellTarget>(RaptureShellModule.Addresses.SetContextTellTarget.Value, SetChatLogTellTargetDetour);
|
SetChatLogTellTargetHook = Plugin.GameInteropProvider.HookFromAddress<RaptureShellModule.Delegates.SetContextTellTarget>(RaptureShellModule.MemberFunctionPointers.SetContextTellTarget, SetChatLogTellTargetDetour);
|
||||||
SetChatLogTellTargetHook.Enable();
|
SetChatLogTellTargetHook.Enable();
|
||||||
|
|
||||||
EurekaContextMenuTellHook = Plugin.GameInteropProvider.HookFromAddress<EurekaContextMenuTellDelegate>(RaptureShellModule.Addresses.SetContextTellTargetInForay.Value, EurekaContextMenuTell);
|
EurekaContextMenuTellHook = Plugin.GameInteropProvider.HookFromAddress<RaptureShellModule.Delegates.SetContextTellTargetInForay>(RaptureShellModule.MemberFunctionPointers.SetContextTellTargetInForay, EurekaContextMenuTell);
|
||||||
EurekaContextMenuTellHook.Enable();
|
EurekaContextMenuTellHook.Enable();
|
||||||
|
|
||||||
Plugin.Framework.Update += InterceptKeybinds;
|
Plugin.Framework.Update += InterceptKeybinds;
|
||||||
@@ -124,19 +112,13 @@ internal sealed unsafe class Chat : IDisposable
|
|||||||
|
|
||||||
internal string? GetLinkshellName(uint idx)
|
internal string? GetLinkshellName(uint idx)
|
||||||
{
|
{
|
||||||
var instance = InfoProxyLinkShell.Instance();
|
var utf = InfoProxyChat.Instance()->GetLinkShellName(idx);
|
||||||
var lsInfo = instance->GetLinkshellInfo(idx);
|
|
||||||
if (lsInfo == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
// TODO APIX: use infoproxychat
|
|
||||||
var utf = instance->GetLinkshellName(*(ulong**)lsInfo);
|
|
||||||
return utf == null ? null : MemoryHelper.ReadStringNullTerminated((nint) utf);
|
return utf == null ? null : MemoryHelper.ReadStringNullTerminated((nint) utf);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal string? GetCrossLinkshellName(uint idx)
|
internal string? GetCrossLinkshellName(uint idx)
|
||||||
{
|
{
|
||||||
var utf = InfoProxyCrossWorldLinkShell.Instance()->GetCrossworldLinkshellName(idx);
|
var utf = InfoProxyCrossWorldLinkshell.Instance()->GetCrossworldLinkshellName(idx);
|
||||||
return utf == null ? null : utf->ToString();
|
return utf == null ? null : utf->ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,14 +328,11 @@ internal sealed unsafe class Chat : IDisposable
|
|||||||
|
|
||||||
private void Login()
|
private void Login()
|
||||||
{
|
{
|
||||||
if (ChangeChannelNameHook == null)
|
var agent = AgentChatLog.Instance();
|
||||||
return;
|
|
||||||
|
|
||||||
var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ChatLog);
|
|
||||||
if (agent == null)
|
if (agent == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ChangeChannelNameDetour((nint) agent);
|
ChangeChannelNameDetour(agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte ChatLogRefreshDetour(nint log, ushort eventId, AtkValue* value)
|
private byte ChatLogRefreshDetour(nint log, ushort eventId, AtkValue* value)
|
||||||
@@ -368,11 +347,12 @@ internal sealed unsafe class Chat : IDisposable
|
|||||||
{
|
{
|
||||||
// FIXME: this whole system sucks
|
// FIXME: this whole system sucks
|
||||||
// FIXME v2: I hate everything about this, but it works
|
// FIXME v2: I hate everything about this, but it works
|
||||||
|
|
||||||
Plugin.Framework.RunOnTick(() =>
|
Plugin.Framework.RunOnTick(() =>
|
||||||
{
|
{
|
||||||
string? input = null;
|
string? input = null;
|
||||||
|
|
||||||
var utf8Bytes = MemoryHelper.ReadRaw((nint) CurrentCharacter, 2);
|
var utf8Bytes = MemoryHelper.ReadRaw((nint)CurrentCharacter+0x4, 2);
|
||||||
var chars = Encoding.UTF8.GetString(utf8Bytes).ToCharArray();
|
var chars = Encoding.UTF8.GetString(utf8Bytes).ToCharArray();
|
||||||
if (chars.Length == 0)
|
if (chars.Length == 0)
|
||||||
return;
|
return;
|
||||||
@@ -381,6 +361,8 @@ internal sealed unsafe class Chat : IDisposable
|
|||||||
if (c != '\0' && !char.IsControl(c))
|
if (c != '\0' && !char.IsControl(c))
|
||||||
input = c.ToString();
|
input = c.ToString();
|
||||||
|
|
||||||
|
Plugin.Log.Information($"Input was {c}");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Activated?.Invoke(new ChatActivatedArgs(new ChannelSwitchInfo(null)) { Input = input, });
|
Activated?.Invoke(new ChatActivatedArgs(new ChannelSwitchInfo(null)) { Input = input, });
|
||||||
@@ -415,7 +397,7 @@ internal sealed unsafe class Chat : IDisposable
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private nint ChangeChannelNameDetour(nint agent)
|
private byte* ChangeChannelNameDetour(AgentChatLog* agent)
|
||||||
{
|
{
|
||||||
// Last ShB patch
|
// Last ShB patch
|
||||||
// +0x40 = chat channel (byte or uint?)
|
// +0x40 = chat channel (byte or uint?)
|
||||||
@@ -423,23 +405,17 @@ internal sealed unsafe class Chat : IDisposable
|
|||||||
// +0x48 = pointer to channel name string
|
// +0x48 = pointer to channel name string
|
||||||
// +0xDA = player name string for tells
|
// +0xDA = player name string for tells
|
||||||
// +0x120 = player world id for tells
|
// +0x120 = player world id for tells
|
||||||
var ret = ChangeChannelNameHook!.Original(agent);
|
var ret = ChangeChannelNameHook.Original(agent);
|
||||||
if (agent == nint.Zero)
|
if ((nint) agent == nint.Zero)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
var channel = (uint) RaptureShellModule.Instance()->ChatType;
|
var channel = (uint) RaptureShellModule.Instance()->ChatType;
|
||||||
if (channel is 17 or 18)
|
if (channel is 17 or 18)
|
||||||
channel = (uint) InputChannel.Tell;
|
channel = (uint) InputChannel.Tell;
|
||||||
|
|
||||||
SeString? name = null;
|
var name = SeString.Parse(agent->ChannelLabel);
|
||||||
var namePtrPtr = (byte**) (agent + 0x48);
|
|
||||||
if (namePtrPtr != null)
|
|
||||||
{
|
|
||||||
var namePtr = *namePtrPtr;
|
|
||||||
name = MemoryHelper.ReadSeStringNullTerminated((nint) namePtr);
|
|
||||||
if (name.Payloads.Count == 0)
|
if (name.Payloads.Count == 0)
|
||||||
name = null;
|
name = null;
|
||||||
}
|
|
||||||
|
|
||||||
if (name == null)
|
if (name == null)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -452,7 +428,7 @@ internal sealed unsafe class Chat : IDisposable
|
|||||||
ushort worldId = 0;
|
ushort worldId = 0;
|
||||||
if (channel == (uint) InputChannel.Tell)
|
if (channel == (uint) InputChannel.Tell)
|
||||||
{
|
{
|
||||||
playerName = MemoryHelper.ReadStringNullTerminated(agent + 0xDA);
|
playerName = MemoryHelper.ReadStringNullTerminated((nint) agent + 0xDA);
|
||||||
worldId = *(ushort*) (agent + 0x120);
|
worldId = *(ushort*) (agent + 0x120);
|
||||||
Plugin.Log.Debug($"Detected tell target '{playerName}'@{worldId}");
|
Plugin.Log.Debug($"Detected tell target '{playerName}'@{worldId}");
|
||||||
}
|
}
|
||||||
@@ -462,7 +438,7 @@ internal sealed unsafe class Chat : IDisposable
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReplyInSelectedChatModeDetour(AgentInterface* agent)
|
private void ReplyInSelectedChatModeDetour(RaptureShellModule* agent)
|
||||||
{
|
{
|
||||||
var replyMode = AgentChatLog.Instance()->ReplyChannel;
|
var replyMode = AgentChatLog.Instance()->ReplyChannel;
|
||||||
if (replyMode == -2)
|
if (replyMode == -2)
|
||||||
@@ -475,7 +451,7 @@ internal sealed unsafe class Chat : IDisposable
|
|||||||
ReplyInSelectedChatModeHook!.Original(agent);
|
ReplyInSelectedChatModeHook!.Original(agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte SetChatLogTellTargetDetour(nint a1, Utf8String* name, Utf8String* a3, ushort world, ulong contentId, ushort reason, byte a7)
|
private bool SetChatLogTellTargetDetour(RaptureShellModule* a1, Utf8String* name, Utf8String* a3, ushort world, ulong contentId, ushort reason, bool a7)
|
||||||
{
|
{
|
||||||
if (name != null)
|
if (name != null)
|
||||||
{
|
{
|
||||||
@@ -558,9 +534,7 @@ internal sealed unsafe class Chat : IDisposable
|
|||||||
|
|
||||||
private Keybind? GetKeybind(string id)
|
private Keybind? GetKeybind(string id)
|
||||||
{
|
{
|
||||||
var agent = (nint) Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.Configkey);
|
var agent = (nint) AgentModule.Instance()->GetAgentByInternalId(AgentId.Configkey);
|
||||||
if (agent == nint.Zero)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var a1 = *(void**) (agent + 0x78);
|
var a1 = *(void**) (agent + 0x78);
|
||||||
if (a1 == null)
|
if (a1 == null)
|
||||||
@@ -611,8 +585,8 @@ internal sealed unsafe class Chat : IDisposable
|
|||||||
AutoTranslate.ReplaceWithPayload(ref decoded);
|
AutoTranslate.ReplaceWithPayload(ref decoded);
|
||||||
using var decodedUtf8String = new Utf8String(decoded);
|
using var decodedUtf8String = new Utf8String(decoded);
|
||||||
|
|
||||||
|
var logModule = RaptureLogModule.Instance();
|
||||||
var networkModule = Framework.Instance()->GetNetworkModuleProxy()->NetworkModule;
|
var networkModule = Framework.Instance()->GetNetworkModuleProxy()->NetworkModule;
|
||||||
var logModule = Framework.Instance()->GetUiModule()->GetRaptureLogModule();
|
|
||||||
|
|
||||||
var ok = SendTellNative(networkModule, contentId, homeWorld, uName, encoded, (byte) reason, homeWorld);
|
var ok = SendTellNative(networkModule, contentId, homeWorld, uName, encoded, (byte) reason, homeWorld);
|
||||||
if (ok)
|
if (ok)
|
||||||
@@ -638,7 +612,7 @@ internal sealed unsafe class Chat : IDisposable
|
|||||||
{
|
{
|
||||||
var uC = Utf8String.FromString(c.ToString());
|
var uC = Utf8String.FromString(c.ToString());
|
||||||
|
|
||||||
SanitiseString(uC, 0x27F, nint.Zero);
|
uC->SanitizeString(0x27F, Utf8String.CreateEmpty());
|
||||||
var wasValid = uC->ToString().Length > 0;
|
var wasValid = uC->ToString().Length > 0;
|
||||||
|
|
||||||
uC->Dtor(true);
|
uC->Dtor(true);
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using Dalamud.Game;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.System.String;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
|
|
||||||
|
namespace ChatTwo.GameFunctions;
|
||||||
|
|
||||||
|
// From: https://git.anna.lgbt/anna/XivCommon/src/branch/main/XivCommon/Functions/Chat.cs
|
||||||
|
public class ChatCommon
|
||||||
|
{
|
||||||
|
private static class Signatures
|
||||||
|
{
|
||||||
|
internal const string SendChat = "48 89 5C 24 ?? 57 48 83 EC 20 48 8B FA 48 8B D9 45 84 C9";
|
||||||
|
}
|
||||||
|
|
||||||
|
private delegate void ProcessChatBoxDelegate(IntPtr uiModule, IntPtr message, IntPtr unused, byte a4);
|
||||||
|
private ProcessChatBoxDelegate? ProcessChatBox { get; }
|
||||||
|
|
||||||
|
internal ChatCommon(ISigScanner scanner)
|
||||||
|
{
|
||||||
|
if (scanner.TryScanText(Signatures.SendChat, out var processChatBoxPtr))
|
||||||
|
{
|
||||||
|
ProcessChatBox = Marshal.GetDelegateForFunctionPointer<ProcessChatBoxDelegate>(processChatBoxPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe void SendMessageUnsafe(byte[] message)
|
||||||
|
{
|
||||||
|
if (ProcessChatBox == null)
|
||||||
|
throw new InvalidOperationException("Could not find signature for chat sending");
|
||||||
|
|
||||||
|
var uiModule = (IntPtr)UIModule.Instance();
|
||||||
|
|
||||||
|
using var payload = new ChatPayload(message);
|
||||||
|
var mem1 = Marshal.AllocHGlobal(400);
|
||||||
|
Marshal.StructureToPtr(payload, mem1, false);
|
||||||
|
|
||||||
|
ProcessChatBox(uiModule, mem1, IntPtr.Zero, 0);
|
||||||
|
|
||||||
|
Marshal.FreeHGlobal(mem1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendMessage(string message)
|
||||||
|
{
|
||||||
|
var bytes = Encoding.UTF8.GetBytes(message);
|
||||||
|
if (bytes.Length == 0)
|
||||||
|
throw new ArgumentException("message is empty", nameof(message));
|
||||||
|
|
||||||
|
if (bytes.Length > 500)
|
||||||
|
throw new ArgumentException("message is longer than 500 bytes", nameof(message));
|
||||||
|
|
||||||
|
if (message.Length != SanitiseText(message).Length)
|
||||||
|
throw new ArgumentException("message contained invalid characters", nameof(message));
|
||||||
|
|
||||||
|
SendMessageUnsafe(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static unsafe string SanitiseText(string text)
|
||||||
|
{
|
||||||
|
var uText = Utf8String.FromString(text);
|
||||||
|
|
||||||
|
uText->SanitizeString( 0x27F, Utf8String.CreateEmpty());
|
||||||
|
|
||||||
|
var sanitised = uText->ToString();
|
||||||
|
uText->Dtor();
|
||||||
|
|
||||||
|
return sanitised;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
|
[SuppressMessage("ReSharper", "PrivateFieldCanBeConvertedToLocalVariable")]
|
||||||
|
private readonly struct ChatPayload : IDisposable
|
||||||
|
{
|
||||||
|
[FieldOffset(0)] private readonly IntPtr textPtr;
|
||||||
|
[FieldOffset(16)] private readonly ulong textLen;
|
||||||
|
[FieldOffset(8)] private readonly ulong unk1;
|
||||||
|
[FieldOffset(24)] private readonly ulong unk2;
|
||||||
|
|
||||||
|
internal ChatPayload(byte[] stringBytes)
|
||||||
|
{
|
||||||
|
textPtr = Marshal.AllocHGlobal(stringBytes.Length + 30);
|
||||||
|
Marshal.Copy(stringBytes, 0, textPtr, stringBytes.Length);
|
||||||
|
Marshal.WriteByte(textPtr + stringBytes.Length, 0);
|
||||||
|
|
||||||
|
textLen = (ulong)(stringBytes.Length + 1);
|
||||||
|
|
||||||
|
unk1 = 64;
|
||||||
|
unk2 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(textPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using ChatTwo.Util;
|
using ChatTwo.Util;
|
||||||
using FFXIVClientStructs.FFXIV.Client.System.Framework;
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI.Info;
|
using FFXIVClientStructs.FFXIV.Client.UI.Info;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
|
||||||
|
|
||||||
namespace ChatTwo.GameFunctions;
|
namespace ChatTwo.GameFunctions;
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ internal sealed unsafe class Context
|
|||||||
|
|
||||||
internal static void OpenItemComparison(uint itemId)
|
internal static void OpenItemComparison(uint itemId)
|
||||||
{
|
{
|
||||||
AgentItemComp.Instance()->CompareItem(0x4D, itemId, 0);
|
AgentItemComp.Instance()->CompareItem(0x4D, itemId, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void SearchForRecipesUsingItem(uint itemId)
|
internal static void SearchForRecipesUsingItem(uint itemId)
|
||||||
@@ -37,6 +37,6 @@ internal sealed unsafe class Context
|
|||||||
|
|
||||||
internal static void SearchForItem(uint itemId)
|
internal static void SearchForItem(uint itemId)
|
||||||
{
|
{
|
||||||
Framework.Instance()->GetUiModule()->GetItemFinderModule()->SearchForItem(itemId, true);
|
ItemFinderModule.Instance()->SearchForItem(itemId, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Globalization;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Dalamud.Game.ClientState.Conditions;
|
using Dalamud.Game.ClientState.Conditions;
|
||||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||||
@@ -5,7 +6,6 @@ using Dalamud.Hooking;
|
|||||||
using Dalamud.Memory;
|
using Dalamud.Memory;
|
||||||
using Dalamud.Utility.Signatures;
|
using Dalamud.Utility.Signatures;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
||||||
using FFXIVClientStructs.FFXIV.Client.System.Framework;
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI.Info;
|
using FFXIVClientStructs.FFXIV.Client.UI.Info;
|
||||||
@@ -73,12 +73,12 @@ internal unsafe class GameFunctions : IDisposable
|
|||||||
|
|
||||||
var worldName = row.Name.RawString;
|
var worldName = row.Name.RawString;
|
||||||
ReplacementName = $"{name}@{worldName}";
|
ReplacementName = $"{name}@{worldName}";
|
||||||
Plugin.Common.Functions.Chat.SendMessage($"/{commandName} add {Placeholder}");
|
Plugin.Common.SendMessage($"/{commandName} add {Placeholder}");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void SetAddonInteractable(string name, bool interactable)
|
internal static void SetAddonInteractable(string name, bool interactable)
|
||||||
{
|
{
|
||||||
var unitManager = AtkStage.GetSingleton()->RaptureAtkUnitManager;
|
var unitManager = AtkStage.Instance()->RaptureAtkUnitManager;
|
||||||
|
|
||||||
var addon = (nint) unitManager->GetAddonByName(name);
|
var addon = (nint) unitManager->GetAddonByName(name);
|
||||||
if (addon == nint.Zero)
|
if (addon == nint.Zero)
|
||||||
@@ -101,7 +101,7 @@ internal unsafe class GameFunctions : IDisposable
|
|||||||
|
|
||||||
internal static bool IsAddonInteractable(string name)
|
internal static bool IsAddonInteractable(string name)
|
||||||
{
|
{
|
||||||
var unitManager = AtkStage.GetSingleton()->RaptureAtkUnitManager;
|
var unitManager = AtkStage.Instance()->RaptureAtkUnitManager;
|
||||||
|
|
||||||
var addon = (nint) unitManager->GetAddonByName(name);
|
var addon = (nint) unitManager->GetAddonByName(name);
|
||||||
if (addon == nint.Zero)
|
if (addon == nint.Zero)
|
||||||
@@ -113,8 +113,8 @@ internal unsafe class GameFunctions : IDisposable
|
|||||||
|
|
||||||
internal static void OpenItemTooltip(uint id, ItemPayload.ItemKind itemKind)
|
internal static void OpenItemTooltip(uint id, ItemPayload.ItemKind itemKind)
|
||||||
{
|
{
|
||||||
var atkStage = AtkStage.GetSingleton();
|
var atkStage = AtkStage.Instance();
|
||||||
var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ItemDetail);
|
var agent = AgentItemDetail.Instance();
|
||||||
var addon = atkStage->RaptureAtkUnitManager->GetAddonByName("ItemDetail");
|
var addon = atkStage->RaptureAtkUnitManager->GetAddonByName("ItemDetail");
|
||||||
|
|
||||||
// atkStage ain't gonna be null or we have bigger problems
|
// atkStage ain't gonna be null or we have bigger problems
|
||||||
@@ -144,10 +144,10 @@ internal unsafe class GameFunctions : IDisposable
|
|||||||
*(byte*) (agentPtr + 0x14E) = 0;
|
*(byte*) (agentPtr + 0x14E) = 0;
|
||||||
|
|
||||||
// this just probably needs to be set
|
// this just probably needs to be set
|
||||||
agent->AddonId = addon->ID;
|
agent->AddonId = addon->Id;
|
||||||
|
|
||||||
// vcall from E8 ?? ?? ?? ?? 0F B7 C0 48 83 C4 60 (FF 50 28 48 8B D3 48 8B CF)
|
// vcall from E8 ?? ?? ?? ?? 0F B7 C0 48 83 C4 60 (FF 50 28 48 8B D3 48 8B CF)
|
||||||
var vf5 = (delegate* unmanaged<AtkUnitBase*, byte, uint, void>*) ((nint) addon->VTable + 40);
|
var vf5 = (delegate* unmanaged<AtkUnitBase*, byte, uint, void>*) ((nint) addon->VirtualTable + 40);
|
||||||
// EA8BED: lets vf5 actually run
|
// EA8BED: lets vf5 actually run
|
||||||
*(byte*) ((nint) atkStage + 0x2B4) |= 2;
|
*(byte*) ((nint) atkStage + 0x2B4) |= 2;
|
||||||
(*vf5)(addon, 0, 15);
|
(*vf5)(addon, 0, 15);
|
||||||
@@ -156,11 +156,11 @@ internal unsafe class GameFunctions : IDisposable
|
|||||||
internal static void CloseItemTooltip()
|
internal static void CloseItemTooltip()
|
||||||
{
|
{
|
||||||
// hide addon first to prevent the "addon close" sound
|
// hide addon first to prevent the "addon close" sound
|
||||||
var addon = AtkStage.GetSingleton()->RaptureAtkUnitManager->GetAddonByName("ItemDetail");
|
var addon = AtkStage.Instance()->RaptureAtkUnitManager->GetAddonByName("ItemDetail");
|
||||||
if (addon != null)
|
if (addon != null)
|
||||||
addon->Hide(true, false, 0);
|
addon->Hide(true, false, 0);
|
||||||
|
|
||||||
var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ItemDetail);
|
var agent = AgentItemDetail.Instance();
|
||||||
if (agent != null)
|
if (agent != null)
|
||||||
{
|
{
|
||||||
var eventData = stackalloc AtkValue[1];
|
var eventData = stackalloc AtkValue[1];
|
||||||
@@ -174,12 +174,12 @@ internal unsafe class GameFunctions : IDisposable
|
|||||||
internal static void OpenPartyFinder()
|
internal static void OpenPartyFinder()
|
||||||
{
|
{
|
||||||
// this whole method: 6.05: 84433A (FF 97 ?? ?? ?? ?? 41 B4 01)
|
// this whole method: 6.05: 84433A (FF 97 ?? ?? ?? ?? 41 B4 01)
|
||||||
var lfg = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.LookingForGroup);
|
var lfg = AgentLookingForGroup.Instance();
|
||||||
if (lfg->IsAgentActive())
|
if (lfg->IsAgentActive())
|
||||||
{
|
{
|
||||||
var addonId = lfg->GetAddonID();
|
var addonId = lfg->GetAddonId();
|
||||||
var atkModule = Framework.Instance()->GetUiModule()->GetRaptureAtkModule();
|
var atkModule = RaptureAtkModule.Instance();
|
||||||
var atkModuleVtbl = (void**) atkModule->AtkModule.vtbl;
|
var atkModuleVtbl = (void**) atkModule->AtkModule.VirtualTable;
|
||||||
var vf27 = (delegate* unmanaged<RaptureAtkModule*, ulong, ulong, byte>) atkModuleVtbl[27];
|
var vf27 = (delegate* unmanaged<RaptureAtkModule*, ulong, ulong, byte>) atkModuleVtbl[27];
|
||||||
vf27(atkModule, addonId, 1);
|
vf27(atkModule, addonId, 1);
|
||||||
}
|
}
|
||||||
@@ -198,6 +198,36 @@ internal unsafe class GameFunctions : IDisposable
|
|||||||
return PlayerState.Instance()->IsMentor();
|
return PlayerState.Instance()->IsMentor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static InfoProxyCommonList.CharacterData[] GetFriends()
|
||||||
|
{
|
||||||
|
ChatTwo.Plugin.Log.Information($"Address {(nint)InfoProxyFriendList.Instance():X}");
|
||||||
|
ChatTwo.Plugin.Log.Information($"Address CharaData {(nint)InfoProxyFriendList.Instance()->CharData:X}");
|
||||||
|
var list = InfoProxyFriendList.Instance()->CharDataSpan.ToArray();
|
||||||
|
foreach (var data in list)
|
||||||
|
{
|
||||||
|
ChatTwo.Plugin.Log.Information($"Data was: {data.NameString} {data.HomeWorld} {data.ContentId}");
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void OpenQuestLog(Quest quest)
|
||||||
|
{
|
||||||
|
var splits = quest.Id.RawString.Split("_");
|
||||||
|
if (splits.Length != 2)
|
||||||
|
{
|
||||||
|
Plugin.ChatGui.Print("QuestId is wrongly formatted");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!uint.TryParse(splits[1], NumberStyles.Any, CultureInfo.InvariantCulture, out var questId))
|
||||||
|
{
|
||||||
|
Plugin.ChatGui.Print("Unable to parse quest id");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AgentQuestJournal.Instance()->OpenForQuest(questId, 1);
|
||||||
|
}
|
||||||
|
|
||||||
internal static void OpenPartyFinder(uint id)
|
internal static void OpenPartyFinder(uint id)
|
||||||
{
|
{
|
||||||
AgentLookingForGroup.Instance()->OpenListing(id);
|
AgentLookingForGroup.Instance()->OpenListing(id);
|
||||||
@@ -229,11 +259,11 @@ internal unsafe class GameFunctions : IDisposable
|
|||||||
|
|
||||||
internal static void ClickNoviceNetworkButton()
|
internal static void ClickNoviceNetworkButton()
|
||||||
{
|
{
|
||||||
var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ChatLog);
|
var agent = AgentChatLog.Instance();
|
||||||
// case 3
|
// case 3
|
||||||
var value = new AtkValue { Type = ValueType.Int, Int = 3, };
|
var value = new AtkValue { Type = ValueType.Int, Int = 3, };
|
||||||
var result = 0;
|
var result = 0;
|
||||||
var vf0 = *(delegate* unmanaged<AgentInterface*, int*, AtkValue*, ulong, ulong, int*>*) agent->VTable;
|
var vf0 = *(delegate* unmanaged<AgentChatLog*, int*, AtkValue*, ulong, ulong, int*>*) agent->VirtualTable;
|
||||||
vf0(agent, &result, &value, 0, 0);
|
vf0(agent, &result, &value, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ namespace ChatTwo;
|
|||||||
|
|
||||||
internal sealed class IpcManager : IDisposable
|
internal sealed class IpcManager : IDisposable
|
||||||
{
|
{
|
||||||
private DalamudPluginInterface Interface { get; }
|
|
||||||
private ICallGateProvider<string> RegisterGate { get; }
|
private ICallGateProvider<string> RegisterGate { get; }
|
||||||
private ICallGateProvider<string, object?> UnregisterGate { get; }
|
private ICallGateProvider<string, object?> UnregisterGate { get; }
|
||||||
private ICallGateProvider<object?> AvailableGate { get; }
|
private ICallGateProvider<object?> AvailableGate { get; }
|
||||||
@@ -15,19 +14,17 @@ internal sealed class IpcManager : IDisposable
|
|||||||
|
|
||||||
internal List<string> Registered { get; } = [];
|
internal List<string> Registered { get; } = [];
|
||||||
|
|
||||||
public IpcManager(DalamudPluginInterface pluginInterface)
|
public IpcManager()
|
||||||
{
|
{
|
||||||
Interface = pluginInterface;
|
RegisterGate = Plugin.Interface.GetIpcProvider<string>("ChatTwo.Register");
|
||||||
|
|
||||||
RegisterGate = Interface.GetIpcProvider<string>("ChatTwo.Register");
|
|
||||||
RegisterGate.RegisterFunc(Register);
|
RegisterGate.RegisterFunc(Register);
|
||||||
|
|
||||||
AvailableGate = Interface.GetIpcProvider<object?>("ChatTwo.Available");
|
AvailableGate = Plugin.Interface.GetIpcProvider<object?>("ChatTwo.Available");
|
||||||
|
|
||||||
UnregisterGate = Interface.GetIpcProvider<string, object?>("ChatTwo.Unregister");
|
UnregisterGate = Plugin.Interface.GetIpcProvider<string, object?>("ChatTwo.Unregister");
|
||||||
UnregisterGate.RegisterAction(Unregister);
|
UnregisterGate.RegisterAction(Unregister);
|
||||||
|
|
||||||
InvokeGate = Interface.GetIpcProvider<string, PlayerPayload?, ulong, Payload?, SeString?, SeString?, object?>("ChatTwo.Invoke");
|
InvokeGate = Plugin.Interface.GetIpcProvider<string, PlayerPayload?, ulong, Payload?, SeString?, SeString?, object?>("ChatTwo.Invoke");
|
||||||
|
|
||||||
AvailableGate.SendMessage();
|
AvailableGate.SendMessage();
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -279,15 +279,15 @@ internal partial class Message
|
|||||||
if (split == "<item>")
|
if (split == "<item>")
|
||||||
{
|
{
|
||||||
var agentChat = AgentChatLog.Instance();
|
var agentChat = AgentChatLog.Instance();
|
||||||
var item = *(InventoryItem*)((nint)agentChat + 0x8A0);
|
var item = agentChat->LinkedItem;
|
||||||
|
|
||||||
if (item.ItemID == 0)
|
if (item.ItemId == 0)
|
||||||
{
|
{
|
||||||
AddChunkWithMessage(text.NewWithStyle(chunk.Source, chunk.Link, split));
|
AddChunkWithMessage(text.NewWithStyle(chunk.Source, chunk.Link, split));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var kind = item.ItemID switch
|
var kind = item.ItemId switch
|
||||||
{
|
{
|
||||||
< 500_000 => ItemPayload.ItemKind.Normal,
|
< 500_000 => ItemPayload.ItemKind.Normal,
|
||||||
< 1_000_000 => ItemPayload.ItemKind.Collectible,
|
< 1_000_000 => ItemPayload.ItemKind.Collectible,
|
||||||
@@ -296,10 +296,10 @@ internal partial class Message
|
|||||||
};
|
};
|
||||||
|
|
||||||
var name = kind != ItemPayload.ItemKind.EventItem
|
var name = kind != ItemPayload.ItemKind.EventItem
|
||||||
? Plugin.DataManager.GetExcelSheet<Item>()!.GetRow(item.ItemID)!.Name.ToString()
|
? Plugin.DataManager.GetExcelSheet<Item>()!.GetRow(item.ItemId)!.Name.ToString()
|
||||||
: Plugin.DataManager.GetExcelSheet<EventItem>()!.GetRow(item.ItemID)!.Name.ToString();
|
: Plugin.DataManager.GetExcelSheet<EventItem>()!.GetRow(item.ItemId)!.Name.ToString();
|
||||||
|
|
||||||
var link = new ItemPayload(item.ItemID, kind, $"{SeIconChar.LinkMarker.ToIconChar()}{name}");
|
var link = new ItemPayload(item.ItemId, kind, $"{SeIconChar.LinkMarker.ToIconChar()}{name}");
|
||||||
AddChunkWithMessage(text.NewWithStyle(chunk.Source, link, link.DisplayName ?? "Unknown"));
|
AddChunkWithMessage(text.NewWithStyle(chunk.Source, link, link.DisplayName ?? "Unknown"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using ChatTwo.Util;
|
|||||||
using Dalamud.Game.Text;
|
using Dalamud.Game.Text;
|
||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Dalamud.Hooking;
|
using Dalamud.Hooking;
|
||||||
using Dalamud.Interface.Internal.Notifications;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
|
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
|
||||||
using Lumina.Excel.GeneratedSheets;
|
using Lumina.Excel.GeneratedSheets;
|
||||||
@@ -35,9 +35,7 @@ internal class MessageManager : IAsyncDisposable
|
|||||||
private readonly Thread PendingMessageThread;
|
private readonly Thread PendingMessageThread;
|
||||||
private readonly CancellationTokenSource PendingThreadCancellationToken = new();
|
private readonly CancellationTokenSource PendingThreadCancellationToken = new();
|
||||||
|
|
||||||
// TODO Replace with delegate in API X
|
private Hook<RaptureLogModule.Delegates.AddMsgSourceEntry>? ContentIdResolverHook { get; init; }
|
||||||
private Hook<ContentIdResolverDelegate>? ContentIdResolverHook { get; init; }
|
|
||||||
private unsafe delegate void ContentIdResolverDelegate(RaptureLogModule* agent, ulong contentId, int messageIndex, ushort worldId, ushort chatType);
|
|
||||||
|
|
||||||
internal ulong CurrentContentId
|
internal ulong CurrentContentId
|
||||||
{
|
{
|
||||||
@@ -57,7 +55,7 @@ internal class MessageManager : IAsyncDisposable
|
|||||||
PendingMessageThread = new Thread(() => ProcessPendingMessages(PendingThreadCancellationToken.Token));
|
PendingMessageThread = new Thread(() => ProcessPendingMessages(PendingThreadCancellationToken.Token));
|
||||||
PendingMessageThread.Start();
|
PendingMessageThread.Start();
|
||||||
|
|
||||||
ContentIdResolverHook = Plugin.GameInteropProvider.HookFromAddress<ContentIdResolverDelegate>(RaptureLogModule.Addresses.AddMsgSourceEntry.Value, ContentIdResolver);
|
ContentIdResolverHook = Plugin.GameInteropProvider.HookFromAddress<RaptureLogModule.Delegates.AddMsgSourceEntry>(RaptureLogModule.MemberFunctionPointers.AddMsgSourceEntry, ContentIdResolver);
|
||||||
ContentIdResolverHook.Enable();
|
ContentIdResolverHook.Enable();
|
||||||
|
|
||||||
Plugin.ChatGui.ChatMessageUnhandled += ChatMessage;
|
Plugin.ChatGui.ChatMessageUnhandled += ChatMessage;
|
||||||
@@ -193,7 +191,7 @@ internal class MessageManager : IAsyncDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
public (SeString? Sender, SeString? Message) LastMessage = (null, null);
|
public (SeString? Sender, SeString? Message) LastMessage = (null, null);
|
||||||
private void ChatMessage(XivChatType type, uint senderId, SeString sender, SeString message)
|
private void ChatMessage(XivChatType type, int timestamp, SeString sender, SeString message)
|
||||||
{
|
{
|
||||||
LastMessage = (sender, message);
|
LastMessage = (sender, message);
|
||||||
|
|
||||||
@@ -202,7 +200,7 @@ internal class MessageManager : IAsyncDisposable
|
|||||||
ReceiverId = CurrentContentId,
|
ReceiverId = CurrentContentId,
|
||||||
ContentId = 0,
|
ContentId = 0,
|
||||||
Type = type,
|
Type = type,
|
||||||
SenderId = senderId,
|
Timestamp = timestamp,
|
||||||
Sender = sender,
|
Sender = sender,
|
||||||
Content = message,
|
Content = message,
|
||||||
};
|
};
|
||||||
@@ -220,9 +218,9 @@ internal class MessageManager : IAsyncDisposable
|
|||||||
// message's content ID. If multiple messages are received in the same tick,
|
// message's content ID. If multiple messages are received in the same tick,
|
||||||
// this will be called for each message immediately after ChatMessage is
|
// this will be called for each message immediately after ChatMessage is
|
||||||
// called for each message.
|
// called for each message.
|
||||||
private unsafe void ContentIdResolver(RaptureLogModule* agent, ulong contentId, int messageIndex, ushort worldId, ushort chatType)
|
private unsafe void ContentIdResolver(RaptureLogModule* agent, ulong contentId, ulong accountId, int messageIndex, ushort worldId, ushort chatType)
|
||||||
{
|
{
|
||||||
ContentIdResolverHook?.Original(agent, contentId, messageIndex, worldId, chatType);
|
ContentIdResolverHook?.Original(agent, contentId, accountId, messageIndex, worldId, chatType);
|
||||||
if (PendingSync.Count == 0)
|
if (PendingSync.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -333,7 +331,7 @@ internal class MessageManager : IAsyncDisposable
|
|||||||
internal ulong ReceiverId { get; set; }
|
internal ulong ReceiverId { get; set; }
|
||||||
internal ulong ContentId { get; set; } // 0 if unknown
|
internal ulong ContentId { get; set; } // 0 if unknown
|
||||||
internal XivChatType Type { get; set; }
|
internal XivChatType Type { get; set; }
|
||||||
internal uint SenderId { get; set; }
|
internal int Timestamp { get; set; }
|
||||||
internal SeString Sender { get; set; }
|
internal SeString Sender { get; set; }
|
||||||
internal SeString Content { get; set; }
|
internal SeString Content { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ using Dalamud.Game.ClientState.Objects.SubKinds;
|
|||||||
using Dalamud.Game.Config;
|
using Dalamud.Game.Config;
|
||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||||
using Dalamud.Interface.Internal;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
using Dalamud.Interface.Internal.Notifications;
|
using Dalamud.Interface.Textures.TextureWraps;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
@@ -379,7 +379,7 @@ public sealed class PayloadHandler {
|
|||||||
Plugin.GameGui.OpenMapWithMapLink(map);
|
Plugin.GameGui.OpenMapWithMapLink(map);
|
||||||
break;
|
break;
|
||||||
case QuestPayload quest:
|
case QuestPayload quest:
|
||||||
LogWindow.Plugin.Common.Functions.Journal.OpenQuest(quest.Quest);
|
GameFunctions.GameFunctions.OpenQuestLog(quest.Quest);
|
||||||
break;
|
break;
|
||||||
case DalamudLinkPayload link:
|
case DalamudLinkPayload link:
|
||||||
ClickLinkPayload(chunk, payload, link);
|
ClickLinkPayload(chunk, payload, link);
|
||||||
@@ -601,7 +601,8 @@ public sealed class PayloadHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var isFriend = LogWindow.Plugin.Common.Functions.FriendList.List.Any(friend => friend.Name.TextValue == player.PlayerName && friend.HomeWorld == world.RowId);
|
var isFriend = GameFunctions.GameFunctions.GetFriends().Any(friend => friend.NameString == player.PlayerName && friend.HomeWorld == world.RowId);
|
||||||
|
Plugin.Log.Information($"Is Friend? {isFriend}");
|
||||||
if (!isFriend && ImGui.Selectable(Language.Context_SendFriendRequest))
|
if (!isFriend && ImGui.Selectable(Language.Context_SendFriendRequest))
|
||||||
LogWindow.Plugin.Functions.SendFriendRequest(player.PlayerName, (ushort) world.RowId);
|
LogWindow.Plugin.Functions.SendFriendRequest(player.PlayerName, (ushort) world.RowId);
|
||||||
|
|
||||||
@@ -629,11 +630,11 @@ public sealed class PayloadHandler {
|
|||||||
// View Party Finder 0x2E
|
// View Party Finder 0x2E
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlayerCharacter? FindCharacterForPayload(PlayerPayload payload)
|
private IPlayerCharacter? FindCharacterForPayload(PlayerPayload payload)
|
||||||
{
|
{
|
||||||
foreach (var obj in Plugin.ObjectTable)
|
foreach (var obj in Plugin.ObjectTable)
|
||||||
{
|
{
|
||||||
if (obj is not PlayerCharacter character)
|
if (obj is not IPlayerCharacter character)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (character.Name.TextValue != payload.PlayerName)
|
if (character.Name.TextValue != payload.PlayerName)
|
||||||
|
|||||||
+7
-6
@@ -1,10 +1,12 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using ChatTwo.GameFunctions;
|
||||||
using ChatTwo.Ipc;
|
using ChatTwo.Ipc;
|
||||||
using ChatTwo.Resources;
|
using ChatTwo.Resources;
|
||||||
using ChatTwo.Ui;
|
using ChatTwo.Ui;
|
||||||
using ChatTwo.Util;
|
using ChatTwo.Util;
|
||||||
|
using Dalamud.Game;
|
||||||
using Dalamud.Game.ClientState.Conditions;
|
using Dalamud.Game.ClientState.Conditions;
|
||||||
using Dalamud.Game.ClientState.Objects;
|
using Dalamud.Game.ClientState.Objects;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
@@ -12,7 +14,6 @@ using Dalamud.IoC;
|
|||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using XivCommon;
|
|
||||||
|
|
||||||
namespace ChatTwo;
|
namespace ChatTwo;
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
internal const string PluginName = "Chat 2";
|
internal const string PluginName = "Chat 2";
|
||||||
|
|
||||||
[PluginService] internal static IPluginLog Log { get; private set; } = null!;
|
[PluginService] internal static IPluginLog Log { get; private set; } = null!;
|
||||||
[PluginService] internal static DalamudPluginInterface Interface { get; private set; } = null!;
|
[PluginService] internal static IDalamudPluginInterface Interface { get; private set; } = null!;
|
||||||
[PluginService] internal static IChatGui ChatGui { get; private set; } = null!;
|
[PluginService] internal static IChatGui ChatGui { get; private set; } = null!;
|
||||||
[PluginService] internal static IClientState ClientState { get; private set; } = null!;
|
[PluginService] internal static IClientState ClientState { get; private set; } = null!;
|
||||||
[PluginService] internal static ICommandManager CommandManager { get; private set; } = null!;
|
[PluginService] internal static ICommandManager CommandManager { get; private set; } = null!;
|
||||||
@@ -39,6 +40,7 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
[PluginService] internal static IGameConfig GameConfig { get; private set; } = null!;
|
[PluginService] internal static IGameConfig GameConfig { get; private set; } = null!;
|
||||||
[PluginService] internal static INotificationManager Notification { get; private set; } = null!;
|
[PluginService] internal static INotificationManager Notification { get; private set; } = null!;
|
||||||
[PluginService] internal static IAddonLifecycle AddonLifecycle { get; private set; } = null!;
|
[PluginService] internal static IAddonLifecycle AddonLifecycle { get; private set; } = null!;
|
||||||
|
[PluginService] internal static ISigScanner Scanner { get; private set; } = null!;
|
||||||
|
|
||||||
internal static Configuration Config = null!;
|
internal static Configuration Config = null!;
|
||||||
|
|
||||||
@@ -53,7 +55,7 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
internal LegacyMessageImporterWindow LegacyMessageImporterWindow { get; }
|
internal LegacyMessageImporterWindow LegacyMessageImporterWindow { get; }
|
||||||
|
|
||||||
internal Commands Commands { get; }
|
internal Commands Commands { get; }
|
||||||
internal XivCommonBase Common { get; }
|
internal ChatCommon Common { get; }
|
||||||
internal TextureCache TextureCache { get; }
|
internal TextureCache TextureCache { get; }
|
||||||
internal GameFunctions.GameFunctions Functions { get; }
|
internal GameFunctions.GameFunctions Functions { get; }
|
||||||
internal MessageManager MessageManager { get; }
|
internal MessageManager MessageManager { get; }
|
||||||
@@ -80,10 +82,10 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
ImGuiUtil.Initialize(this);
|
ImGuiUtil.Initialize(this);
|
||||||
|
|
||||||
Commands = new Commands(this);
|
Commands = new Commands(this);
|
||||||
Common = new XivCommonBase(Interface);
|
Common = new ChatCommon(Scanner);
|
||||||
TextureCache = new TextureCache();
|
TextureCache = new TextureCache();
|
||||||
Functions = new GameFunctions.GameFunctions(this);
|
Functions = new GameFunctions.GameFunctions(this);
|
||||||
Ipc = new IpcManager(Interface);
|
Ipc = new IpcManager();
|
||||||
ExtraChat = new ExtraChat(this);
|
ExtraChat = new ExtraChat(this);
|
||||||
FontManager = new FontManager(this);
|
FontManager = new FontManager(this);
|
||||||
|
|
||||||
@@ -165,7 +167,6 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
MessageManager?.DisposeAsync().AsTask().Wait();
|
MessageManager?.DisposeAsync().AsTask().Wait();
|
||||||
Functions?.Dispose();
|
Functions?.Dispose();
|
||||||
TextureCache?.Dispose();
|
TextureCache?.Dispose();
|
||||||
Common?.Dispose();
|
|
||||||
Commands?.Dispose();
|
Commands?.Dispose();
|
||||||
|
|
||||||
EmoteCache.Dispose();
|
EmoteCache.Dispose();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using Dalamud.Interface.Internal;
|
using Dalamud.Interface.Textures;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Interface.Textures.TextureWraps;
|
||||||
using Lumina.Excel.GeneratedSheets;
|
using Lumina.Excel.GeneratedSheets;
|
||||||
|
|
||||||
namespace ChatTwo;
|
namespace ChatTwo;
|
||||||
@@ -24,9 +24,7 @@ internal class TextureCache : IDisposable
|
|||||||
if (dict.ContainsKey((icon, hq)))
|
if (dict.ContainsKey((icon, hq)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var tex = hq
|
var tex = Plugin.TextureProvider.GetFromGameIcon(new GameIconLookup(icon, hq)).GetWrapOrDefault();
|
||||||
? Plugin.TextureProvider.GetIcon(icon, ITextureProvider.IconFlags.ItemHighQuality)
|
|
||||||
: Plugin.TextureProvider.GetIcon(icon);
|
|
||||||
if (tex != null)
|
if (tex != null)
|
||||||
dict[(icon, hq)] = tex;
|
dict[(icon, hq)] = tex;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,14 +12,15 @@ using Dalamud.Game.ClientState.Keys;
|
|||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Interface.Internal;
|
|
||||||
using Dalamud.Interface.Style;
|
using Dalamud.Interface.Style;
|
||||||
|
using Dalamud.Interface.Textures.TextureWraps;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.Memory;
|
using Dalamud.Memory;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
|
using Lumina.Data.Files;
|
||||||
using Lumina.Excel;
|
using Lumina.Excel;
|
||||||
using Lumina.Excel.GeneratedSheets;
|
using Lumina.Excel.GeneratedSheets;
|
||||||
|
|
||||||
@@ -114,7 +115,7 @@ public sealed class ChatLogWindow : Window
|
|||||||
WorldSheet = Plugin.DataManager.GetExcelSheet<World>()!;
|
WorldSheet = Plugin.DataManager.GetExcelSheet<World>()!;
|
||||||
LogFilterSheet = Plugin.DataManager.GetExcelSheet<LogFilter>()!;
|
LogFilterSheet = Plugin.DataManager.GetExcelSheet<LogFilter>()!;
|
||||||
TextCommandSheet = Plugin.DataManager.GetExcelSheet<TextCommand>()!;
|
TextCommandSheet = Plugin.DataManager.GetExcelSheet<TextCommand>()!;
|
||||||
FontIcon = Plugin.TextureProvider.GetTextureFromGame("common/font/fonticon_ps5.tex");
|
FontIcon = Plugin.TextureProvider.CreateFromTexFile(Plugin.DataManager.GetFile<TexFile>("common/font/fonticon_ps5.tex")!);
|
||||||
|
|
||||||
Plugin.Functions.Chat.Activated += Activated;
|
Plugin.Functions.Chat.Activated += Activated;
|
||||||
Plugin.ClientState.Login += Login;
|
Plugin.ClientState.Login += Login;
|
||||||
@@ -804,7 +805,7 @@ public sealed class ChatLogWindow : Window
|
|||||||
// registers stub handlers and actually processes its commands in a
|
// registers stub handlers and actually processes its commands in a
|
||||||
// SendMessage detour.
|
// SendMessage detour.
|
||||||
var bytes = Encoding.UTF8.GetBytes(channel.Value.Prefix());
|
var bytes = Encoding.UTF8.GetBytes(channel.Value.Prefix());
|
||||||
Plugin.Common.Functions.Chat.SendMessageUnsafe(bytes);
|
Plugin.Common.SendMessageUnsafe(bytes);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -828,7 +829,7 @@ public sealed class ChatLogWindow : Window
|
|||||||
var world = WorldSheet.GetRow(target.World);
|
var world = WorldSheet.GetRow(target.World);
|
||||||
if (world is { IsPublic: true })
|
if (world is { IsPublic: true })
|
||||||
{
|
{
|
||||||
if (reason == TellReason.Reply && Plugin.Common.Functions.FriendList.List.Any(friend => friend.ContentId == target.ContentId))
|
if (reason == TellReason.Reply && GameFunctions.GameFunctions.GetFriends().Any(friend => friend.ContentId == target.ContentId))
|
||||||
reason = TellReason.Friend;
|
reason = TellReason.Friend;
|
||||||
|
|
||||||
var tellBytes = Encoding.UTF8.GetBytes(trimmed);
|
var tellBytes = Encoding.UTF8.GetBytes(trimmed);
|
||||||
@@ -854,7 +855,7 @@ public sealed class ChatLogWindow : Window
|
|||||||
var bytes = Encoding.UTF8.GetBytes(trimmed);
|
var bytes = Encoding.UTF8.GetBytes(trimmed);
|
||||||
AutoTranslate.ReplaceWithPayload(ref bytes);
|
AutoTranslate.ReplaceWithPayload(ref bytes);
|
||||||
|
|
||||||
Plugin.Common.Functions.Chat.SendMessageUnsafe(bytes);
|
Plugin.Common.SendMessageUnsafe(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
Chat = string.Empty;
|
Chat = string.Empty;
|
||||||
@@ -989,9 +990,6 @@ public sealed class ChatLogWindow : Window
|
|||||||
if (i > 0)
|
if (i > 0)
|
||||||
{
|
{
|
||||||
var prevMessage = messages[i - 1];
|
var prevMessage = messages[i - 1];
|
||||||
|
|
||||||
// TODO: TryGetValue isn't always true for some strange reason
|
|
||||||
// This should be looked into, because default will be null for the prevHeight in that case
|
|
||||||
prevMessage.Height.TryGetValue(tab.Identifier, out var prevHeight);
|
prevMessage.Height.TryGetValue(tab.Identifier, out var prevHeight);
|
||||||
if (prevHeight == null || (prevMessage.IsVisible.TryGetValue(tab.Identifier, out var prevVisible) && prevVisible))
|
if (prevHeight == null || (prevMessage.IsVisible.TryGetValue(tab.Identifier, out var prevVisible) && prevVisible))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public class DebuggerWindow : Window
|
|||||||
|
|
||||||
public override unsafe void Draw()
|
public override unsafe void Draw()
|
||||||
{
|
{
|
||||||
var agent = (nint) Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ItemDetail);
|
var agent = (nint) AgentItemDetail.Instance();
|
||||||
ImGui.TextUnformatted($"Current Cursor Pos: {ChatLogWindow.CursorPos}");
|
ImGui.TextUnformatted($"Current Cursor Pos: {ChatLogWindow.CursorPos}");
|
||||||
if (ImGui.Selectable($"Agent Address: {agent:X}"))
|
if (ImGui.Selectable($"Agent Address: {agent:X}"))
|
||||||
ImGui.SetClipboardText(agent.ToString("X"));
|
ImGui.SetClipboardText(agent.ToString("X"));
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
using ChatTwo.Util;
|
using ChatTwo.Util;
|
||||||
using Dalamud.Interface.ImGuiNotification;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
using Dalamud.Interface.ImGuiNotification.EventArgs;
|
using Dalamud.Interface.ImGuiNotification.EventArgs;
|
||||||
using Dalamud.Interface.Internal.Notifications;
|
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using ChatTwo.Resources;
|
|||||||
using ChatTwo.Util;
|
using ChatTwo.Util;
|
||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||||
using Dalamud.Interface.Internal.Notifications;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Dalamud;
|
using Dalamud.Game;
|
||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using ChatTwo.Resources;
|
|||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Interface.Colors;
|
using Dalamud.Interface.Colors;
|
||||||
using Dalamud.Interface.ImGuiNotification;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
using Dalamud.Interface.Internal.Notifications;
|
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Dalamud.Interface.ImGuiNotification;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
using Dalamud.Interface.Internal.Notifications;
|
|
||||||
|
|
||||||
namespace ChatTwo.Util;
|
namespace ChatTwo.Util;
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
"net8.0-windows7.0": {
|
"net8.0-windows7.0": {
|
||||||
"DalamudPackager": {
|
"DalamudPackager": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[2.1.12, )",
|
"requested": "[2.1.13, )",
|
||||||
"resolved": "2.1.12",
|
"resolved": "2.1.13",
|
||||||
"contentHash": "Sc0PVxvgg4NQjcI8n10/VfUQBAS4O+Fw2pZrAqBdRMbthYGeogzu5+xmIGCGmsEZ/ukMOBuAqiNiB5qA3MRalg=="
|
"contentHash": "rMN1omGe8536f4xLMvx9NwfvpAc9YFFfeXJ1t4P4PE6Gu8WCIoFliR1sh07hM+bfODmesk/dvMbji7vNI+B/pQ=="
|
||||||
},
|
},
|
||||||
"LiteDB": {
|
"LiteDB": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
@@ -58,12 +58,6 @@
|
|||||||
"resolved": "3.1.4",
|
"resolved": "3.1.4",
|
||||||
"contentHash": "lFIdxgGDA5iYkUMRFOze7BGLcdpoLFbR+a20kc1W7NepvzU7ejtxtWOg9RvgG7kb9tBoJ3ONYOK6kLil/dgF1w=="
|
"contentHash": "lFIdxgGDA5iYkUMRFOze7BGLcdpoLFbR+a20kc1W7NepvzU7ejtxtWOg9RvgG7kb9tBoJ3ONYOK6kLil/dgF1w=="
|
||||||
},
|
},
|
||||||
"XivCommon": {
|
|
||||||
"type": "Direct",
|
|
||||||
"requested": "[9.0.0, )",
|
|
||||||
"resolved": "9.0.0",
|
|
||||||
"contentHash": "avaBp3FmSCi/PiQhntCeBDYOHejdyTWmFtz4pRBVQQ8vHkmRx+YTk1la9dkYBMlXxRXKckEdH1iI1Fu61JlE7w=="
|
|
||||||
},
|
|
||||||
"MessagePack.Annotations": {
|
"MessagePack.Annotations": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "2.5.140",
|
"resolved": "2.5.140",
|
||||||
|
|||||||
Reference in New Issue
Block a user