More cleanup

This commit is contained in:
Infi
2024-04-11 07:09:09 +02:00
parent 48fec7dfaa
commit c24ca3c007
11 changed files with 199 additions and 189 deletions
+37 -37
View File
@@ -7,53 +7,53 @@ using FFXIVClientStructs.FFXIV.Component.GUI;
namespace ChatTwo.GameFunctions; namespace ChatTwo.GameFunctions;
internal sealed unsafe class Context { internal sealed unsafe class Context
{
[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> _inviteToNoviceNetwork = null!; private readonly delegate* unmanaged<IntPtr, ulong, ushort, byte*, byte> InviteToNoviceNetworkNative = null!;
[Signature("E8 ?? ?? ?? ?? EB 35 BA", Fallibility = Fallibility.Fallible)] [Signature("E8 ?? ?? ?? ?? EB 35 BA", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<uint, uint, ulong, uint, byte, byte> _tryOn = null!; 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> _linkItem = 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> _itemComparison = null!; private readonly delegate* unmanaged<AgentInterface*, ushort, uint, byte, void> ItemComparisonNative = null!;
[Signature("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 48 83 F8 0F", Fallibility = Fallibility.Fallible)] [Signature("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 48 83 F8 0F", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<IntPtr, uint, void> _searchForRecipesUsingItem = null!; private readonly delegate* unmanaged<IntPtr, uint, void> SearchForRecipesUsingItemNative = null!;
[Signature("E8 ?? ?? ?? ?? EB 45 45 33 C9", Fallibility = Fallibility.Fallible)] [Signature("E8 ?? ?? ?? ?? EB 45 45 33 C9", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<void*, uint, byte, void> _searchForItem = null!; private readonly delegate* unmanaged<void*, uint, byte, void> SearchForItemNative = null!;
#region Offsets #region Offsets
[Signature( [Signature(
"FF 90 ?? ?? ?? ?? 8B 93 ?? ?? ?? ?? 48 8B C8 E8 ?? ?? ?? ?? 41 0F B6 D4 48 8B CB E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 48 81 FF ?? ?? ?? ?? 0F 85", "FF 90 ?? ?? ?? ?? 8B 93 ?? ?? ?? ?? 48 8B C8 E8 ?? ?? ?? ?? 41 0F B6 D4 48 8B CB E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 48 81 FF ?? ?? ?? ?? 0F 85",
Offset = 2 Offset = 2
)] )]
private readonly int? _searchForRecipesUsingItemVfunc; private readonly int? SearchForRecipesUsingItemVfunc;
#endregion #endregion
private Plugin Plugin { get; } private Plugin Plugin { get; }
internal Context(Plugin plugin) { internal Context(Plugin plugin)
{
Plugin = plugin; Plugin = plugin;
Plugin.GameInteropProvider.InitializeFromAttributes(this); Plugin.GameInteropProvider.InitializeFromAttributes(this);
} }
internal void InviteToNoviceNetwork(string name, ushort world) { internal void InviteToNoviceNetwork(string name, ushort world)
if (_inviteToNoviceNetwork == null) { {
if (InviteToNoviceNetworkNative == null)
return; return;
}
// 6.3: 221EFD // 6.3: 221EFD
var a1 = Plugin.Functions.GetInfoProxyByIndex(0x14); var a1 = Plugin.Functions.GetInfoProxyByIndex(0x14);
fixed (byte* namePtr = name.ToTerminatedBytes()) {
// 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
_inviteToNoviceNetwork(a1, 0, world, namePtr); fixed (byte* namePtr = name.ToTerminatedBytes()) {
InviteToNoviceNetworkNative(a1, 0, world, namePtr);
} }
} }
@@ -65,49 +65,49 @@ internal sealed unsafe class Context {
// 0x10005: copy item name // 0x10005: copy item name
// 0x10006: search recipes using this material // 0x10006: search recipes using this material
internal void TryOn(uint itemId, byte stainId) { internal void TryOn(uint itemId, byte stainId)
if (_tryOn == null) { {
if (TryOnNative == null)
return; return;
TryOnNative(0xFF, itemId, stainId, 0, 0);
} }
_tryOn(0xFF, itemId, stainId, 0, 0); internal void LinkItem(uint itemId)
} {
if (LinkItemNative == null)
internal void LinkItem(uint itemId) {
if (_linkItem == null) {
return; return;
}
var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ChatLog); var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ChatLog);
_linkItem(agent, itemId); LinkItemNative(agent, itemId);
} }
internal void OpenItemComparison(uint itemId) { internal void OpenItemComparison(uint itemId)
if (_itemComparison == null) { {
if (ItemComparisonNative == null)
return; return;
}
var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ItemCompare); var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ItemCompare);
_itemComparison(agent, 0x4D, itemId, 0); ItemComparisonNative(agent, 0x4D, itemId, 0);
} }
internal void SearchForRecipesUsingItem(uint itemId) { internal void SearchForRecipesUsingItem(uint itemId)
if (_searchForRecipesUsingItem == null || _searchForRecipesUsingItemVfunc is not { } offset) { {
if (SearchForRecipesUsingItemNative == null || SearchForRecipesUsingItemVfunc is not { } offset)
return; return;
}
var uiModule = Framework.Instance()->GetUiModule(); var uiModule = Framework.Instance()->GetUiModule();
var vf = (delegate* unmanaged<UIModule*, IntPtr>) uiModule->vfunc[offset / 8]; var vf = (delegate* unmanaged<UIModule*, IntPtr>) uiModule->vfunc[offset / 8];
var a1 = vf(uiModule); var a1 = vf(uiModule);
_searchForRecipesUsingItem(a1, itemId); SearchForRecipesUsingItemNative(a1, itemId);
} }
internal void SearchForItem(uint itemId) { internal void SearchForItem(uint itemId)
if (_searchForItem == null) { {
if (SearchForItemNative == null)
return; return;
}
var itemFinder = Framework.Instance()->GetUiModule()->GetItemFinderModule(); var itemFinder = Framework.Instance()->GetUiModule()->GetItemFinderModule();
_searchForItem(itemFinder, itemId, 1); SearchForItemNative(itemFinder, itemId, 1);
} }
} }
+96 -98
View File
@@ -11,8 +11,10 @@ using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType;
namespace ChatTwo.GameFunctions; namespace ChatTwo.GameFunctions;
internal unsafe class GameFunctions : IDisposable { internal unsafe class GameFunctions : IDisposable
private static class Signatures { {
private static class Signatures
{
internal const string IsMentorA1 = "48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 84 C0 74 71 0F B6 86"; internal const string IsMentorA1 = "48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 84 C0 74 71 0F B6 86";
internal const string ResolveTextCommandPlaceholder = "E8 ?? ?? ?? ?? 49 8D 4F 18 4C 8B E0"; internal const string ResolveTextCommandPlaceholder = "E8 ?? ?? ?? ?? 49 8D 4F 18 4C 8B E0";
@@ -20,52 +22,47 @@ internal unsafe class GameFunctions : IDisposable {
} }
#region Functions #region Functions
[Signature("E8 ?? ?? ?? ?? 8B FD 8B CD", Fallibility = Fallibility.Fallible)] [Signature("E8 ?? ?? ?? ?? 8B FD 8B CD", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<IntPtr, uint, IntPtr> _getInfoProxyByIndex = null!; private readonly delegate* unmanaged<IntPtr, uint, IntPtr> GetInfoProxyByIndexNative = null!;
[Signature("E8 ?? ?? ?? ?? 84 C0 74 0D B0 02", Fallibility = Fallibility.Fallible)] [Signature("E8 ?? ?? ?? ?? 84 C0 74 0D B0 02", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<IntPtr, byte> _isMentor = null!; private readonly delegate* unmanaged<IntPtr, byte> IsMentorNative = null!;
[Signature("48 89 5C 24 ?? 57 48 83 EC 20 48 8B FA 48 8B D9 E8 ?? ?? ?? ?? 48 8B 8B ?? ?? ?? ?? 48 85 C9", Fallibility = Fallibility.Fallible)] [Signature("48 89 5C 24 ?? 57 48 83 EC 20 48 8B FA 48 8B D9 E8 ?? ?? ?? ?? 48 8B 8B ?? ?? ?? ?? 48 85 C9", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<AgentInterface*, ulong, byte> _openPartyFinder = null!; private readonly delegate* unmanaged<AgentInterface*, ulong, byte> OpenPartyFinderNative = null!;
[Signature("E8 ?? ?? ?? ?? EB 20 48 8B 46 28", Fallibility = Fallibility.Fallible)] [Signature("E8 ?? ?? ?? ?? EB 20 48 8B 46 28", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<AgentInterface*, uint, void> _openAchievement = null!; private readonly delegate* unmanaged<AgentInterface*, uint, void> OpenAchievementNative = null!;
[Signature("E8 ?? ?? ?? ?? 41 8D 4F 08 84 C0", Fallibility = Fallibility.Fallible)] [Signature("E8 ?? ?? ?? ?? 41 8D 4F 08 84 C0", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<byte> _inInstance = null!; private readonly delegate* unmanaged<byte> InInstanceNative = null!;
#endregion #endregion
#region Hooks #region Hooks
private delegate IntPtr ResolveTextCommandPlaceholderDelegate(IntPtr a1, byte* placeholderText, byte a3, byte a4); private delegate IntPtr ResolveTextCommandPlaceholderDelegate(IntPtr a1, byte* placeholderText, byte a3, byte a4);
[Signature(Signatures.ResolveTextCommandPlaceholder, DetourName = nameof(ResolveTextCommandPlaceholderDetour))] [Signature(Signatures.ResolveTextCommandPlaceholder, DetourName = nameof(ResolveTextCommandPlaceholderDetour))]
private Hook<ResolveTextCommandPlaceholderDelegate>? ResolveTextCommandPlaceholderHook { get; init; } private Hook<ResolveTextCommandPlaceholderDelegate>? ResolveTextCommandPlaceholderHook { get; init; }
#endregion #endregion
#pragma warning disable 0649 #pragma warning disable 0649
[Signature(Signatures.CurrentChatEntryOffset, Offset = 2)] [Signature(Signatures.CurrentChatEntryOffset, Offset = 2)]
private readonly byte? _currentChatEntryOffset; private readonly byte? CurrentChatEntryOffset;
[Signature(Signatures.IsMentorA1, ScanType = ScanType.StaticAddress)] [Signature(Signatures.IsMentorA1, ScanType = ScanType.StaticAddress)]
private readonly IntPtr? _isMentorA1; private readonly IntPtr? IsMentorA1;
#pragma warning restore 0649 #pragma warning restore 0649
[Signature("FF 90 ?? ?? ?? ?? 48 8B C8 BA ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B F0 48 85 C0 0F 84 ?? ?? ?? ?? 48 8B 10 33 ED", Offset = 2)] [Signature("FF 90 ?? ?? ?? ?? 48 8B C8 BA ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B F0 48 85 C0 0F 84 ?? ?? ?? ?? 48 8B 10 33 ED", Offset = 2)]
private readonly int? _infoModuleVfunc; private readonly int? InfoModuleVfunc;
private Plugin Plugin { get; } private Plugin Plugin { get; }
internal Party Party { get; } internal Party Party { get; }
internal Chat Chat { get; } internal Chat Chat { get; }
internal Context Context { get; } internal Context Context { get; }
internal GameFunctions(Plugin plugin) { internal GameFunctions(Plugin plugin)
{
Plugin = plugin; Plugin = plugin;
Party = new Party(Plugin); Party = new Party(Plugin);
Chat = new Chat(Plugin); Chat = new Chat(Plugin);
@@ -76,101 +73,105 @@ internal unsafe class GameFunctions : IDisposable {
ResolveTextCommandPlaceholderHook?.Enable(); ResolveTextCommandPlaceholderHook?.Enable();
} }
public void Dispose() { public void Dispose()
{
Chat.Dispose(); Chat.Dispose();
ResolveTextCommandPlaceholderHook?.Dispose(); ResolveTextCommandPlaceholderHook?.Dispose();
Marshal.FreeHGlobal(_placeholderNamePtr); Marshal.FreeHGlobal(PlaceholderNamePtr);
} }
private IntPtr GetInfoModule() { private IntPtr GetInfoModule()
if (_infoModuleVfunc is not { } vfunc) { {
if (InfoModuleVfunc is not { } vfunc)
return IntPtr.Zero; return IntPtr.Zero;
}
var uiModule = Framework.Instance()->GetUiModule(); var uiModule = Framework.Instance()->GetUiModule();
var getInfoModule = (delegate* unmanaged<UIModule*, IntPtr>) uiModule->vfunc[vfunc / 8]; var getInfoModule = (delegate* unmanaged<UIModule*, IntPtr>) uiModule->vfunc[vfunc / 8];
return getInfoModule(uiModule); return getInfoModule(uiModule);
} }
internal IntPtr GetInfoProxyByIndex(uint idx) { internal IntPtr GetInfoProxyByIndex(uint idx)
{
var infoModule = GetInfoModule(); var infoModule = GetInfoModule();
return infoModule == IntPtr.Zero ? IntPtr.Zero : _getInfoProxyByIndex(infoModule, idx); return infoModule == IntPtr.Zero ? IntPtr.Zero : GetInfoProxyByIndexNative(infoModule, idx);
} }
internal uint? GetCurrentChatLogEntryIndex() { internal uint? GetCurrentChatLogEntryIndex()
if (_currentChatEntryOffset == null) { {
if (CurrentChatEntryOffset == null)
return null; return null;
}
var log = (IntPtr) Framework.Instance()->GetUiModule()->GetRaptureLogModule(); var log = (IntPtr) Framework.Instance()->GetUiModule()->GetRaptureLogModule();
return *(uint*) (log + _currentChatEntryOffset.Value); return *(uint*) (log + CurrentChatEntryOffset.Value);
} }
internal void SendFriendRequest(string name, ushort world) { internal void SendFriendRequest(string name, ushort world)
{
ListCommand(name, world, "friendlist"); ListCommand(name, world, "friendlist");
} }
internal void AddToBlacklist(string name, ushort world) { internal void AddToBlacklist(string name, ushort world)
{
ListCommand(name, world, "blist"); ListCommand(name, world, "blist");
} }
private void ListCommand(string name, ushort world, string commandName) { private void ListCommand(string name, ushort world, string commandName)
{
var row = Plugin.DataManager.GetExcelSheet<World>()!.GetRow(world); var row = Plugin.DataManager.GetExcelSheet<World>()!.GetRow(world);
if (row == null) { if (row == null)
return; return;
}
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.Functions.Chat.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.GetSingleton()->RaptureAtkUnitManager;
var addon = (IntPtr) unitManager->GetAddonByName(name); var addon = (IntPtr) unitManager->GetAddonByName(name);
if (addon == IntPtr.Zero) { if (addon == IntPtr.Zero)
return; return;
}
var flags = (uint*) (addon + 0x180); var flags = (uint*) (addon + 0x180);
if (interactable) { if (interactable)
*flags &= ~(1u << 22); *flags &= ~(1u << 22);
} else { else
*flags |= 1 << 22; *flags |= 1 << 22;
} }
}
internal static void SetChatInteractable(bool interactable) { internal static void SetChatInteractable(bool interactable)
for (var i = 0; i < 4; i++) { {
for (var i = 0; i < 4; i++)
SetAddonInteractable($"ChatLogPanel_{i}", interactable); SetAddonInteractable($"ChatLogPanel_{i}", interactable);
}
SetAddonInteractable("ChatLog", interactable); SetAddonInteractable("ChatLog", interactable);
} }
internal static bool IsAddonInteractable(string name) { internal static bool IsAddonInteractable(string name)
{
var unitManager = AtkStage.GetSingleton()->RaptureAtkUnitManager; var unitManager = AtkStage.GetSingleton()->RaptureAtkUnitManager;
var addon = (IntPtr) unitManager->GetAddonByName(name); var addon = (IntPtr) unitManager->GetAddonByName(name);
if (addon == IntPtr.Zero) { if (addon == IntPtr.Zero)
return false; return false;
}
var flags = (uint*) (addon + 0x180); var flags = (uint*) (addon + 0x180);
return (*flags & (1 << 22)) == 0; return (*flags & (1 << 22)) == 0;
} }
internal static void OpenItemTooltip(uint id) { internal static void OpenItemTooltip(uint id)
{
var atkStage = AtkStage.GetSingleton(); var atkStage = AtkStage.GetSingleton();
var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ItemDetail); var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ItemDetail);
var addon = atkStage->RaptureAtkUnitManager->GetAddonByName("ItemDetail"); var addon = atkStage->RaptureAtkUnitManager->GetAddonByName("ItemDetail");
if (agent == null || addon == null) {
// atkStage ain't gonna be null or we have bigger problems // atkStage ain't gonna be null or we have bigger problems
if (agent == null || addon == null)
return; return;
}
var agentPtr = (IntPtr) agent; var agentPtr = (IntPtr) agent;
@@ -203,74 +204,74 @@ internal unsafe class GameFunctions : IDisposable {
(*vf5)(addon, 0, 15); (*vf5)(addon, 0, 15);
} }
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.GetSingleton()->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 = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ItemDetail);
if (agent != null) { if (agent != null)
agent->Hide(); agent->Hide();
} }
}
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 = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.LookingForGroup);
if (lfg->IsAgentActive()) { if (lfg->IsAgentActive())
{
var addonId = lfg->GetAddonID(); var addonId = lfg->GetAddonID();
var atkModule = Framework.Instance()->GetUiModule()->GetRaptureAtkModule(); var atkModule = Framework.Instance()->GetUiModule()->GetRaptureAtkModule();
var atkModuleVtbl = (void**) atkModule->AtkModule.vtbl; var atkModuleVtbl = (void**) atkModule->AtkModule.vtbl;
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);
} else { }
else
{
// 6.05: 8443DD // 6.05: 8443DD
if (*(uint*) ((IntPtr) lfg + 0x2C20) > 0) { if (*(uint*) ((IntPtr) lfg + 0x2C20) > 0)
lfg->Hide(); lfg->Hide();
} else { else
lfg->Show(); lfg->Show();
} }
} }
}
internal bool IsMentor() { internal bool IsMentor()
if (_isMentor == null || _isMentorA1 == null || _isMentorA1.Value == IntPtr.Zero) { {
if (IsMentorNative == null || IsMentorA1 == null || IsMentorA1.Value == IntPtr.Zero)
return false; return false;
return IsMentorNative(IsMentorA1.Value) > 0;
} }
return _isMentor(_isMentorA1.Value) > 0; internal void OpenPartyFinder(uint id)
} {
if (OpenPartyFinderNative == null)
internal void OpenPartyFinder(uint id) {
if (_openPartyFinder == null) {
return; return;
}
var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.LookingForGroup); var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.LookingForGroup);
if (agent != null) { if (agent != null)
_openPartyFinder(agent, id); OpenPartyFinderNative(agent, id);
}
} }
internal void OpenAchievement(uint id) { internal void OpenAchievement(uint id)
if (_openAchievement == null) { {
if (OpenAchievementNative == null)
return; return;
}
var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.Achievement); var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.Achievement);
if (agent != null) { if (agent != null)
_openAchievement(agent, id); OpenAchievementNative(agent, id);
}
} }
internal bool IsInInstance() { internal bool IsInInstance()
if (_inInstance == null) { {
if (InInstanceNative == null)
return false; return false;
}
return _inInstance() != 0; return InInstanceNative() != 0;
} }
internal bool TryOpenAdventurerPlate(ulong playerId) internal bool TryOpenAdventurerPlate(ulong playerId)
@@ -287,36 +288,33 @@ internal unsafe class GameFunctions : IDisposable {
} }
} }
internal void ClickNoviceNetworkButton() { internal void ClickNoviceNetworkButton()
{
var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ChatLog); var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ChatLog);
// case 3 // case 3
var value = new AtkValue { var value = new AtkValue { Type = ValueType.Int, Int = 3, };
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<AgentInterface*, int*, AtkValue*, ulong, ulong, int*>*) agent->VTable;
vf0(agent, &result, &value, 0, 0); vf0(agent, &result, &value, 0, 0);
} }
private readonly IntPtr _placeholderNamePtr = Marshal.AllocHGlobal(128); private readonly IntPtr PlaceholderNamePtr = Marshal.AllocHGlobal(128);
private readonly string _placeholder = $"<{Guid.NewGuid():N}>"; private readonly string Placeholder = $"<{Guid.NewGuid():N}>";
private string? _replacementName; private string? ReplacementName;
private IntPtr ResolveTextCommandPlaceholderDetour(IntPtr a1, byte* placeholderText, byte a3, byte a4) { private IntPtr ResolveTextCommandPlaceholderDetour(IntPtr a1, byte* placeholderText, byte a3, byte a4)
if (_replacementName == null) { {
if (ReplacementName == null)
goto Original; goto Original;
}
var placeholder = MemoryHelper.ReadStringNullTerminated((IntPtr) placeholderText); var placeholder = MemoryHelper.ReadStringNullTerminated((IntPtr) placeholderText);
if (placeholder != _placeholder) { if (placeholder != Placeholder)
goto Original; goto Original;
}
MemoryHelper.WriteString(_placeholderNamePtr, _replacementName); MemoryHelper.WriteString(PlaceholderNamePtr, ReplacementName);
_replacementName = null; ReplacementName = null;
return _placeholderNamePtr; return PlaceholderNamePtr;
Original: Original:
return ResolveTextCommandPlaceholderHook!.Original(a1, placeholderText, a3, a4); return ResolveTextCommandPlaceholderHook!.Original(a1, placeholderText, a3, a4);
+37 -36
View File
@@ -6,101 +6,102 @@ using FFXIVClientStructs.FFXIV.Component.GUI;
namespace ChatTwo.GameFunctions; namespace ChatTwo.GameFunctions;
internal sealed unsafe class Party { internal sealed unsafe class Party
{
[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> _inviteToParty = null!; private readonly delegate* unmanaged<IntPtr, ulong, byte*, ushort, byte> InviteToPartyNative = null!;
[Signature("48 83 EC 38 41 B1 09", Fallibility = Fallibility.Fallible)] [Signature("48 83 EC 38 41 B1 09", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<IntPtr, ulong, ushort, byte> _inviteToPartyContentId = null!; private readonly delegate* unmanaged<IntPtr, ulong, ushort, byte> InviteToPartyContentIdNative = null!;
[Signature("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 48 8B 83 ?? ?? ?? ?? 48 85 C0 74 62", Fallibility = Fallibility.Fallible)] [Signature("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 48 8B 83 ?? ?? ?? ?? 48 85 C0 74 62", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<IntPtr, ulong, byte> _inviteToPartyInInstance = null!; private readonly delegate* unmanaged<IntPtr, ulong, byte> InviteToPartyInInstanceNative = null!;
[Signature("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 49 8B 56 20", Fallibility = Fallibility.Fallible)] [Signature("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 49 8B 56 20", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<AgentInterface*, byte*, ushort, ulong, void> _promote = null!; private readonly delegate* unmanaged<AgentInterface*, byte*, ushort, ulong, void> PromoteNative = null!;
[Signature("E8 ?? ?? ?? ?? EB 66 49 8B 4E 20", Fallibility = Fallibility.Fallible)] [Signature("E8 ?? ?? ?? ?? EB 66 49 8B 4E 20", Fallibility = Fallibility.Fallible)]
private readonly delegate* unmanaged<AgentInterface*, byte*, ushort, ulong, void> _kick = null!; private readonly delegate* unmanaged<AgentInterface*, byte*, ushort, ulong, void> KickNative = null!;
private Plugin Plugin { get; } private Plugin Plugin { get; }
internal Party(Plugin plugin) { internal Party(Plugin plugin)
{
Plugin = plugin; Plugin = plugin;
Plugin.GameInteropProvider.InitializeFromAttributes(this); Plugin.GameInteropProvider.InitializeFromAttributes(this);
} }
internal void InviteSameWorld(string name, ushort world, ulong contentId) { internal void InviteSameWorld(string name, ushort world, ulong contentId)
if (_inviteToParty == null) { {
if (InviteToPartyNative == null)
return; return;
}
// 6.11: 214A55 // 6.11: 214A55
var a1 = Plugin.Functions.GetInfoProxyByIndex(2); var a1 = Plugin.Functions.GetInfoProxyByIndex(2);
fixed (byte* namePtr = name.ToTerminatedBytes()) {
// this only works if target is on the same world // this only works if target is on the same world
_inviteToParty(a1, contentId, namePtr, world); fixed (byte* namePtr = name.ToTerminatedBytes()) {
InviteToPartyNative(a1, contentId, namePtr, world);
} }
} }
internal void InviteOtherWorld(ulong contentId) { internal void InviteOtherWorld(ulong contentId)
if (_inviteToPartyContentId == null) { {
if (InviteToPartyContentIdNative == null)
return; return;
}
// 6.11: 214A55 // 6.11: 214A55
var a1 = Plugin.Functions.GetInfoProxyByIndex(2); var a1 = Plugin.Functions.GetInfoProxyByIndex(2);
if (contentId != 0) {
// 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
// pass 0 and it will work on any world EXCEPT for the world the // pass 0 and it will work on any world EXCEPT for the world the
// current player is on // current player is on
_inviteToPartyContentId(a1, contentId, 0); if (contentId != 0)
} InviteToPartyContentIdNative(a1, contentId, 0);
} }
internal void InviteInInstance(ulong contentId) { internal void InviteInInstance(ulong contentId)
if (_inviteToPartyInInstance == null) { {
if (InviteToPartyInInstanceNative == null)
return; return;
}
// 6.11: 214A55 // 6.11: 214A55
var a1 = Plugin.Functions.GetInfoProxyByIndex(2); var a1 = Plugin.Functions.GetInfoProxyByIndex(2);
if (contentId != 0) {
// 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
// pass 0 and it will work on any world EXCEPT for the world the // pass 0 and it will work on any world EXCEPT for the world the
// current player is on // current player is on
_inviteToPartyInInstance(a1, contentId); if (contentId != 0)
} InviteToPartyInInstanceNative(a1, contentId);
} }
internal void Kick(string name, ulong contentId) { internal void Kick(string name, ulong contentId)
if (_kick == null) { {
if (KickNative == null)
return; return;
}
var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.SocialPartyMember); var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.SocialPartyMember);
if (agent == null) { if (agent == null)
return; return;
}
fixed (byte* namePtr = name.ToTerminatedBytes()) { fixed (byte* namePtr = name.ToTerminatedBytes()) {
_kick(agent, namePtr, 0, contentId); KickNative(agent, namePtr, 0, contentId);
} }
} }
internal void Promote(string name, ulong contentId) { internal void Promote(string name, ulong contentId)
if (_promote == null) { {
if (PromoteNative == null)
return; return;
}
var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.SocialPartyMember); var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.SocialPartyMember);
if (agent == null) { if (agent == null)
return; return;
}
fixed (byte* namePtr = name.ToTerminatedBytes()) { fixed (byte* namePtr = name.ToTerminatedBytes()) {
_promote(agent, namePtr, 0, contentId); PromoteNative(agent, namePtr, 0, contentId);
} }
} }
} }
@@ -8,7 +8,8 @@ internal class ChannelSwitchInfo {
internal RotateMode Rotate { get; } internal RotateMode Rotate { get; }
internal string? Text { get; } internal string? Text { get; }
internal ChannelSwitchInfo(InputChannel? channel, bool permanent = false, RotateMode rotate = RotateMode.None, string? text = null) { internal ChannelSwitchInfo(InputChannel? channel, bool permanent = false, RotateMode rotate = RotateMode.None, string? text = null)
{
Channel = channel; Channel = channel;
Permanent = permanent; Permanent = permanent;
Rotate = rotate; Rotate = rotate;
@@ -1,13 +1,15 @@
namespace ChatTwo.GameFunctions.Types; namespace ChatTwo.GameFunctions.Types;
internal sealed class ChatActivatedArgs { internal sealed class ChatActivatedArgs
{
internal string? AddIfNotPresent { get; init; } internal string? AddIfNotPresent { get; init; }
internal string? Input { get; init; } internal string? Input { get; init; }
internal ChannelSwitchInfo ChannelSwitchInfo { get; } internal ChannelSwitchInfo ChannelSwitchInfo { get; }
internal TellReason? TellReason { get; init; } internal TellReason? TellReason { get; init; }
internal TellTarget? TellTarget { get; init; } internal TellTarget? TellTarget { get; init; }
internal ChatActivatedArgs(ChannelSwitchInfo channelSwitchInfo) { internal ChatActivatedArgs(ChannelSwitchInfo channelSwitchInfo)
{
ChannelSwitchInfo = channelSwitchInfo; ChannelSwitchInfo = channelSwitchInfo;
} }
} }
+2 -1
View File
@@ -2,7 +2,8 @@ using Dalamud.Game.ClientState.Keys;
namespace ChatTwo.GameFunctions.Types; namespace ChatTwo.GameFunctions.Types;
internal class Keybind { internal class Keybind
{
internal VirtualKey Key1 { get; init; } internal VirtualKey Key1 { get; init; }
internal ModifierFlag Modifier1 { get; init; } internal ModifierFlag Modifier1 { get; init; }
+2 -1
View File
@@ -1,7 +1,8 @@
namespace ChatTwo.GameFunctions.Types; namespace ChatTwo.GameFunctions.Types;
[Flags] [Flags]
internal enum ModifierFlag { internal enum ModifierFlag
{
Shift = 1 << 0, Shift = 1 << 0,
Ctrl = 1 << 1, Ctrl = 1 << 1,
Alt = 1 << 2, Alt = 1 << 2,
+2 -1
View File
@@ -1,6 +1,7 @@
namespace ChatTwo.GameFunctions.Types; namespace ChatTwo.GameFunctions.Types;
internal enum RotateMode { internal enum RotateMode
{
None, None,
Forward, Forward,
Reverse, Reverse,
@@ -1,11 +1,13 @@
namespace ChatTwo.GameFunctions.Types; namespace ChatTwo.GameFunctions.Types;
internal sealed class TellHistoryInfo { internal sealed class TellHistoryInfo
{
internal string Name { get; } internal string Name { get; }
internal uint World { get; } internal uint World { get; }
internal ulong ContentId { get; } internal ulong ContentId { get; }
internal TellHistoryInfo(string name, uint world, ulong contentId) { internal TellHistoryInfo(string name, uint world, ulong contentId)
{
Name = name; Name = name;
World = world; World = world;
ContentId = contentId; ContentId = contentId;
+2 -1
View File
@@ -1,6 +1,7 @@
namespace ChatTwo.GameFunctions.Types; namespace ChatTwo.GameFunctions.Types;
internal enum TellReason { internal enum TellReason
{
Direct = 0, Direct = 0,
PartyFinder = 1, PartyFinder = 1,
Reply = 2, Reply = 2,
+4 -2
View File
@@ -1,12 +1,14 @@
namespace ChatTwo.GameFunctions.Types; namespace ChatTwo.GameFunctions.Types;
internal sealed class TellTarget { internal sealed class TellTarget
{
internal string Name { get; } internal string Name { get; }
internal ushort World { get; } internal ushort World { get; }
internal ulong ContentId { get; } internal ulong ContentId { get; }
internal TellReason Reason { get; } internal TellReason Reason { get; }
internal TellTarget(string name, ushort world, ulong contentId, TellReason reason) { internal TellTarget(string name, ushort world, ulong contentId, TellReason reason)
{
Name = name; Name = name;
World = world; World = world;
ContentId = contentId; ContentId = contentId;