Compare commits

...

2 Commits

Author SHA1 Message Date
Anna 6df71875cc
chore: bump version to 8.0.0 2023-10-03 02:31:46 -04:00
Anna f22702f251
refactor: update for api 9 2023-10-03 02:30:28 -04:00
30 changed files with 2244 additions and 2258 deletions

View File

@ -2,13 +2,15 @@
using System.Runtime.InteropServices;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Hooking;
using Dalamud.Plugin.Services;
using Framework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework;
namespace XivCommon.Functions {
/// <summary>
/// The class containing BattleTalk functionality
/// </summary>
public class BattleTalk : IDisposable {
namespace XivCommon.Functions;
/// <summary>
/// The class containing BattleTalk functionality
/// </summary>
public class BattleTalk : IDisposable {
private bool HookEnabled { get; }
/// <summary>
@ -31,7 +33,7 @@ namespace XivCommon.Functions {
private AddBattleTalkDelegate? AddBattleTalk { get; }
private Hook<AddBattleTalkDelegate>? AddBattleTalkHook { get; }
internal unsafe BattleTalk(bool hook) {
internal unsafe BattleTalk(IGameInteropProvider interop, bool hook) {
this.HookEnabled = hook;
var addBattleTalkPtr = (IntPtr) Framework.Instance()->GetUiModule()->VTable->ShowBattleTalk;
@ -39,7 +41,7 @@ namespace XivCommon.Functions {
this.AddBattleTalk = Marshal.GetDelegateForFunctionPointer<AddBattleTalkDelegate>(addBattleTalkPtr);
if (this.HookEnabled) {
this.AddBattleTalkHook = Hook<AddBattleTalkDelegate>.FromAddress(addBattleTalkPtr, this.AddBattleTalkDetour);
this.AddBattleTalkHook = interop.HookFromAddress<AddBattleTalkDelegate>(addBattleTalkPtr, this.AddBattleTalkDetour);
this.AddBattleTalkHook.Enable();
}
}
@ -58,7 +60,7 @@ namespace XivCommon.Functions {
try {
return this.AddBattleTalkDetourInner(uiModule, senderPtr, messagePtr, duration, style);
} catch (Exception ex) {
Logger.LogError(ex, "Exception in BattleTalk detour");
Logger.Log.Error(ex, "Exception in BattleTalk detour");
}
Return:
@ -81,7 +83,7 @@ namespace XivCommon.Functions {
try {
this.OnBattleTalk?.Invoke(ref sender, ref message, ref options, ref handled);
} catch (Exception ex) {
Logger.LogError(ex, "Exception in BattleTalk event");
Logger.Log.Error(ex, "Exception in BattleTalk event");
}
if (handled) {
@ -133,12 +135,12 @@ namespace XivCommon.Functions {
}
}
}
}
}
/// <summary>
/// Options for displaying a BattleTalk window.
/// </summary>
public class BattleTalkOptions {
/// <summary>
/// Options for displaying a BattleTalk window.
/// </summary>
public class BattleTalkOptions {
/// <summary>
/// Duration to display the window, in seconds.
/// </summary>
@ -148,12 +150,12 @@ namespace XivCommon.Functions {
/// The style of the window.
/// </summary>
public BattleTalkStyle Style { get; set; } = BattleTalkStyle.Normal;
}
}
/// <summary>
/// BattleTalk window styles.
/// </summary>
public enum BattleTalkStyle : byte {
/// <summary>
/// BattleTalk window styles.
/// </summary>
public enum BattleTalkStyle : byte {
/// <summary>
/// A normal battle talk window with a white background.
/// </summary>
@ -178,5 +180,4 @@ namespace XivCommon.Functions {
/// </para>
/// </summary>
Blue = 9,
}
}

View File

@ -7,11 +7,12 @@ using FFXIVClientStructs.FFXIV.Client.System.Memory;
using FFXIVClientStructs.FFXIV.Client.System.String;
using Framework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework;
namespace XivCommon.Functions {
/// <summary>
/// A class containing chat functionality
/// </summary>
public class Chat {
namespace XivCommon.Functions;
/// <summary>
/// A class containing chat functionality
/// </summary>
public class Chat {
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";
internal const string SanitiseString = "E8 ?? ?? ?? ?? EB 0A 48 8D 4C 24 ?? E8 ?? ?? ?? ?? 48 8D 8D";
@ -23,7 +24,7 @@ namespace XivCommon.Functions {
private readonly unsafe delegate* unmanaged<Utf8String*, int, IntPtr, void> _sanitiseString = null!;
internal Chat(SigScanner scanner) {
internal Chat(ISigScanner scanner) {
if (scanner.TryScanText(Signatures.SendChat, out var processChatBoxPtr, "chat sending")) {
this.ProcessChatBox = Marshal.GetDelegateForFunctionPointer<ProcessChatBoxDelegate>(processChatBoxPtr);
}
@ -153,5 +154,4 @@ namespace XivCommon.Functions {
Marshal.FreeHGlobal(this.textPtr);
}
}
}
}

View File

@ -1,22 +1,23 @@
using System;
using System.Runtime.InteropServices;
using Dalamud.Game;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Hooking;
using Dalamud.Plugin.Services;
namespace XivCommon.Functions {
/// <summary>
/// Class containing chat bubble events and functions
/// </summary>
public class ChatBubbles : IDisposable {
namespace XivCommon.Functions;
/// <summary>
/// Class containing chat bubble events and functions
/// </summary>
public class ChatBubbles : IDisposable {
private static class Signatures {
internal const string ChatBubbleOpen = "E8 ?? ?? ?? ?? C7 43 ?? ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? E8";
internal const string ChatBubbleUpdate = "48 85 D2 0F 84 ?? ?? ?? ?? 48 89 5C 24 ?? 57 48 83 EC 20 8B 41 0C";
}
private ObjectTable ObjectTable { get; }
private IObjectTable ObjectTable { get; }
private delegate void OpenChatBubbleDelegate(IntPtr manager, IntPtr @object, IntPtr text, byte a4);
@ -56,7 +57,7 @@ namespace XivCommon.Functions {
/// </summary>
public event OnUpdateChatBubbleDelegate? OnUpdateBubble;
internal ChatBubbles(ObjectTable objectTable, SigScanner scanner, bool hookEnabled) {
internal ChatBubbles(IObjectTable objectTable, ISigScanner scanner, IGameInteropProvider interop, bool hookEnabled) {
this.ObjectTable = objectTable;
if (!hookEnabled) {
@ -64,12 +65,12 @@ namespace XivCommon.Functions {
}
if (scanner.TryScanText(Signatures.ChatBubbleOpen, out var openPtr, "chat bubbles open")) {
this.OpenChatBubbleHook = Hook<OpenChatBubbleDelegate>.FromAddress(openPtr, this.OpenChatBubbleDetour);
this.OpenChatBubbleHook = interop.HookFromAddress<OpenChatBubbleDelegate>(openPtr, this.OpenChatBubbleDetour);
this.OpenChatBubbleHook.Enable();
}
if (scanner.TryScanText(Signatures.ChatBubbleUpdate, out var updatePtr, "chat bubbles update")) {
this.UpdateChatBubbleHook = Hook<UpdateChatBubbleDelegate>.FromAddress(updatePtr + 9, this.UpdateChatBubbleDetour);
this.UpdateChatBubbleHook = interop.HookFromAddress<UpdateChatBubbleDelegate>(updatePtr + 9, this.UpdateChatBubbleDetour);
this.UpdateChatBubbleHook.Enable();
}
}
@ -84,7 +85,7 @@ namespace XivCommon.Functions {
try {
this.OpenChatBubbleDetourInner(manager, @object, text, a4);
} catch (Exception ex) {
Logger.LogError(ex, "Exception in chat bubble detour");
Logger.Log.Error(ex, "Exception in chat bubble detour");
this.OpenChatBubbleHook!.Original(manager, @object, text, a4);
}
}
@ -100,7 +101,7 @@ namespace XivCommon.Functions {
try {
this.OnChatBubble?.Invoke(ref @object, ref text);
} catch (Exception ex) {
Logger.LogError(ex, "Exception in chat bubble event");
Logger.Log.Error(ex, "Exception in chat bubble event");
}
var newText = text.Encode().Terminate();
@ -116,7 +117,7 @@ namespace XivCommon.Functions {
try {
this.UpdateChatBubbleDetourInner(bubblePtr, @object);
} catch (Exception ex) {
Logger.LogError(ex, "Exception in update chat bubble detour");
Logger.Log.Error(ex, "Exception in update chat bubble detour");
this.UpdateChatBubbleHook!.Original(bubblePtr, @object);
}
}
@ -131,15 +132,15 @@ namespace XivCommon.Functions {
try {
this.OnUpdateBubble?.Invoke(ref @object);
} catch (Exception ex) {
Logger.LogError(ex, "Exception in chat bubble update event");
Logger.Log.Error(ex, "Exception in chat bubble update event");
}
this.UpdateChatBubbleHook!.Original(bubblePtr, @object.Address);
}
}
}
[StructLayout(LayoutKind.Explicit, Size = 0x80)]
internal unsafe struct ChatBubble {
[StructLayout(LayoutKind.Explicit, Size = 0x80)]
internal unsafe struct ChatBubble {
[FieldOffset(0x0)]
internal readonly uint Id;
@ -157,12 +158,11 @@ namespace XivCommon.Functions {
[FieldOffset(0x78)]
internal readonly ulong Unk_78; // check whats in memory here
}
}
internal enum ChatBubbleStatus : uint {
internal enum ChatBubbleStatus : uint {
GetData = 0,
On = 1,
Init = 2,
Off = 3,
}
}

View File

@ -5,11 +5,12 @@ using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using Lumina.Excel.GeneratedSheets;
using Framework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework;
namespace XivCommon.Functions {
/// <summary>
/// Duty Finder functions
/// </summary>
public class DutyFinder {
namespace XivCommon.Functions;
/// <summary>
/// Duty Finder functions
/// </summary>
public class DutyFinder {
private static class Signatures {
internal const string OpenRegularDuty = "48 89 6C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B F9 41 0F B6 E8";
internal const string OpenRoulette = "E9 ?? ?? ?? ?? 8B 93 ?? ?? ?? ?? 48 83 C4 20";
@ -22,7 +23,7 @@ namespace XivCommon.Functions {
private readonly OpenDutyDelegate? _openDuty;
private readonly OpenRouletteDelegate? _openRoulette;
internal DutyFinder(SigScanner scanner) {
internal DutyFinder(ISigScanner scanner) {
if (scanner.TryScanText(Signatures.OpenRegularDuty, out var openDutyPtr, "Duty Finder (open duty)")) {
this._openDuty = Marshal.GetDelegateForFunctionPointer<OpenDutyDelegate>(openDutyPtr);
}
@ -77,5 +78,4 @@ namespace XivCommon.Functions {
this._openRoulette(agent, roulette, 0);
}
}
}

View File

@ -4,11 +4,12 @@ using Dalamud.Game;
using Dalamud.Game.ClientState.Objects.Types;
using Framework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework;
namespace XivCommon.Functions {
/// <summary>
/// Class containing examine functions
/// </summary>
public class Examine {
namespace XivCommon.Functions;
/// <summary>
/// Class containing examine functions
/// </summary>
public class Examine {
private static class Signatures {
internal const string RequestCharacterInfo = "40 53 48 83 EC 40 48 8B D9 48 8B 49 10 48 8B 01 FF 90 ?? ?? ?? ?? BA";
}
@ -17,7 +18,7 @@ namespace XivCommon.Functions {
private RequestCharInfoDelegate? RequestCharacterInfo { get; }
internal Examine(SigScanner scanner) {
internal Examine(ISigScanner scanner) {
// got this by checking what accesses rciData below
if (scanner.TryScanText(Signatures.RequestCharacterInfo, out var rciPtr, "Examine")) {
this.RequestCharacterInfo = Marshal.GetDelegateForFunctionPointer<RequestCharInfoDelegate>(rciPtr);
@ -63,5 +64,4 @@ namespace XivCommon.Functions {
this.RequestCharacterInfo(rciData);
}
}
}

View File

@ -3,11 +3,12 @@ using System.Collections.Generic;
using FFXIVClientStructs.FFXIV.Client.System.Framework;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
namespace XivCommon.Functions.FriendList {
/// <summary>
/// The class containing friend list functionality
/// </summary>
public class FriendList {
namespace XivCommon.Functions.FriendList;
/// <summary>
/// The class containing friend list functionality
/// </summary>
public class FriendList {
// Updated: 5.58-HF1
private const int InfoOffset = 0x28;
private const int LengthOffset = 0x10;
@ -58,5 +59,4 @@ namespace XivCommon.Functions.FriendList {
internal FriendList() {
}
}
}

View File

@ -3,12 +3,13 @@ using System.Runtime.InteropServices;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Memory;
namespace XivCommon.Functions.FriendList {
/// <summary>
/// An entry in a player's friend list.
/// </summary>
[StructLayout(LayoutKind.Explicit, Size = Size)]
public unsafe struct FriendListEntry {
namespace XivCommon.Functions.FriendList;
/// <summary>
/// An entry in a player's friend list.
/// </summary>
[StructLayout(LayoutKind.Explicit, Size = Size)]
public unsafe struct FriendListEntry {
internal const int Size = 104;
/// <summary>
@ -68,5 +69,4 @@ namespace XivCommon.Functions.FriendList {
}
}
}
}
}

View File

@ -1,11 +1,12 @@
using System;
using Dalamud.Game;
namespace XivCommon.Functions.Housing {
/// <summary>
/// The class containing housing functionality
/// </summary>
public class Housing {
namespace XivCommon.Functions.Housing;
/// <summary>
/// The class containing housing functionality
/// </summary>
public class Housing {
private static class Signatures {
internal const string HousingPointer = "48 8B 05 ?? ?? ?? ?? 48 83 78 ?? ?? 74 16 48 8D 8F ?? ?? ?? ?? 66 89 5C 24 ?? 48 8D 54 24 ?? E8 ?? ?? ?? ?? 48 8B 7C 24";
}
@ -47,10 +48,9 @@ namespace XivCommon.Functions.Housing {
}
}
internal Housing(SigScanner scanner) {
internal Housing(ISigScanner scanner) {
if (scanner.TryGetStaticAddressFromSig(Signatures.HousingPointer, out var ptr)) {
this.HousingPointer = ptr;
}
}
}
}

View File

@ -1,8 +1,9 @@
namespace XivCommon.Functions.Housing {
/// <summary>
/// Information about a player's current location in a housing ward.
/// </summary>
public class HousingLocation {
namespace XivCommon.Functions.Housing;
/// <summary>
/// Information about a player's current location in a housing ward.
/// </summary>
public class HousingLocation {
/// <summary>
/// The housing ward that the player is in.
/// </summary>
@ -55,5 +56,4 @@
this.Ward = (ushort) (ward + 1);
}
}
}
}

View File

@ -1,12 +1,13 @@
using System.Runtime.InteropServices;
namespace XivCommon.Functions.Housing {
/// <summary>
/// Information about the player's current location in a housing ward as
/// kept by the game's internal structures.
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public readonly struct RawHousingLocation {
namespace XivCommon.Functions.Housing;
/// <summary>
/// Information about the player's current location in a housing ward as
/// kept by the game's internal structures.
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public readonly struct RawHousingLocation {
/// <summary>
/// The zero-indexed plot number that the player is in.
///
@ -37,5 +38,4 @@ namespace XivCommon.Functions.Housing {
/// A byte that is zero when the player is inside a plot.
/// </summary>
public readonly byte InsideIndicator; // aa -> ab
}
}

View File

@ -5,11 +5,12 @@ using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using Lumina.Excel.GeneratedSheets;
using Framework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework;
namespace XivCommon.Functions {
/// <summary>
/// Journal functions
/// </summary>
public class Journal {
namespace XivCommon.Functions;
/// <summary>
/// Journal functions
/// </summary>
public class Journal {
private static class Signatures {
internal const string OpenQuest = "E8 ?? ?? ?? ?? 48 8B 74 24 ?? 48 8B 7C 24 ?? 48 83 C4 30 5B C3 48 8B CB";
internal const string IsQuestCompleted = "E8 ?? ?? ?? ?? 41 88 84 2C";
@ -22,7 +23,7 @@ namespace XivCommon.Functions {
private readonly OpenQuestDelegate? _openQuest;
private readonly IsQuestCompletedDelegate? _isQuestCompleted;
internal Journal(SigScanner scanner) {
internal Journal(ISigScanner scanner) {
if (scanner.TryScanText(Signatures.OpenQuest, out var openQuestPtr, "Journal (open quest)")) {
this._openQuest = Marshal.GetDelegateForFunctionPointer<OpenQuestDelegate>(openQuestPtr);
}
@ -79,5 +80,4 @@ namespace XivCommon.Functions {
return this._isQuestCompleted((ushort) (questId & 0xFFFF)) != 0;
}
}
}

View File

@ -1,11 +1,12 @@
using System;
using Dalamud.Game.Text.SeStringHandling;
namespace XivCommon.Functions.NamePlates {
/// <summary>
/// Arguments for the name plate update event
/// </summary>
public class NamePlateUpdateEventArgs {
namespace XivCommon.Functions.NamePlates;
/// <summary>
/// Arguments for the name plate update event
/// </summary>
public class NamePlateUpdateEventArgs {
/// <summary>
/// The object ID associated with this name plate.
/// </summary>
@ -74,5 +75,4 @@ namespace XivCommon.Functions.NamePlates {
internal NamePlateUpdateEventArgs(uint objectId) {
this.ObjectId = objectId;
}
}
}

View File

@ -3,15 +3,17 @@ using System.Runtime.InteropServices;
using Dalamud.Game;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Hooking;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Graphics;
using FFXIVClientStructs.FFXIV.Client.UI;
using Framework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework;
namespace XivCommon.Functions.NamePlates {
/// <summary>
/// The class containing name plate functionality
/// </summary>
public class NamePlates : IDisposable {
namespace XivCommon.Functions.NamePlates;
/// <summary>
/// The class containing name plate functionality
/// </summary>
public class NamePlates : IDisposable {
private static class Signatures {
internal const string NamePlateUpdate = "48 8B C4 41 56 48 81 EC ?? ?? ?? ?? 48 89 58 F0";
}
@ -46,7 +48,7 @@ namespace XivCommon.Functions.NamePlates {
/// </summary>
public bool ForceRedraw { get; set; }
internal NamePlates(GameFunctions functions, SigScanner scanner, bool hookEnabled) {
internal NamePlates(GameFunctions functions, ISigScanner scanner, IGameInteropProvider interop, bool hookEnabled) {
this.Functions = functions;
if (!hookEnabled) {
@ -55,7 +57,7 @@ namespace XivCommon.Functions.NamePlates {
if (scanner.TryScanText(Signatures.NamePlateUpdate, out var updatePtr)) {
unsafe {
this._namePlateUpdateHook = Hook<NamePlateUpdateDelegate>.FromAddress(updatePtr, this.NamePlateUpdateDetour);
this._namePlateUpdateHook = interop.HookFromAddress<NamePlateUpdateDelegate>(updatePtr, this.NamePlateUpdateDetour);
}
this._namePlateUpdateHook.Enable();
@ -83,7 +85,7 @@ namespace XivCommon.Functions.NamePlates {
try {
this.NamePlateUpdateDetourInner(numberData, stringData);
} catch (Exception ex) {
Logger.LogError(ex, "Exception in NamePlateUpdateDetour");
Logger.Log.Error(ex, "Exception in NamePlateUpdateDetour");
}
return this._namePlateUpdateHook!.Original(addon, numberData, stringData);
@ -162,7 +164,7 @@ namespace XivCommon.Functions.NamePlates {
try {
this.OnUpdate?.Invoke(args);
} catch (Exception ex) {
Logger.LogError(ex, "Exception in name plate update event");
Logger.Log.Error(ex, "Exception in name plate update event");
}
void Replace(byte[] bytes, int i, bool free = true) {
@ -223,5 +225,4 @@ namespace XivCommon.Functions.NamePlates {
}
}
}
}
}

View File

@ -1,9 +1,10 @@
using System.Runtime.InteropServices;
using FFXIVClientStructs.FFXIV.Client.Graphics;
namespace XivCommon.Functions.NamePlates {
[StructLayout(LayoutKind.Explicit, Size = 0x28)]
internal unsafe struct NumberArrayData {
namespace XivCommon.Functions.NamePlates;
[StructLayout(LayoutKind.Explicit, Size = 0x28)]
internal unsafe struct NumberArrayData {
[FieldOffset(0x0)]
public AtkArrayData AtkArrayData;
@ -22,10 +23,10 @@ namespace XivCommon.Functions.NamePlates {
this.IntArray[index] = value;
this.AtkArrayData.HasModifiedData = 1;
}
}
}
[StructLayout(LayoutKind.Explicit, Size = 0x20)]
internal unsafe struct AtkArrayData {
[StructLayout(LayoutKind.Explicit, Size = 0x20)]
internal unsafe struct AtkArrayData {
[FieldOffset(0x0)]
public void* vtbl;
@ -43,10 +44,10 @@ namespace XivCommon.Functions.NamePlates {
[FieldOffset(0x1F)]
public byte Unk1F; // initialized to -1
}
}
[StructLayout(LayoutKind.Explicit, Size = 0x30)]
internal unsafe struct StringArrayData {
[StructLayout(LayoutKind.Explicit, Size = 0x30)]
internal unsafe struct StringArrayData {
[FieldOffset(0x0)]
public AtkArrayData AtkArrayData;
@ -55,12 +56,12 @@ namespace XivCommon.Functions.NamePlates {
[FieldOffset(0x28)]
public byte* UnkString; // char *
}
}
/// <summary>
/// The various different name plate types
/// </summary>
public enum PlateType {
/// <summary>
/// The various different name plate types
/// </summary>
public enum PlateType {
/// <summary>
/// A normal player name plate
/// </summary>
@ -90,12 +91,12 @@ namespace XivCommon.Functions.NamePlates {
/// A name plate where the title always appears below the name and the FC tag is removed
/// </summary>
LowTitleNoFc = 8,
}
}
/// <summary>
/// A colour, represented in the RGBA format.
/// </summary>
public class RgbaColour {
/// <summary>
/// A colour, represented in the RGBA format.
/// </summary>
public class RgbaColour {
/// <summary>
/// The red component of the colour.
/// </summary>
@ -172,5 +173,4 @@ namespace XivCommon.Functions.NamePlates {
A = rgba.A,
};
}
}
}

View File

@ -2,18 +2,19 @@
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Dalamud.Game;
using Dalamud.Game.Gui.PartyFinder;
using Dalamud.Game.Gui.PartyFinder.Types;
using Dalamud.Hooking;
using Dalamud.Plugin.Services;
namespace XivCommon.Functions {
/// <summary>
/// A class containing Party Finder functionality
/// </summary>
public class PartyFinder : IDisposable {
namespace XivCommon.Functions;
/// <summary>
/// A class containing Party Finder functionality
/// </summary>
public class PartyFinder : IDisposable {
private static class Signatures {
internal const string RequestListings = "48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 40 0F 10 81";
internal const string JoinCrossParty = "E8 ?? ?? ?? ?? 0F B7 47 28";
internal const string JoinCrossParty = "E8 ?? ?? ?? ?? 41 0F B7 07 49 8B CC";
}
private delegate byte RequestPartyFinderListingsDelegate(IntPtr agent, byte categoryIdx);
@ -39,7 +40,7 @@ namespace XivCommon.Functions {
/// </summary>
public event JoinPfEventDelegate? JoinParty;
private PartyFinderGui PartyFinderGui { get; }
private IPartyFinderGui PartyFinderGui { get; }
private bool JoinsEnabled { get; }
private bool ListingsEnabled { get; }
private IntPtr PartyFinderAgent { get; set; } = IntPtr.Zero;
@ -59,7 +60,7 @@ namespace XivCommon.Functions {
/// </summary>
public IReadOnlyDictionary<uint, PartyFinderListing> CurrentListings => this.Listings;
internal PartyFinder(SigScanner scanner, PartyFinderGui partyFinderGui, Hooks hooks) {
internal PartyFinder(ISigScanner scanner, IPartyFinderGui partyFinderGui, IGameInteropProvider interop, Hooks hooks) {
this.PartyFinderGui = partyFinderGui;
this.ListingsEnabled = hooks.HasFlag(Hooks.PartyFinderListings);
@ -73,13 +74,13 @@ namespace XivCommon.Functions {
this.RequestPartyFinderListings = Marshal.GetDelegateForFunctionPointer<RequestPartyFinderListingsDelegate>(requestPfPtr);
if (this.ListingsEnabled) {
this.RequestPfListingsHook = Hook<RequestPartyFinderListingsDelegate>.FromAddress(requestPfPtr, this.OnRequestPartyFinderListings);
this.RequestPfListingsHook = interop.HookFromAddress<RequestPartyFinderListingsDelegate>(requestPfPtr, this.OnRequestPartyFinderListings);
this.RequestPfListingsHook.Enable();
}
}
if (this.JoinsEnabled && scanner.TryScanText(Signatures.JoinCrossParty, out var joinPtr, "Party Finder joins")) {
this.JoinPfHook = Hook<JoinPfDelegate>.FromAddress(joinPtr, this.JoinPfDetour);
this.JoinPfHook = interop.HookFromAddress<JoinPfDelegate>(joinPtr, this.JoinPfDetour);
this.JoinPfHook.Enable();
}
}
@ -122,7 +123,7 @@ namespace XivCommon.Functions {
this.JoinParty?.Invoke(listing);
}
} catch (Exception ex) {
Logger.LogError(ex, "Exception in PF join detour");
Logger.Log.Error(ex, "Exception in PF join detour");
}
return ret;
@ -156,9 +157,9 @@ namespace XivCommon.Functions {
var categoryIdx = Marshal.ReadByte(this.PartyFinderAgent + categoryOffset);
this.RequestPartyFinderListings(this.PartyFinderAgent, categoryIdx);
}
}
}
internal enum JoinType : byte {
internal enum JoinType : byte {
/// <summary>
/// Join via invite or party conversion.
/// </summary>
@ -177,5 +178,4 @@ namespace XivCommon.Functions {
LeaveDuty = 3,
Unknown4 = 4,
}
}

View File

@ -3,12 +3,14 @@ using System.Runtime.InteropServices;
using Dalamud.Game;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Hooking;
using Dalamud.Plugin.Services;
namespace XivCommon.Functions {
/// <summary>
/// Class containing Talk events
/// </summary>
public class Talk : IDisposable {
namespace XivCommon.Functions;
/// <summary>
/// Class containing Talk events
/// </summary>
public class Talk : IDisposable {
private static class Signatures {
internal const string SetAtkValue = "E8 ?? ?? ?? ?? 41 03 ED";
internal const string ShowMessageBox = "4C 8B DC 55 57 41 55 49 8D 6B 98";
@ -42,7 +44,7 @@ namespace XivCommon.Functions {
/// </summary>
public event TalkEventDelegate? OnTalk;
internal Talk(SigScanner scanner, bool hooksEnabled) {
internal Talk(ISigScanner scanner, IGameInteropProvider interop, bool hooksEnabled) {
if (scanner.TryScanText(Signatures.SetAtkValue, out var setAtkPtr, "Talk - set atk value")) {
this.SetAtkValueString = Marshal.GetDelegateForFunctionPointer<SetAtkValueStringDelegate>(setAtkPtr);
} else {
@ -54,7 +56,7 @@ namespace XivCommon.Functions {
}
if (scanner.TryScanText(Signatures.ShowMessageBox, out var showMessageBoxPtr, "Talk")) {
this.AddonTalkV45Hook = Hook<AddonTalkV45Delegate>.FromAddress(showMessageBoxPtr, this.AddonTalkV45Detour);
this.AddonTalkV45Hook = interop.HookFromAddress<AddonTalkV45Delegate>(showMessageBoxPtr, this.AddonTalkV45Detour);
this.AddonTalkV45Hook.Enable();
}
}
@ -72,7 +74,7 @@ namespace XivCommon.Functions {
try {
this.AddonTalkV45DetourInner(data);
} catch (Exception ex) {
Logger.LogError(ex, "Exception in Talk detour");
Logger.Log.Error(ex, "Exception in Talk detour");
}
Return:
@ -90,7 +92,7 @@ namespace XivCommon.Functions {
try {
this.OnTalk?.Invoke(ref name, ref text, ref style);
} catch (Exception ex) {
Logger.LogError(ex, "Exception in Talk event");
Logger.Log.Error(ex, "Exception in Talk event");
}
var newName = name.Encode().Terminate();
@ -105,12 +107,12 @@ namespace XivCommon.Functions {
}
}
}
}
}
/// <summary>
/// Talk window styles.
/// </summary>
public enum TalkStyle : byte {
/// <summary>
/// Talk window styles.
/// </summary>
public enum TalkStyle : byte {
/// <summary>
/// The normal style with a white background.
/// </summary>
@ -155,5 +157,4 @@ namespace XivCommon.Functions {
/// The system message style with a purple background.
/// </summary>
PurpleSystem = 9,
}
}

View File

@ -1,10 +1,11 @@
using Dalamud.Game.Text.SeStringHandling;
namespace XivCommon.Functions.Tooltips {
/// <summary>
/// The class allowing for action tooltip manipulation
/// </summary>
public unsafe class ActionTooltip : BaseTooltip {
namespace XivCommon.Functions.Tooltips;
/// <summary>
/// The class allowing for action tooltip manipulation
/// </summary>
public unsafe class ActionTooltip : BaseTooltip {
internal ActionTooltip(Tooltips.StringArrayDataSetStringDelegate sadSetString, byte*** stringArrayData, int** numberArrayData) : base(sadSetString, stringArrayData, numberArrayData) {
}
@ -24,5 +25,4 @@ namespace XivCommon.Functions.Tooltips {
get => (ActionTooltipFields) (**(this.NumberArrayData + 4));
set => **(this.NumberArrayData + 4) = (int) value;
}
}
}

View File

@ -1,10 +1,11 @@
using System;
namespace XivCommon.Functions.Tooltips {
/// <summary>
/// An enum containing the strings used in action tooltips.
/// </summary>
public enum ActionTooltipString {
namespace XivCommon.Functions.Tooltips;
/// <summary>
/// An enum containing the strings used in action tooltips.
/// </summary>
public enum ActionTooltipString {
#pragma warning disable 1591
Name = 0,
Type = 1,
@ -22,13 +23,13 @@ namespace XivCommon.Functions.Tooltips {
Acquired = 14,
Affinity = 15,
#pragma warning restore 1591
}
}
/// <summary>
/// An enum containing the fields that can be displayed in action tooltips.
/// </summary>
[Flags]
public enum ActionTooltipFields {
/// <summary>
/// An enum containing the fields that can be displayed in action tooltips.
/// </summary>
[Flags]
public enum ActionTooltipFields {
#pragma warning disable 1591
Range = 1 << 0,
Radius = 1 << 1,
@ -40,5 +41,4 @@ namespace XivCommon.Functions.Tooltips {
Affinity = 1 << 7,
Unknown8 = 1 << 8,
#pragma warning restore 1591
}
}

View File

@ -1,11 +1,12 @@
using System;
using Dalamud.Game.Text.SeStringHandling;
namespace XivCommon.Functions.Tooltips {
/// <summary>
/// The base class for tooltips
/// </summary>
public abstract unsafe class BaseTooltip {
namespace XivCommon.Functions.Tooltips;
/// <summary>
/// The base class for tooltips
/// </summary>
public abstract unsafe class BaseTooltip {
private Tooltips.StringArrayDataSetStringDelegate SadSetString { get; }
/// <summary>
@ -46,5 +47,4 @@ namespace XivCommon.Functions.Tooltips {
}
}
}
}
}

View File

@ -1,10 +1,11 @@
using Dalamud.Game.Text.SeStringHandling;
namespace XivCommon.Functions.Tooltips {
/// <summary>
/// The class allowing for item tooltip manipulation
/// </summary>
public unsafe class ItemTooltip : BaseTooltip {
namespace XivCommon.Functions.Tooltips;
/// <summary>
/// The class allowing for item tooltip manipulation
/// </summary>
public unsafe class ItemTooltip : BaseTooltip {
internal ItemTooltip(Tooltips.StringArrayDataSetStringDelegate sadSetString, byte*** stringArrayData, int** numberArrayData) : base(sadSetString, stringArrayData, numberArrayData) {
}
@ -24,5 +25,4 @@ namespace XivCommon.Functions.Tooltips {
get => (ItemTooltipFields) (*(*(this.NumberArrayData + 4) + 4));
set => *(*(this.NumberArrayData + 4) + 4) = (int) value;
}
}
}

View File

@ -1,10 +1,11 @@
using System;
namespace XivCommon.Functions.Tooltips {
/// <summary>
/// An enum containing the strings used in item tooltips.
/// </summary>
public enum ItemTooltipString {
namespace XivCommon.Functions.Tooltips;
/// <summary>
/// An enum containing the strings used in item tooltips.
/// </summary>
public enum ItemTooltipString {
#pragma warning disable 1591
Name = 0,
GlamourName = 1,
@ -54,13 +55,13 @@ namespace XivCommon.Functions.Tooltips {
ShopSellingPrice = 63,
ControllerControls = 64,
#pragma warning restore 1591
}
}
/// <summary>
/// An enum containing the fields that can be displayed in item tooltips.
/// </summary>
[Flags]
public enum ItemTooltipFields {
/// <summary>
/// An enum containing the fields that can be displayed in item tooltips.
/// </summary>
[Flags]
public enum ItemTooltipFields {
#pragma warning disable 1591
Crafter = 1 << 0,
Description = 1 << 1,
@ -90,5 +91,4 @@ namespace XivCommon.Functions.Tooltips {
GlamourIndicator = 1 << 16,
Unknown19 = 1 << 19,
#pragma warning restore 1591
}
}

View File

@ -3,12 +3,14 @@ using System.Runtime.InteropServices;
using Dalamud.Game;
using Dalamud.Game.Gui;
using Dalamud.Hooking;
using Dalamud.Plugin.Services;
namespace XivCommon.Functions.Tooltips {
/// <summary>
/// The class containing tooltip functionality
/// </summary>
public class Tooltips : IDisposable {
namespace XivCommon.Functions.Tooltips;
/// <summary>
/// The class containing tooltip functionality
/// </summary>
public class Tooltips : IDisposable {
private static class Signatures {
internal const string AgentItemDetailUpdateTooltip = "E8 ?? ?? ?? ?? 48 8B 5C 24 ?? 48 89 AE ?? ?? ?? ?? 48 89 AE";
internal const string AgentActionDetailUpdateTooltip = "E8 ?? ?? ?? ?? EB 68 FF 50 40";
@ -59,11 +61,11 @@ namespace XivCommon.Functions.Tooltips {
/// </summary>
public event ActionTooltipEventDelegate? OnActionTooltip;
private GameGui GameGui { get; }
private IGameGui GameGui { get; }
private ItemTooltip? ItemTooltip { get; set; }
private ActionTooltip? ActionTooltip { get; set; }
internal Tooltips(SigScanner scanner, GameGui gui, bool enabled) {
internal Tooltips(ISigScanner scanner, IGameGui gui, IGameInteropProvider interop, bool enabled) {
this.GameGui = gui;
if (scanner.TryScanText(Signatures.SadSetString, out var setStringPtr, "Tooltips - StringArrayData::SetString")) {
@ -78,7 +80,7 @@ namespace XivCommon.Functions.Tooltips {
if (scanner.TryScanText(Signatures.AgentItemDetailUpdateTooltip, out var updateItemPtr, "Tooltips - Items")) {
unsafe {
this.ItemUpdateTooltipHook = Hook<ItemUpdateTooltipDelegate>.FromAddress(updateItemPtr, this.ItemUpdateTooltipDetour);
this.ItemUpdateTooltipHook = interop.HookFromAddress<ItemUpdateTooltipDelegate>(updateItemPtr, this.ItemUpdateTooltipDetour);
}
this.ItemUpdateTooltipHook.Enable();
@ -86,7 +88,7 @@ namespace XivCommon.Functions.Tooltips {
if (scanner.TryScanText(Signatures.AgentActionDetailUpdateTooltip, out var updateActionPtr, "Tooltips - Actions")) {
unsafe {
this.ActionGenerateTooltipHook = Hook<ActionUpdateTooltipDelegate>.FromAddress(updateActionPtr, this.ActionUpdateTooltipDetour);
this.ActionGenerateTooltipHook = interop.HookFromAddress<ActionUpdateTooltipDelegate>(updateActionPtr, this.ActionUpdateTooltipDetour);
}
this.ActionGenerateTooltipHook.Enable();
@ -106,7 +108,7 @@ namespace XivCommon.Functions.Tooltips {
try {
this.ItemUpdateTooltipDetourInner(numberArrayData, stringArrayData);
} catch (Exception ex) {
Logger.LogError(ex, "Exception in item tooltip detour");
Logger.Log.Error(ex, "Exception in item tooltip detour");
}
}
@ -119,7 +121,7 @@ namespace XivCommon.Functions.Tooltips {
try {
this.OnItemTooltip?.Invoke(this.ItemTooltip, this.GameGui.HoveredItem);
} catch (Exception ex) {
Logger.LogError(ex, "Exception in OnItemTooltip event");
Logger.Log.Error(ex, "Exception in OnItemTooltip event");
}
}
@ -134,7 +136,7 @@ namespace XivCommon.Functions.Tooltips {
try {
this.ActionUpdateTooltipDetourInner(numberArrayData, stringArrayData);
} catch (Exception ex) {
Logger.LogError(ex, "Exception in action tooltip detour");
Logger.Log.Error(ex, "Exception in action tooltip detour");
}
}
@ -144,8 +146,7 @@ namespace XivCommon.Functions.Tooltips {
try {
this.OnActionTooltip?.Invoke(this.ActionTooltip, this.GameGui.HoveredAction);
} catch (Exception ex) {
Logger.LogError(ex, "Exception in OnActionTooltip event");
}
Logger.Log.Error(ex, "Exception in OnActionTooltip event");
}
}
}

View File

@ -2,8 +2,9 @@
using System.Runtime.InteropServices;
using Dalamud.Game;
namespace XivCommon.Functions {
internal class UiAlloc {
namespace XivCommon.Functions;
internal class UiAlloc {
private static class Signatures {
internal const string GameAlloc = "E8 ?? ?? ?? ?? 49 83 CC FF 4C 8B F0";
internal const string GameFree = "E8 ?? ?? ?? ?? 4C 89 7B 60";
@ -22,7 +23,7 @@ namespace XivCommon.Functions {
private readonly GetGameAllocatorDelegate? _getGameAllocator;
internal UiAlloc(SigScanner scanner) {
internal UiAlloc(ISigScanner scanner) {
if (scanner.TryScanText(Signatures.GameAlloc, out var gameAllocPtr, "UiAlloc (GameAlloc)")) {
this._gameAlloc = Marshal.GetDelegateForFunctionPointer<GameAllocDelegate>(gameAllocPtr);
} else {
@ -55,5 +56,4 @@ namespace XivCommon.Functions {
this._gameFree(ptr);
}
}
}

View File

@ -1,8 +1,6 @@
using System;
using Dalamud.Game;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.Gui;
using Dalamud.Game.Gui.PartyFinder;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using FFXIVClientStructs.FFXIV.Component.GUI;
using XivCommon.Functions;
@ -12,14 +10,15 @@ 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 GameGui GameGui { get; }
namespace XivCommon;
private Dalamud.Game.Framework Framework { get; }
/// <summary>
/// A class containing game functions
/// </summary>
public class GameFunctions : IDisposable {
private IGameGui GameGui { get; }
private IFramework Framework { get; }
internal UiAlloc UiAlloc { get; }
@ -84,22 +83,25 @@ namespace XivCommon {
public Housing Housing { get; }
internal GameFunctions(Hooks hooks) {
this.Framework = Util.GetService<Dalamud.Game.Framework>();
this.GameGui = Util.GetService<GameGui>();
Logger.Log = Util.GetService<IPluginLog>();
var objectTable = Util.GetService<ObjectTable>();
var partyFinderGui = Util.GetService<PartyFinderGui>();
var scanner = Util.GetService<SigScanner>();
this.Framework = Util.GetService<IFramework>();
this.GameGui = Util.GetService<IGameGui>();
var interop = Util.GetService<IGameInteropProvider>();
var objectTable = Util.GetService<IObjectTable>();
var partyFinderGui = Util.GetService<IPartyFinderGui>();
var scanner = Util.GetService<ISigScanner>();
this.UiAlloc = new UiAlloc(scanner);
this.Chat = new Chat(scanner);
this.PartyFinder = new PartyFinder(scanner, partyFinderGui, hooks);
this.BattleTalk = new BattleTalk(hooks.HasFlag(Hooks.BattleTalk));
this.PartyFinder = new PartyFinder(scanner, partyFinderGui, interop, hooks);
this.BattleTalk = new BattleTalk(interop, hooks.HasFlag(Hooks.BattleTalk));
this.Examine = new Examine(scanner);
this.Talk = new Talk(scanner, hooks.HasFlag(Hooks.Talk));
this.ChatBubbles = new ChatBubbles(objectTable, scanner, hooks.HasFlag(Hooks.ChatBubbles));
this.Tooltips = new Tooltips(scanner, this.GameGui, hooks.HasFlag(Hooks.Tooltips));
this.NamePlates = new NamePlates(this, scanner, hooks.HasFlag(Hooks.NamePlates));
this.Talk = new Talk(scanner, interop, hooks.HasFlag(Hooks.Talk));
this.ChatBubbles = new ChatBubbles(objectTable, scanner, interop, hooks.HasFlag(Hooks.ChatBubbles));
this.Tooltips = new Tooltips(scanner, this.GameGui, interop, hooks.HasFlag(Hooks.Tooltips));
this.NamePlates = new NamePlates(this, scanner, interop, hooks.HasFlag(Hooks.NamePlates));
this.DutyFinder = new DutyFinder(scanner);
this.Journal = new Journal(scanner);
this.FriendList = new FriendList();
@ -122,7 +124,7 @@ namespace XivCommon {
/// <returns>pointer to struct</returns>
[Obsolete("Use Framework.Instance()")]
public unsafe Framework* GetFramework() {
return (Framework*) this.Framework.Address.BaseAddress;
return FFXIVClientStructs.FFXIV.Client.System.Framework.Framework.Instance();
}
/// <summary>
@ -172,5 +174,4 @@ namespace XivCommon {
public unsafe IntPtr GetAtkStageSingleton() {
return (IntPtr) AtkStage.GetSingleton();
}
}
}

View File

@ -1,11 +1,12 @@
using System;
namespace XivCommon {
/// <summary>
/// Flags for which hooks to use
/// </summary>
[Flags]
public enum Hooks {
namespace XivCommon;
/// <summary>
/// Flags for which hooks to use
/// </summary>
[Flags]
public enum Hooks {
/// <summary>
/// No hook.
///
@ -66,9 +67,8 @@ namespace XivCommon {
/// This hook is used in order to enable name plate functions.
/// </summary>
NamePlates = 1 << 7,
}
internal static class HooksExt {
internal const Hooks DefaultHooks = Hooks.None;
}
}
internal static class HooksExt {
internal const Hooks DefaultHooks = Hooks.None;
}

27
XivCommon/Logger.cs Executable file → Normal file
View File

@ -1,26 +1,7 @@
using System;
using Dalamud.Logging;
using Dalamud.Plugin.Services;
namespace XivCommon {
internal static class Logger {
private static string Format(string msg) {
return $"[XIVCommon] {msg}";
}
namespace XivCommon;
internal static void Log(string msg) {
PluginLog.Log(Format(msg));
}
internal static void LogWarning(string msg) {
PluginLog.LogWarning(Format(msg));
}
internal static void LogError(string msg) {
PluginLog.LogError(Format(msg));
}
internal static void LogError(Exception ex, string msg) {
PluginLog.LogError(ex, Format(msg));
}
}
internal static class Logger {
internal static IPluginLog Log { get; set; } = null!;
}

View File

@ -2,8 +2,9 @@
using System.Collections.Generic;
using Dalamud.Game;
namespace XivCommon {
internal static class SigScannerExt {
namespace XivCommon;
internal static class SigScannerExt {
/// <summary>
/// Scan for a signature in memory.
/// </summary>
@ -12,7 +13,7 @@ namespace XivCommon {
/// <param name="result">pointer where signature was found or <see cref="IntPtr.Zero"/> if not found</param>
/// <param name="name">name of this signature - if specified, a warning will be printed if the signature could not be found</param>
/// <returns>true if signature was found</returns>
internal static bool TryScanText(this SigScanner scanner, string sig, out IntPtr result, string? name = null) {
internal static bool TryScanText(this ISigScanner scanner, string sig, out IntPtr result, string? name = null) {
result = IntPtr.Zero;
try {
result = scanner.ScanText(sig);
@ -25,5 +26,4 @@ namespace XivCommon {
return false;
}
}
}
}

View File

@ -4,8 +4,9 @@ using System.Reflection;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Plugin;
namespace XivCommon {
internal static class Util {
namespace XivCommon;
internal static class Util {
internal static byte[] Terminate(this byte[] array) {
var terminated = new byte[array.Length + 1];
Array.Copy(array, terminated, array.Length);
@ -36,7 +37,7 @@ namespace XivCommon {
}
internal static void PrintMissingSig(string name) {
Logger.LogWarning($"Could not find signature for {name}. This functionality will be disabled.");
Logger.Log.Warning($"Could not find signature for {name}. This functionality will be disabled.");
}
internal static T GetService<T>() {
@ -59,5 +60,4 @@ namespace XivCommon {
return start;
}
}
}

View File

@ -5,7 +5,7 @@
<LangVersion>latest</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Nullable>enable</Nullable>
<Version>7.0.2</Version>
<Version>8.0.0</Version>
<DebugType>full</DebugType>
</PropertyGroup>
@ -14,7 +14,7 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Title>XivCommon</Title>
<Authors>ascclemens</Authors>
<RepositoryUrl>https://git.annaclemens.io/ascclemens/XivCommon</RepositoryUrl>
<RepositoryUrl>https://git.anna.lgbt/anna/XivCommon</RepositoryUrl>
<Description>A set of common functions, hooks, and events not included in Dalamud.</Description>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>

View File

@ -1,10 +1,11 @@
using System;
namespace XivCommon {
/// <summary>
/// A base class for accessing XivCommon functionality.
/// </summary>
public class XivCommonBase : IDisposable {
namespace XivCommon;
/// <summary>
/// A base class for accessing XivCommon functionality.
/// </summary>
public class XivCommonBase : IDisposable {
/// <summary>
/// Game functions and events
/// </summary>
@ -27,5 +28,4 @@ namespace XivCommon {
public void Dispose() {
this.Functions.Dispose();
}
}
}