refactor: use ClientStructs more thoroughly

Obsolete old functions
This commit is contained in:
Anna 2021-11-04 01:56:26 -04:00
parent 35364d5bdb
commit 5e9321cc86
9 changed files with 94 additions and 130 deletions

View File

@ -113,7 +113,7 @@ namespace XivCommon.Functions {
this.Show(sender.Encode(), message.Encode(), options);
}
private void Show(byte[] sender, byte[] message, BattleTalkOptions? options) {
private unsafe void Show(byte[] sender, byte[] message, BattleTalkOptions? options) {
if (sender.Length == 0) {
throw new ArgumentException("sender cannot be empty", nameof(sender));
}
@ -128,15 +128,13 @@ namespace XivCommon.Functions {
options ??= new BattleTalkOptions();
var uiModule = this.Functions.GetUiModule();
var uiModule = (IntPtr) this.Functions.GetFramework()->GetUiModule();
unsafe {
fixed (byte* senderPtr = sender.Terminate(), messagePtr = message.Terminate()) {
if (this.HookEnabled) {
this.AddBattleTalkDetour(uiModule, (IntPtr) senderPtr, (IntPtr) messagePtr, options.Duration, (byte) options.Style);
} else {
this.AddBattleTalk(uiModule, (IntPtr) senderPtr, (IntPtr) messagePtr, options.Duration, (byte) options.Style);
}
fixed (byte* senderPtr = sender.Terminate(), messagePtr = message.Terminate()) {
if (this.HookEnabled) {
this.AddBattleTalkDetour(uiModule, (IntPtr) senderPtr, (IntPtr) messagePtr, options.Duration, (byte) options.Style);
} else {
this.AddBattleTalk(uiModule, (IntPtr) senderPtr, (IntPtr) messagePtr, options.Duration, (byte) options.Style);
}
}
}

View File

@ -32,12 +32,12 @@ namespace XivCommon.Functions {
/// </summary>
/// <param name="message">Message to send</param>
/// <exception cref="InvalidOperationException">If the signature for this function could not be found</exception>
public void SendMessage(string message) {
public unsafe void SendMessage(string message) {
if (this.ProcessChatBox == null) {
throw new InvalidOperationException("Could not find signature for chat sending");
}
var uiModule = this.Functions.GetUiModule();
var uiModule = (IntPtr) this.Functions.GetFramework()->GetUiModule();
using var payload = new ChatPayload(message);
var mem1 = Marshal.AllocHGlobal(400);

View File

@ -8,6 +8,7 @@ using Dalamud;
using Dalamud.Game;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Hooking;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using FFXIVClientStructs.FFXIV.Component.GUI;
using XivCommon.Functions.ContextMenu.Inventory;
using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType;
@ -281,13 +282,17 @@ namespace XivCommon.Functions.ContextMenu {
Unknown,
}
private (AgentType agentType, IntPtr agent) GetContextMenuAgent(IntPtr? agent = null) {
private unsafe (AgentType agentType, IntPtr agent) GetContextMenuAgent(IntPtr? agent = null) {
agent ??= this.Agent;
IntPtr GetAgent(AgentId id) {
return (IntPtr) this.Functions.GetFramework()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(id);
}
var agentType = AgentType.Unknown;
if (agent == this.Functions.GetAgentByInternalId(9u)) {
if (agent == GetAgent(AgentId.Context)) {
agentType = AgentType.Normal;
} else if (agent == this.Functions.GetAgentByInternalId(10u)) {
} else if (agent == GetAgent(AgentId.InventoryContext)) {
agentType = AgentType.Inventory;
}
@ -300,7 +305,7 @@ namespace XivCommon.Functions.ContextMenu {
return null;
}
var stage = (AtkStage*) this.Functions.GetAtkStageSingleton();
var stage = AtkStage.GetSingleton();
var parentAddon = this._getAddonByInternalId((IntPtr) stage->RaptureAtkUnitManager, parentAddonId);
return Encoding.UTF8.GetString(Util.ReadTerminated(parentAddon + 8));
}
@ -311,7 +316,7 @@ namespace XivCommon.Functions.ContextMenu {
return IntPtr.Zero;
}
var stage = (AtkStage*) this.Functions.GetAtkStageSingleton();
var stage = AtkStage.GetSingleton();
return this._getAddonByInternalId((IntPtr) stage->RaptureAtkUnitManager, addonId);
}

View File

@ -1,6 +1,7 @@
using System;
using System.Runtime.InteropServices;
using Dalamud.Game;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using Lumina.Excel.GeneratedSheets;
namespace XivCommon.Functions {
@ -49,12 +50,12 @@ namespace XivCommon.Functions {
/// </summary>
/// <param name="contentFinderCondition">ID of duty to show</param>
/// <exception cref="InvalidOperationException">if the open duty function could not be found in memory</exception>
public void OpenDuty(uint contentFinderCondition) {
public unsafe void OpenDuty(uint contentFinderCondition) {
if (this._openDuty == null) {
throw new InvalidOperationException("Could not find signature for open duty function");
}
var agent = this.Functions.GetAgentByInternalId(ContentsFinderAgentId);
var agent = (IntPtr) this.Functions.GetFramework()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ContentsFinder);
this._openDuty(agent, contentFinderCondition, 0);
}
@ -71,12 +72,12 @@ namespace XivCommon.Functions {
/// Opens the Duty Finder to the given roulette ID.
/// </summary>
/// <param name="roulette">ID of roulette to show</param>
public void OpenRoulette(byte roulette) {
public unsafe void OpenRoulette(byte roulette) {
if (this._openRoulette == null) {
throw new InvalidOperationException("Could not find signature for open roulette function");
}
var agent = this.Functions.GetAgentByInternalId(ContentsFinderAgentId);
var agent = (IntPtr) this.Functions.GetFramework()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ContentsFinder);
this._openRoulette(agent, roulette, 0);
}

View File

@ -41,7 +41,7 @@ namespace XivCommon.Functions {
/// </summary>
/// <param name="objectId">Object ID to open window for</param>
/// <exception cref="InvalidOperationException">If the signature for this function could not be found</exception>
public void OpenExamineWindow(uint objectId) {
public unsafe void OpenExamineWindow(uint objectId) {
if (this.RequestCharacterInfo == null) {
throw new InvalidOperationException("Could not find signature for Examine function");
}
@ -51,19 +51,17 @@ namespace XivCommon.Functions {
// offsets and stuff come from the beginning of case 0x2c (around line 621 in IDA)
// if 29f8 ever changes, I'd just scan for it in old binary and find what it is in the new binary at the same spot
// 40 55 53 57 41 54 41 55 41 56 48 8D 6C 24 ??
var agentModule = this.Functions.GetAgentModule();
var agentModule = (IntPtr) this.Functions.GetFramework()->GetUiModule()->GetAgentModule();
var rciData = Marshal.ReadIntPtr(agentModule + 0x1A0);
unsafe {
// offsets at sig E8 ?? ?? ?? ?? 33 C0 EB 4C
// this is called at the end of the 2c case
var raw = (uint*) rciData;
*(raw + 10) = objectId;
*(raw + 11) = objectId;
*(raw + 12) = objectId;
*(raw + 13) = 0xE0000000;
*(raw + 311) = 0;
}
// offsets at sig E8 ?? ?? ?? ?? 33 C0 EB 4C
// this is called at the end of the 2c case
var raw = (uint*) rciData;
*(raw + 10) = objectId;
*(raw + 11) = objectId;
*(raw + 12) = objectId;
*(raw + 13) = 0xE0000000;
*(raw + 311) = 0;
this.RequestCharacterInfo(rciData);
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
namespace XivCommon.Functions.FriendList {
/// <summary>
@ -22,37 +23,39 @@ namespace XivCommon.Functions.FriendList {
/// The list is empty if not logged in.
/// </para>
/// </summary>
public IList<FriendListEntry> List {
public unsafe IList<FriendListEntry> List {
get {
var friendListAgent = this.Functions.GetAgentByInternalId(FriendListAgentId);
var friendListAgent = (IntPtr) this.Functions
.GetFramework()
->GetUiModule()
->GetAgentModule()
->GetAgentByInternalId(AgentId.FriendList);
if (friendListAgent == IntPtr.Zero) {
return Array.Empty<FriendListEntry>();
}
unsafe {
var info = *(IntPtr*) (friendListAgent + InfoOffset);
if (info == IntPtr.Zero) {
return Array.Empty<FriendListEntry>();
}
var length = *(ushort*) (info + LengthOffset);
if (length == 0) {
return Array.Empty<FriendListEntry>();
}
var list = *(IntPtr*) (info + ListOffset);
if (list == IntPtr.Zero) {
return Array.Empty<FriendListEntry>();
}
var entries = new List<FriendListEntry>(length);
for (var i = 0; i < length; i++) {
var entry = *(FriendListEntry*) (list + i * FriendListEntry.Size);
entries.Add(entry);
}
return entries;
var info = *(IntPtr*) (friendListAgent + InfoOffset);
if (info == IntPtr.Zero) {
return Array.Empty<FriendListEntry>();
}
var length = *(ushort*) (info + LengthOffset);
if (length == 0) {
return Array.Empty<FriendListEntry>();
}
var list = *(IntPtr*) (info + ListOffset);
if (list == IntPtr.Zero) {
return Array.Empty<FriendListEntry>();
}
var entries = new List<FriendListEntry>(length);
for (var i = 0; i < length; i++) {
var entry = *(FriendListEntry*) (list + i * FriendListEntry.Size);
entries.Add(entry);
}
return entries;
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Runtime.InteropServices;
using Dalamud.Game;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using Lumina.Excel.GeneratedSheets;
namespace XivCommon.Functions {
@ -50,12 +51,12 @@ namespace XivCommon.Functions {
/// </summary>
/// <param name="questId">ID of quest to show</param>
/// <exception cref="InvalidOperationException">if the open quest function could not be found in memory</exception>
public void OpenQuest(uint questId) {
public unsafe void OpenQuest(uint questId) {
if (this._openQuest == null) {
throw new InvalidOperationException("Could not find signature for open quest function");
}
var agent = this.Functions.GetAgentByInternalId(JournalAgentId);
var agent = (IntPtr) this.Functions.GetFramework()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.Journal);
this._openQuest(agent, (int) (questId & 0xFFFF), 1, 0, 1);
}

View File

@ -97,7 +97,7 @@ namespace XivCommon.Functions.NamePlates {
return;
}
var atkModule = (RaptureAtkModule*) this.Functions.GetAtkModule();
var atkModule = this.Functions.GetFramework()->GetUiModule()->GetRaptureAtkModule();
var active = numbers->IntArray[0];

View File

@ -1,40 +1,26 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Dalamud.Game;
using Dalamud.Game.ClientState;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.Gui;
using Dalamud.Game.Gui.PartyFinder;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using FFXIVClientStructs.FFXIV.Component.GUI;
using XivCommon.Functions;
using XivCommon.Functions.ContextMenu;
using XivCommon.Functions.FriendList;
using XivCommon.Functions.NamePlates;
using XivCommon.Functions.Tooltips;
using Framework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework;
namespace XivCommon {
/// <summary>
/// A class containing game functions
/// </summary>
public class GameFunctions : IDisposable {
private static class Signatures {
internal const string GetAgentByInternalId = "E8 ?? ?? ?? ?? 83 FF 0D";
internal const string GetAtkStageSingleton = "E8 ?? ?? ?? ?? 41 B8 01 00 00 00 48 8D 15 ?? ?? ?? ?? 48 8B 48 20 E8 ?? ?? ?? ?? 48 8B CF";
}
private delegate IntPtr GetAtkStageSingletonDelegate();
private delegate IntPtr GetAgentModuleDelegate(IntPtr basePtr);
private delegate IntPtr GetAtkModuleDelegate(IntPtr uiModule);
private delegate IntPtr GetAgentByInternalIdDelegate(IntPtr agentModule, uint id);
private GameGui GameGui { get; }
private GetAgentByInternalIdDelegate? GetAgentByInternalIdInternal { get; }
private GetAtkStageSingletonDelegate? GetAtkStageSingletonInternal { get; }
private Dalamud.Game.Framework Framework { get; }
internal UiAlloc UiAlloc { get; }
@ -99,6 +85,7 @@ namespace XivCommon {
public Journal Journal { get; }
internal GameFunctions(Hooks hooks) {
this.Framework = Util.GetService<Dalamud.Game.Framework>();
this.GameGui = Util.GetService<GameGui>();
var clientState = Util.GetService<ClientState>();
@ -119,14 +106,6 @@ namespace XivCommon {
this.DutyFinder = new DutyFinder(this, scanner);
this.Journal = new Journal(this, scanner);
this.FriendList = new FriendList(this);
if (scanner.TryScanText(Signatures.GetAgentByInternalId, out var byInternalIdPtr, "GetAgentByInternalId")) {
this.GetAgentByInternalIdInternal = Marshal.GetDelegateForFunctionPointer<GetAgentByInternalIdDelegate>(byInternalIdPtr);
}
if (scanner.TryScanText(Signatures.GetAtkStageSingleton, out var getSingletonPtr, "GetAtkStageSingleton")) {
this.GetAtkStageSingletonInternal = Marshal.GetDelegateForFunctionPointer<GetAtkStageSingletonDelegate>(getSingletonPtr);
}
}
/// <inheritdoc />
@ -140,53 +119,39 @@ namespace XivCommon {
this.PartyFinder.Dispose();
}
/// <summary>
/// Convenience method to get a pointer to <see cref="Framework"/>.
/// </summary>
/// <returns>pointer to struct</returns>
public unsafe Framework* GetFramework() {
return (Framework*) this.Framework.Address.BaseAddress;
}
/// <summary>
/// Gets the pointer to the UI module
/// </summary>
/// <returns>Pointer</returns>
public IntPtr GetUiModule() {
return this.GameGui.GetUIModule();
[Obsolete("Use GetFramework()->GetUiModule()")]
public unsafe IntPtr GetUiModule() {
return (IntPtr) this.GetFramework()->GetUiModule();
}
/// <summary>
/// Gets the pointer to the RaptureAtkModule
/// </summary>
/// <returns>Pointer</returns>
public IntPtr GetAtkModule() {
var uiModule = this.GetUiModule();
if (uiModule == IntPtr.Zero) {
return IntPtr.Zero;
}
var getAtkModulePtr = FollowPtrChain(uiModule, new[] { 0, 0x38 });
if (getAtkModulePtr == IntPtr.Zero) {
return IntPtr.Zero;
}
var getAtkModule = Marshal.GetDelegateForFunctionPointer<GetAtkModuleDelegate>(getAtkModulePtr);
return getAtkModule(uiModule);
[Obsolete("Use GetFramework()->GetUiModule()->GetRaptureAtkModule()")]
public unsafe IntPtr GetAtkModule() {
return (IntPtr) this.GetFramework()->GetUiModule()->GetRaptureAtkModule();
}
/// <summary>
/// Gets the pointer to the agent module
/// </summary>
/// <returns>Pointer</returns>
public IntPtr GetAgentModule() {
var uiModule = this.GetUiModule();
var getAgentModulePtr = FollowPtrChain(uiModule, new[] { 0, 0x110 });
var getAgentModule = Marshal.GetDelegateForFunctionPointer<GetAgentModuleDelegate>(getAgentModulePtr);
return getAgentModule(uiModule);
}
private static IntPtr FollowPtrChain(IntPtr start, IEnumerable<int> offsets) {
foreach (var offset in offsets) {
start = Marshal.ReadIntPtr(start, offset);
if (start == IntPtr.Zero) {
break;
}
}
return start;
[Obsolete("Use GetFramework()->GetUiModule()->GetAgentModule()")]
public unsafe IntPtr GetAgentModule() {
return (IntPtr) this.GetFramework()->GetUiModule()->GetAgentModule();
}
/// <summary>
@ -195,13 +160,9 @@ namespace XivCommon {
/// <param name="id">internal id of agent</param>
/// <returns>Pointer</returns>
/// <exception cref="InvalidOperationException">if the signature for the function could not be found</exception>
public IntPtr GetAgentByInternalId(uint id) {
if (this.GetAgentByInternalIdInternal == null) {
throw new InvalidOperationException("Could not find signature for GetAgentByInternalId");
}
var agent = this.GetAgentModule();
return this.GetAgentByInternalIdInternal(agent, id);
[Obsolete("Use GetFramework()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId)")]
public unsafe IntPtr GetAgentByInternalId(uint id) {
return (IntPtr) this.GetFramework()->GetUiModule()->GetAgentModule()->GetAgentByInternalId((AgentId) id);
}
/// <summary>
@ -209,12 +170,9 @@ namespace XivCommon {
/// </summary>
/// <returns>Pointer</returns>
/// <exception cref="InvalidOperationException">if the signature for the function could not be found</exception>
public IntPtr GetAtkStageSingleton() {
if (this.GetAtkStageSingletonInternal == null) {
throw new InvalidOperationException("Could not find signature for GetAtkStageSingleton");
}
return this.GetAtkStageSingletonInternal();
[Obsolete("Use AtkStage.GetSingleton()")]
public unsafe IntPtr GetAtkStageSingleton() {
return (IntPtr) AtkStage.GetSingleton();
}
}
}