feat: add friend list
This commit is contained in:
parent
30d370c63b
commit
ddccc18ae8
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace XivCommon.Functions.FriendList {
|
||||
/// <summary>
|
||||
/// The class containing friend list functionality
|
||||
/// </summary>
|
||||
public class FriendList {
|
||||
// Updated: 5.58-HF1
|
||||
private const uint FriendListAgentId = 54;
|
||||
private const int InfoOffset = 0x28;
|
||||
private const int LengthOffset = 0x10;
|
||||
private const int ListOffset = 0x98;
|
||||
|
||||
private GameFunctions Functions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// A live list of the currently-logged-in player's friends.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The list is empty if not logged in.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public IList<FriendListEntry> List {
|
||||
get {
|
||||
var friendListAgent = this.Functions.GetAgentByInternalId(FriendListAgentId);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal FriendList(GameFunctions functions) {
|
||||
this.Functions = functions;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
using System;
|
||||
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 {
|
||||
internal const int Size = 96;
|
||||
|
||||
/// <summary>
|
||||
/// The content ID of the friend.
|
||||
/// </summary>
|
||||
[FieldOffset(0x00)]
|
||||
public readonly ulong ContentId;
|
||||
|
||||
/// <summary>
|
||||
/// The home world of the friend.
|
||||
/// </summary>
|
||||
[FieldOffset(0x16)]
|
||||
public readonly ushort HomeWorld;
|
||||
|
||||
/// <summary>
|
||||
/// The current world of the friend.
|
||||
/// </summary>
|
||||
[FieldOffset(0x18)]
|
||||
public readonly ushort CurrentWorld;
|
||||
|
||||
/// <summary>
|
||||
/// The job the friend is currently on.
|
||||
/// </summary>
|
||||
[FieldOffset(0x21)]
|
||||
public readonly byte Job;
|
||||
|
||||
/// <summary>
|
||||
/// The friend's raw SeString name. See <see cref="Name"/>.
|
||||
/// </summary>
|
||||
[FieldOffset(0x22)]
|
||||
public fixed byte RawName[32];
|
||||
|
||||
/// <summary>
|
||||
/// The friend's raw SeString free company tag. See <see cref="FreeCompany"/>.
|
||||
/// </summary>
|
||||
[FieldOffset(0x42)]
|
||||
public fixed byte RawFreeCompany[5];
|
||||
|
||||
/// <summary>
|
||||
/// The friend's name.
|
||||
/// </summary>
|
||||
public SeString Name {
|
||||
get {
|
||||
fixed (byte* ptr = this.RawName) {
|
||||
return MemoryHelper.ReadSeStringNullTerminated((IntPtr) ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The friend's free company tag.
|
||||
/// </summary>
|
||||
public SeString FreeCompany {
|
||||
get {
|
||||
fixed (byte* ptr = this.RawFreeCompany) {
|
||||
return MemoryHelper.ReadSeStringNullTerminated((IntPtr) ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ using Dalamud.Game.Gui;
|
|||
using Dalamud.Game.Gui.PartyFinder;
|
||||
using XivCommon.Functions;
|
||||
using XivCommon.Functions.ContextMenu;
|
||||
using XivCommon.Functions.FriendList;
|
||||
using XivCommon.Functions.NamePlates;
|
||||
using XivCommon.Functions.Tooltips;
|
||||
|
||||
|
@ -87,6 +88,11 @@ namespace XivCommon {
|
|||
/// </summary>
|
||||
public DutyFinder DutyFinder { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Friend list functions
|
||||
/// </summary>
|
||||
public FriendList FriendList { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Journal functions
|
||||
/// </summary>
|
||||
|
@ -112,6 +118,7 @@ namespace XivCommon {
|
|||
this.NamePlates = new NamePlates(this, scanner, hooks.HasFlag(Hooks.NamePlates));
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue