- Replace all possible hooks with CS

- Mark ones that can be replaced soon
- Use Dalamuds ConfigOption for chat color parsing
This commit is contained in:
Infi
2024-05-25 16:50:37 +02:00
parent 8aaaa684a2
commit 0c19772b18
10 changed files with 104 additions and 109 deletions
+1
View File
@@ -1,3 +1,4 @@
using Dalamud.Game.Config;
using LiteDB; using LiteDB;
namespace ChatTwo.Code; namespace ChatTwo.Code;
+2
View File
@@ -1,3 +1,5 @@
using Dalamud.Game.Config;
namespace ChatTwo.Code; namespace ChatTwo.Code;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1028:Enum Storage should be Int32")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1028:Enum Storage should be Int32")]
+31 -1
View File
@@ -1,5 +1,6 @@
using ChatTwo.Resources; using ChatTwo.Resources;
using ChatTwo.Util; using ChatTwo.Util;
using Dalamud.Game.Config;
namespace ChatTwo.Code; namespace ChatTwo.Code;
@@ -187,7 +188,7 @@ internal static class ChatTypeExt
}; };
} }
internal static uint? DefaultColour(this ChatType type) internal static uint? DefaultColor(this ChatType type)
{ {
switch (type) switch (type)
{ {
@@ -370,6 +371,35 @@ internal static class ChatTypeExt
_ => false, _ => false,
}; };
public static UiConfigOption ToConfigEntry(this ChatType type) => type switch
{
ChatType.Say => UiConfigOption.ColorSay,
ChatType.Shout => UiConfigOption.ColorShout,
ChatType.TellOutgoing => UiConfigOption.ColorTell,
ChatType.Party => UiConfigOption.ColorParty,
ChatType.Linkshell1 => UiConfigOption.ColorLS1,
ChatType.Linkshell2 => UiConfigOption.ColorLS2,
ChatType.Linkshell3 => UiConfigOption.ColorLS3,
ChatType.Linkshell4 => UiConfigOption.ColorLS4,
ChatType.Linkshell5 => UiConfigOption.ColorLS5,
ChatType.Linkshell6 => UiConfigOption.ColorLS6,
ChatType.Linkshell7 => UiConfigOption.ColorLS7,
ChatType.Linkshell8 => UiConfigOption.ColorLS8,
ChatType.FreeCompany => UiConfigOption.ColorFCompany,
ChatType.NoviceNetwork => UiConfigOption.ColorBeginner,
ChatType.CustomEmote => UiConfigOption.ColorEmoteUser,
ChatType.StandardEmote => UiConfigOption.ColorEmote,
ChatType.Yell => UiConfigOption.ColorYell,
ChatType.GainBuff => UiConfigOption.ColorBuffGive,
ChatType.GainDebuff => UiConfigOption.ColorDebuffGive,
ChatType.System => UiConfigOption.ColorSysMsg,
ChatType.NpcDialogue => UiConfigOption.ColorNpcSay,
ChatType.LootRoll => UiConfigOption.ColorLoot,
ChatType.FreeCompanyAnnouncement => UiConfigOption.ColorFCAnnounce,
ChatType.PvpTeamAnnouncement => UiConfigOption.ColorPvPGroupAnnounce,
_ => UiConfigOption.ColorSay,
};
internal static bool HasSource(this ChatType type) => type switch internal static bool HasSource(this ChatType type) => type switch
{ {
// Battle // Battle
+44 -71
View File
@@ -14,6 +14,7 @@ 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;
using FFXIVClientStructs.FFXIV.Client.UI.Agent; using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using FFXIVClientStructs.FFXIV.Client.UI.Info;
using FFXIVClientStructs.FFXIV.Client.UI.Misc; using FFXIVClientStructs.FFXIV.Client.UI.Misc;
using FFXIVClientStructs.FFXIV.Client.UI.Shell; using FFXIVClientStructs.FFXIV.Client.UI.Shell;
using FFXIVClientStructs.FFXIV.Component.GUI; using FFXIVClientStructs.FFXIV.Component.GUI;
@@ -26,109 +27,103 @@ internal sealed unsafe class Chat : IDisposable
{ {
// Functions // Functions
// TODO Replace with CS in RaptureShellModule
[Signature("E8 ?? ?? ?? ?? 0F B7 44 37 ??", Fallibility = Fallibility.Fallible)] [Signature("E8 ?? ?? ?? ?? 0F B7 44 37 ??", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<RaptureShellModule*, int, uint, Utf8String*, byte, void> ChangeChatChannel = null!; private readonly delegate* unmanaged<RaptureShellModule*, int, uint, Utf8String*, byte, void> ChangeChatChannel = null!;
// TODO Replace with CS in RaptureShellModule
[Signature("48 89 5C 24 ?? 55 56 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 48 8B 02", Fallibility = Fallibility.Fallible)] [Signature("48 89 5C 24 ?? 55 56 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 48 8B 02", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<RaptureShellModule*, Utf8String*, Utf8String*, ushort, ulong, ushort, byte, bool> SetChannelTargetTell = null!; private readonly delegate* unmanaged<RaptureShellModule*, Utf8String*, Utf8String*, ushort, ulong, ushort, byte, bool> SetChannelTargetTell = null!;
[Signature("E8 ?? ?? ?? ?? 48 8D 4D A0 8B F8")] [Signature("E8 ?? ?? ?? ?? 48 8D 4D A0 8B F8")]
private readonly delegate* unmanaged<IntPtr, Utf8String*, IntPtr, uint> GetKeybindNative = null!; private readonly delegate* unmanaged<nint, Utf8String*, IntPtr, uint> GetKeybindNative = null!;
// TODO Replace with CS in AcquaintanceModule
[Signature("44 8B 89 ?? ?? ?? ?? 4C 8B C1 45 85 C9")] [Signature("44 8B 89 ?? ?? ?? ?? 4C 8B C1 45 85 C9")]
private readonly delegate* unmanaged<void*, int, IntPtr> GetTellHistory = null!; private readonly delegate* unmanaged<void*, int, nint> GetTellHistory = null!;
[Signature("E8 ?? ?? ?? ?? 48 8D 4D 50 E8 ?? ?? ?? ?? 48 8B 17")] [Signature("E8 ?? ?? ?? ?? 48 8D 4D 50 E8 ?? ?? ?? ?? 48 8B 17")]
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<IntPtr, ulong, ushort, Utf8String*, Utf8String*, byte, ulong, byte> SendTellNative = null!; private readonly delegate* unmanaged<nint, ulong, ushort, Utf8String*, Utf8String*, byte, ulong, byte> SendTellNative = null!;
[Signature("E8 ?? ?? ?? ?? F6 43 0A 40")] [Signature("E8 ?? ?? ?? ?? F6 43 0A 40")]
private readonly delegate* unmanaged<Framework*, IntPtr> GetNetworkModule = null!; private readonly delegate* unmanaged<Framework*, nint> GetNetworkModule = null!;
// TODO Replace with CS in InfoProxyCrossworldLinkshell
[Signature("E8 ?? ?? ?? ?? 48 8B C8 E8 ?? ?? ?? ?? 45 8D 46 FB")] [Signature("E8 ?? ?? ?? ?? 48 8B C8 E8 ?? ?? ?? ?? 45 8D 46 FB")]
private readonly delegate* unmanaged<IntPtr, uint, Utf8String*> GetCrossLinkshellNameNative = null!; private readonly delegate* unmanaged<nint, uint, Utf8String*> GetCrossLinkshellNameNative = null!;
// TODO Replace with CS in InfoProxyLinkshell
[Signature("3B 51 10 73 0F 8B C2 48 83 C0 0B")] [Signature("3B 51 10 73 0F 8B C2 48 83 C0 0B")]
private readonly delegate* unmanaged<IntPtr, uint, ulong*> GetLinkshellInfo = null!; private readonly delegate* unmanaged<nint, uint, ulong*> GetLinkshellInfo = null!;
// TODO Replace with CS in InfoProxyLinkshell
[Signature("E8 ?? ?? ?? ?? 4C 8B C8 44 8D 47 01")] [Signature("E8 ?? ?? ?? ?? 4C 8B C8 44 8D 47 01")]
private readonly delegate* unmanaged<IntPtr, ulong, byte*> GetLinkshellNameNative = null!; private readonly delegate* unmanaged<nint, ulong, byte*> GetLinkshellNameNative = null!;
// TODO Replace with CS virtual function
[Signature("40 56 41 54 41 55 41 57 48 83 EC 28 48 8B 01", Fallibility = Fallibility.Fallible)] [Signature("40 56 41 54 41 55 41 57 48 83 EC 28 48 8B 01", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<UIModule*, int, ulong> RotateLinkshellHistoryNative; private readonly delegate* unmanaged<UIModule*, int, ulong> RotateLinkshellHistoryNative;
// TODO Replace with CS virtual function
[Signature("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC 20 48 8B 01 44 8B F2", Fallibility = Fallibility.Fallible)] [Signature("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC 20 48 8B 01 44 8B F2", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<UIModule*, int, ulong> RotateCrossLinkshellHistoryNative; private readonly delegate* unmanaged<UIModule*, int, ulong> RotateCrossLinkshellHistoryNative;
[Signature("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 8B F2 48 8D B9")] // TODO Replace with CS version on Utf8String
private readonly delegate* unmanaged<IntPtr, uint, IntPtr> GetColourInfo = null!;
[Signature("E8 ?? ?? ?? ?? EB 0A 48 8D 4C 24 ?? E8 ?? ?? ?? ?? 48 8D 8D")] [Signature("E8 ?? ?? ?? ?? EB 0A 48 8D 4C 24 ?? E8 ?? ?? ?? ?? 48 8D 8D")]
private readonly delegate* unmanaged<Utf8String*, int, IntPtr, void> SanitiseString = null!; private readonly delegate* unmanaged<Utf8String*, int, nint, void> SanitiseString = null!;
// Hooks // Hooks
private delegate byte ChatLogRefreshDelegate(IntPtr log, ushort eventId, AtkValue* value); private delegate byte ChatLogRefreshDelegate(nint log, ushort eventId, AtkValue* value);
private delegate IntPtr ChangeChannelNameDelegate(IntPtr agent); private delegate nint ChangeChannelNameDelegate(nint agent);
private delegate void ReplyInSelectedChatModeDelegate(AgentInterface* agent); private delegate void ReplyInSelectedChatModeDelegate(AgentInterface* agent);
private delegate byte SetChatLogTellTarget(IntPtr a1, Utf8String* name, Utf8String* a3, ushort world, ulong contentId, ushort a6, byte a7); private delegate byte SetChatLogTellTarget(nint a1, Utf8String* name, Utf8String* a3, ushort world, ulong contentId, ushort a6, byte a7);
private delegate void EurekaContextMenuTellDelegate(RaptureShellModule* param1, Utf8String* playerName, Utf8String* worldName, ushort world, ulong contentId, ushort param6); private delegate void EurekaContextMenuTellDelegate(RaptureShellModule* param1, Utf8String* playerName, Utf8String* worldName, ushort world, ulong contentId, ushort param6);
[Signature(
"40 53 56 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 49 8B F0 8B FA", // Client::UI::AddonChatLog.OnRefresh
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; }
[Signature( // TODO Replace with CS version
"E8 ?? ?? ?? ?? BA ?? ?? ?? ?? 48 8D 4D B0 48 8B F8 E8 ?? ?? ?? ?? 41 8B D6", [Signature("E8 ?? ?? ?? ?? BA ?? ?? ?? ?? 48 8D 4D B0 48 8B F8 E8 ?? ?? ?? ?? 41 8B D6", DetourName = nameof(ChangeChannelNameDetour))]
DetourName = nameof(ChangeChannelNameDetour)
)]
private Hook<ChangeChannelNameDelegate>? ChangeChannelNameHook { get; init; } private Hook<ChangeChannelNameDelegate>? ChangeChannelNameHook { get; init; }
[Signature( // TODO Replace with CS version
"48 89 5C 24 ?? 57 48 83 EC 30 8B B9 ?? ?? ?? ?? 48 8B D9 83 FF FE", [Signature("48 89 5C 24 ?? 57 48 83 EC 30 8B B9 ?? ?? ?? ?? 48 8B D9 83 FF FE", DetourName = nameof(ReplyInSelectedChatModeDetour))]
DetourName = nameof(ReplyInSelectedChatModeDetour)
)]
private Hook<ReplyInSelectedChatModeDelegate>? ReplyInSelectedChatModeHook { get; init; } private Hook<ReplyInSelectedChatModeDelegate>? ReplyInSelectedChatModeHook { get; init; }
[Signature( // TODO Replace with CS version
"E8 ?? ?? ?? ?? 4C 8B 7C 24 ?? EB 34", [Signature("E8 ?? ?? ?? ?? 4C 8B 7C 24 ?? EB 34", DetourName = nameof(SetChatLogTellTargetDetour))]
DetourName = nameof(SetChatLogTellTargetDetour)
)]
private Hook<SetChatLogTellTarget>? SetChatLogTellTargetHook { get; init; } private Hook<SetChatLogTellTarget>? SetChatLogTellTargetHook { get; init; }
[Signature( // TODO Replace with CS version
"E8 ?? ?? ?? ?? EB 8A 48 8B 1D", [Signature("E8 ?? ?? ?? ?? EB 8A 48 8B 1D", DetourName = nameof(EurekaContextMenuTell))]
DetourName = nameof(EurekaContextMenuTell)
)]
private Hook<EurekaContextMenuTellDelegate>? EurekaContextMenuTellHook { get; init; } private Hook<EurekaContextMenuTellDelegate>? EurekaContextMenuTellHook { get; init; }
// Offsets // Offsets
#pragma warning disable 0649 #pragma warning disable 0649
// TODO: Replace with CS version under AgentChatLog
[Signature("8B B9 ?? ?? ?? ?? 48 8B D9 83 FF FE 0F 84", Offset = 2)] [Signature("8B B9 ?? ?? ?? ?? 48 8B D9 83 FF FE 0F 84", Offset = 2)]
private readonly int? ReplyChannelOffset; private readonly int? ReplyChannelOffset;
// TODO: Replace with CS version under RaptureShellModule
[Signature("89 83 ?? ?? ?? ?? 48 8B 01 83 FE 13 7C 05 41 8B D4 EB 03 83 CA FF FF 90", Offset = 2)] [Signature("89 83 ?? ?? ?? ?? 48 8B 01 83 FE 13 7C 05 41 8B D4 EB 03 83 CA FF FF 90", Offset = 2)]
private readonly int? ShellChannelOffset; private readonly int? ShellChannelOffset;
// TODO: Replace with CS version under UiModule
[Signature("4C 8D B6 ?? ?? ?? ?? 41 8B 1E 45 85 E4 74 7A 33 FF 8B EF 66 0F 1F 44 00", Offset = 3)] [Signature("4C 8D B6 ?? ?? ?? ?? 41 8B 1E 45 85 E4 74 7A 33 FF 8B EF 66 0F 1F 44 00", Offset = 3)]
private readonly int? LinkshellCycleOffset; private readonly int? LinkshellCycleOffset;
[Signature("BA ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B F0 48 85 C0 0F 84 ?? ?? ?? ?? 48 8B 10 33", Offset = 1)]
private readonly uint? LinkshellInfoProxyIdx;
[Signature("BA ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 89 6C 24 ?? 4C 8B E0 48 89 74 24", Offset = 1)]
private readonly uint? CrossLinkshellInfoProxyIdx;
#pragma warning restore 0649 #pragma warning restore 0649
// Pointers // Pointers
@@ -136,9 +131,6 @@ internal sealed unsafe class Chat : IDisposable
[Signature("48 8D 15 ?? ?? ?? ?? 0F B6 C8 48 8D 05", ScanType = ScanType.StaticAddress)] [Signature("48 8D 15 ?? ?? ?? ?? 0F B6 C8 48 8D 05", ScanType = ScanType.StaticAddress)]
private readonly char* CurrentCharacter = null!; private readonly char* CurrentCharacter = null!;
[Signature("48 8D 0D ?? ?? ?? ?? 8B 14 ?? 85 D2 7E ?? 48 8B 0D ?? ?? ?? ?? 48 83 C1 10 E8 ?? ?? ?? ?? 8B 70 ?? 41 8D 4D", ScanType = ScanType.StaticAddress)]
private IntPtr ColourLookup { get; init; }
// Events // Events
internal delegate void ChatActivatedEventDelegate(ChatActivatedArgs args); internal delegate void ChatActivatedEventDelegate(ChatActivatedArgs args);
@@ -190,10 +182,7 @@ internal sealed unsafe class Chat : IDisposable
internal string? GetLinkshellName(uint idx) internal string? GetLinkshellName(uint idx)
{ {
if (LinkshellInfoProxyIdx is not { } proxyIdx) var infoProxy = Plugin.Functions.GetInfoProxyByIndex(InfoProxyId.LinkShell);
return null;
var infoProxy = Plugin.Functions.GetInfoProxyByIndex(proxyIdx);
if (infoProxy == IntPtr.Zero) if (infoProxy == IntPtr.Zero)
return null; return null;
@@ -207,10 +196,7 @@ internal sealed unsafe class Chat : IDisposable
internal string? GetCrossLinkshellName(uint idx) internal string? GetCrossLinkshellName(uint idx)
{ {
if (CrossLinkshellInfoProxyIdx is not { } proxyIdx) var infoProxy = Plugin.Functions.GetInfoProxyByIndex(InfoProxyId.CrossWorldLinkShell);
return null;
var infoProxy = Plugin.Functions.GetInfoProxyByIndex(proxyIdx);
if (infoProxy == IntPtr.Zero) if (infoProxy == IntPtr.Zero)
return null; return null;
@@ -249,35 +235,22 @@ internal sealed unsafe class Chat : IDisposable
return func(uiModule, idx); return func(uiModule, idx);
} }
// This function looks up a channel's user-defined colour. // This function looks up a channel's user-defined color.
// // If this function ever returns 0, it returns null instead.
// If this function would ever return 0, it returns null instead. internal uint? GetChannelColor(ChatType type)
internal uint? GetChannelColour(ChatType type)
{ {
if (GetColourInfo == null || ColourLookup == IntPtr.Zero)
return null;
// Colours are retrieved by looking up their code in a lookup table. Some codes share a colour, so they're lumped into a parent code here.
// Only codes >= 10 (say) have configurable colours.
// After getting the lookup value for the code, it is passed into a function with a handler which returns a pointer.
// This pointer + 32 is the RGB value. This functions returns RGBA with A always max.
var parent = new ChatCode((ushort) type).Parent(); var parent = new ChatCode((ushort) type).Parent();
switch (parent) switch (parent)
{ {
case ChatType.Debug: case ChatType.Debug:
case ChatType.Urgent: case ChatType.Urgent:
case ChatType.Notice: case ChatType.Notice:
return type.DefaultColour(); return type.DefaultColor();
} }
var framework = (IntPtr) Framework.Instance(); Plugin.GameConfig.TryGet(parent.ToConfigEntry(), out uint color);
var lookupResult = *(uint*) (ColourLookup + (int) parent * 4);
var info = GetColourInfo(framework + 16, lookupResult);
var rgb = *(uint*) (info + 32) & 0xFFFFFF;
var rgb = color & 0xFFFFFF;
if (rgb == 0) if (rgb == 0)
return null; return null;
@@ -750,7 +723,7 @@ internal sealed unsafe class Chat : IDisposable
{ {
var uC = Utf8String.FromString(c.ToString()); var uC = Utf8String.FromString(c.ToString());
SanitiseString(uC, 0x27F, IntPtr.Zero); SanitiseString(uC, 0x27F, nint.Zero);
var wasValid = uC->ToString().Length > 0; var wasValid = uC->ToString().Length > 0;
uC->Dtor(true); uC->Dtor(true);
+6 -24
View File
@@ -2,30 +2,23 @@ using ChatTwo.Util;
using Dalamud.Utility.Signatures; using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.System.Framework; 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.Component.GUI; using FFXIVClientStructs.FFXIV.Component.GUI;
namespace ChatTwo.GameFunctions; namespace ChatTwo.GameFunctions;
internal sealed unsafe class Context internal sealed unsafe class Context
{ {
// TODO: Replace with CS version after https://github.com/aers/FFXIVClientStructs/pull/873 got merged
[Signature("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 48 8B CB E8 ?? ?? ?? ?? 45 33 C9", Fallibility = Fallibility.Fallible)] [Signature("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 48 8B CB E8 ?? ?? ?? ?? 45 33 C9", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<IntPtr, ulong, ushort, byte*, byte> InviteToNoviceNetworkNative = null!; private readonly delegate* unmanaged<IntPtr, ulong, ushort, byte*, byte> InviteToNoviceNetworkNative = null!;
[Signature("E8 ?? ?? ?? ?? EB 35 BA", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<uint, uint, ulong, uint, byte, byte> TryOnNative = null!;
[Signature("E8 ?? ?? ?? ?? EB 7B 49 8B 06", Fallibility = Fallibility.Fallible)] [Signature("E8 ?? ?? ?? ?? EB 7B 49 8B 06", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<AgentInterface*, uint, void> LinkItemNative = null!; private readonly delegate* unmanaged<AgentInterface*, uint, void> LinkItemNative = null!;
[Signature("E8 ?? ?? ?? ?? EB 3F 83 F8 FE", Fallibility = Fallibility.Fallible)] [Signature("E8 ?? ?? ?? ?? EB 3F 83 F8 FE", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<AgentInterface*, ushort, uint, byte, void> ItemComparisonNative = null!; private readonly delegate* unmanaged<AgentInterface*, ushort, uint, byte, void> ItemComparisonNative = null!;
[Signature("48 89 5C 24 ?? 57 48 83 EC ?? 8B FA B8", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<IntPtr, uint, void> SearchForRecipesUsingItemNative = null!;
[Signature("E8 ?? ?? ?? ?? EB 45 45 33 C9", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<void*, uint, byte, void> SearchForItemNative = null!;
private Plugin Plugin { get; } private Plugin Plugin { get; }
internal Context(Plugin plugin) internal Context(Plugin plugin)
@@ -40,7 +33,7 @@ internal sealed unsafe class Context
return; return;
// 6.3: 221EFD // 6.3: 221EFD
var a1 = Plugin.Functions.GetInfoProxyByIndex(0x14); var a1 = Plugin.Functions.GetInfoProxyByIndex((InfoProxyId) 0x14);
// can specify content id if we have it, but there's no need // can specify content id if we have it, but there's no need
fixed (byte* namePtr = name.ToTerminatedBytes()) { fixed (byte* namePtr = name.ToTerminatedBytes()) {
@@ -58,10 +51,7 @@ internal sealed unsafe class Context
internal void TryOn(uint itemId, byte stainId) internal void TryOn(uint itemId, byte stainId)
{ {
if (TryOnNative == null) AgentTryon.TryOn(0xFF, itemId, stainId, 0, 0);
return;
TryOnNative(0xFF, itemId, stainId, 0, 0);
} }
internal void LinkItem(uint itemId) internal void LinkItem(uint itemId)
@@ -84,19 +74,11 @@ internal sealed unsafe class Context
internal void SearchForRecipesUsingItem(uint itemId) internal void SearchForRecipesUsingItem(uint itemId)
{ {
if (SearchForRecipesUsingItemNative == null) AgentRecipeProductList.Instance()->SearchForRecipesUsingItem(itemId);
return;
var a1 = (nint) AgentModule.Instance()->GetAgentByInternalId(AgentId.RecipeProductList);
SearchForRecipesUsingItemNative(a1, itemId);
} }
internal void SearchForItem(uint itemId) internal void SearchForItem(uint itemId)
{ {
if (SearchForItemNative == null) Framework.Instance()->GetUiModule()->GetItemFinderModule()->SearchForItem(itemId, true);
return;
var itemFinder = Framework.Instance()->GetUiModule()->GetItemFinderModule();
SearchForItemNative(itemFinder, itemId, 1);
} }
} }
+2 -2
View File
@@ -60,13 +60,13 @@ internal unsafe class GameFunctions : IDisposable
Marshal.FreeHGlobal(PlaceholderNamePtr); Marshal.FreeHGlobal(PlaceholderNamePtr);
} }
internal nint GetInfoProxyByIndex(uint idx) internal nint GetInfoProxyByIndex(InfoProxyId proxyId)
{ {
var infoModule = InfoModule.Instance(); var infoModule = InfoModule.Instance();
if (infoModule == null) if (infoModule == null)
return nint.Zero; return nint.Zero;
return (nint) infoModule->GetInfoProxyById(idx); return (nint) infoModule->GetInfoProxyById(proxyId);
} }
internal int GetCurrentChatLogEntryIndex() internal int GetCurrentChatLogEntryIndex()
+5 -3
View File
@@ -2,12 +2,14 @@ using ChatTwo.Util;
using Dalamud.Utility.Signatures; using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.System.Framework; 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.Component.GUI; using FFXIVClientStructs.FFXIV.Component.GUI;
namespace ChatTwo.GameFunctions; namespace ChatTwo.GameFunctions;
internal sealed unsafe class Party internal sealed unsafe class Party
{ {
// TODO: Replace all hooks with CS after https://github.com/aers/FFXIVClientStructs/pull/872 got merged
[Signature("E8 ?? ?? ?? ?? 33 C0 EB 51", Fallibility = Fallibility.Fallible)] [Signature("E8 ?? ?? ?? ?? 33 C0 EB 51", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<IntPtr, ulong, byte*, ushort, byte> InviteToPartyNative = null!; private readonly delegate* unmanaged<IntPtr, ulong, byte*, ushort, byte> InviteToPartyNative = null!;
@@ -37,7 +39,7 @@ internal sealed unsafe class Party
return; return;
// 6.11: 214A55 // 6.11: 214A55
var a1 = Plugin.Functions.GetInfoProxyByIndex(2); var a1 = Plugin.Functions.GetInfoProxyByIndex(InfoProxyId.PartyInvite);
// this only works if target is on the same world // this only works if target is on the same world
fixed (byte* namePtr = name.ToTerminatedBytes()) { fixed (byte* namePtr = name.ToTerminatedBytes()) {
@@ -51,7 +53,7 @@ internal sealed unsafe class Party
return; return;
// 6.11: 214A55 // 6.11: 214A55
var a1 = Plugin.Functions.GetInfoProxyByIndex(2); var a1 = Plugin.Functions.GetInfoProxyByIndex(InfoProxyId.PartyInvite);
// third param is world, but it requires a specific world // third param is world, but it requires a specific world
// if they're not on that world, it will fail // if they're not on that world, it will fail
@@ -67,7 +69,7 @@ internal sealed unsafe class Party
return; return;
// 6.11: 214A55 // 6.11: 214A55
var a1 = Plugin.Functions.GetInfoProxyByIndex(2); var a1 = Plugin.Functions.GetInfoProxyByIndex(InfoProxyId.PartyInvite);
// third param is world, but it requires a specific world // third param is world, but it requires a specific world
// if they're not on that world, it will fail // if they're not on that world, it will fail
+2 -2
View File
@@ -675,7 +675,7 @@ public sealed class ChatLogWindow : Window
} }
var normalColor = ImGui.GetColorU32(ImGuiCol.Text); var normalColor = ImGui.GetColorU32(ImGuiCol.Text);
var inputColour = Plugin.Config.ChatColours.TryGetValue(inputType, out var inputCol) ? inputCol : inputType.DefaultColour(); var inputColour = Plugin.Config.ChatColours.TryGetValue(inputType, out var inputCol) ? inputCol : inputType.DefaultColor();
if (!isCommand && Plugin.ExtraChat.ChannelOverride is var (_, overrideColour)) if (!isCommand && Plugin.ExtraChat.ChannelOverride is var (_, overrideColour))
inputColour = overrideColour; inputColour = overrideColour;
@@ -1583,7 +1583,7 @@ public sealed class ChatLogWindow : Window
if (colour == null && text.FallbackColour != null) if (colour == null && text.FallbackColour != null)
{ {
var type = text.FallbackColour.Value; var type = text.FallbackColour.Value;
colour = Plugin.Config.ChatColours.TryGetValue(type, out var col) ? col : type.DefaultColour(); colour = Plugin.Config.ChatColours.TryGetValue(type, out var col) ? col : type.DefaultColor();
} }
var push = colour != null; var push = colour != null;
+8 -3
View File
@@ -178,6 +178,7 @@ public partial class InputPreview : Window
NextChunkIsAutoTranslate = true; NextChunkIsAutoTranslate = true;
// TODO: Remove after Key and Group in AutoTranslatePayload became public
// Skipping: StartByte, PayloadType, PayloadLength // Skipping: StartByte, PayloadType, PayloadLength
using var reader = new BinaryReader(new MemoryStream(chunk.Link!.Encode().Skip(3).ToArray())); using var reader = new BinaryReader(new MemoryStream(chunk.Link!.Encode().Skip(3).ToArray()));
var group = (uint) reader.ReadByte(); var group = (uint) reader.ReadByte();
@@ -199,7 +200,7 @@ public partial class InputPreview : Window
if (ImGui.GetContentRegionAvail().X < emoteSize.X) if (ImGui.GetContentRegionAvail().X < emoteSize.X)
ImGui.NewLine(); ImGui.NewLine();
// We only draw a dummy if it is still loading, in the case it failed we draw the actual name // We only draw a dummy if it is still loading, in case it failed, we draw the actual name
var image = EmoteCache.GetEmote(emotePayload.Code); var image = EmoteCache.GetEmote(emotePayload.Code);
if (image is { Failed: false }) if (image is { Failed: false })
{ {
@@ -216,11 +217,15 @@ public partial class InputPreview : Window
} }
} }
if (NextChunkIsAutoTranslate)
if (text.Link != null || NextChunkIsAutoTranslate)
{ {
NextChunkIsAutoTranslate = false; NextChunkIsAutoTranslate = false;
ImGuiUtil.WrapText(text.Content, chunk, handler, LogWindow.DefaultText, lineWidth);
return;
}
if (text.Link != null)
{
if (text.Link is ItemPayload) if (text.Link is ItemPayload)
CursorPosition += "<item>".Length; CursorPosition += "<item>".Length;
else if (text.Link is MapLinkPayload) else if (text.Link is MapLinkPayload)
+3 -3
View File
@@ -50,15 +50,15 @@ internal sealed class ChatColours : ISettingsTab
if (ImGuiUtil.IconButton(FontAwesomeIcon.LongArrowAltDown, $"{type}", Language.Options_ChatColours_Import)) if (ImGuiUtil.IconButton(FontAwesomeIcon.LongArrowAltDown, $"{type}", Language.Options_ChatColours_Import))
{ {
var gameColour = Plugin.Functions.Chat.GetChannelColour(type); var gameColour = Plugin.Functions.Chat.GetChannelColor(type);
Mutable.ChatColours[type] = gameColour ?? type.DefaultColour() ?? 0; Mutable.ChatColours[type] = gameColour ?? type.DefaultColor() ?? 0;
} }
ImGui.SameLine(); ImGui.SameLine();
var vec = Mutable.ChatColours.TryGetValue(type, out var colour) var vec = Mutable.ChatColours.TryGetValue(type, out var colour)
? ColourUtil.RgbaToVector3(colour) ? ColourUtil.RgbaToVector3(colour)
: ColourUtil.RgbaToVector3(type.DefaultColour() ?? 0); : ColourUtil.RgbaToVector3(type.DefaultColor() ?? 0);
if (ImGui.ColorEdit3(type.Name(), ref vec, ImGuiColorEditFlags.NoInputs)) if (ImGui.ColorEdit3(type.Name(), ref vec, ImGuiColorEditFlags.NoInputs))
Mutable.ChatColours[type] = ColourUtil.Vector3ToRgba(vec); Mutable.ChatColours[type] = ColourUtil.Vector3ToRgba(vec);
} }