Add PartyList and PartyMember for ClientState use.

This commit is contained in:
attickdoor 2020-04-15 17:55:48 -04:00
parent 1cf6129085
commit 79960fa993
5 changed files with 179 additions and 1 deletions

View file

@ -0,0 +1,34 @@
using Dalamud.Game.ClientState.Structs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Dalamud.Game.ClientState.Actors.Types
{
public class PartyMember
{
public string CharacterName;
public long Unknown;
public Actor Actor;
public ObjectKind ObjectKind;
public PartyMember(ActorTable table, Structs.PartyMember rawData)
{
CharacterName = Marshal.PtrToStringAnsi(rawData.namePtr);
Unknown = rawData.unknown;
Actor = null;
for (var i = 0; i < table.Length; i++)
{
if (table[i].ActorId == rawData.actorId)
{
Actor = table[i];
break;
}
}
ObjectKind = rawData.objectKind;
}
}
}

View file

@ -80,6 +80,11 @@ namespace Dalamud.Game.ClientState
/// </summary>
public JobGauges JobGauges;
/// <summary>
/// The class facilitating party list data access
/// </summary>
public PartyList PartyList;
/// <summary>
/// Provides access to the keypress state of keyboard keys in game.
/// </summary>
@ -101,6 +106,8 @@ namespace Dalamud.Game.ClientState
this.Actors = new ActorTable(dalamud, Address);
this.PartyList = new PartyList(dalamud, Address);
this.JobGauges = new JobGauges(Address);
this.KeyState = new KeyState(Address, scanner.Module.BaseAddress);
@ -116,11 +123,13 @@ namespace Dalamud.Game.ClientState
public void Enable() {
this.Actors.Enable();
this.PartyList.Enable();
this.setupTerritoryTypeHook.Enable();
}
public void Dispose() {
this.Actors.Dispose();
this.PartyList.Dispose();
this.setupTerritoryTypeHook.Dispose();
}

View file

@ -13,7 +13,8 @@ namespace Dalamud.Game.ClientState
// Functions
public IntPtr SetupTerritoryType { get; private set; }
public IntPtr SomeActorTableAccess { get; private set; }
public IntPtr PartyListUpdate { get; private set; }
protected override void Setup64Bit(SigScanner sig) {
ViewportActorTable = sig.GetStaticAddressFromSig("48 8D 0D ?? ?? ?? ?? 85 ED", 0) + 0x148;
SomeActorTableAccess = sig.ScanText("E8 ?? ?? ?? ?? 48 8D 55 A0 48 8D 8E ?? ?? ?? ??");
@ -25,6 +26,8 @@ namespace Dalamud.Game.ClientState
// This resolves to a fixed offset only, without the base address added in, so GetStaticAddressFromSig() can't be used
KeyboardState = sig.ScanText("48 8D 0C 85 ?? ?? ?? ?? 8B 04 31 85 C2 0F 85") + 0x4;
PartyListUpdate = sig.ScanText("E8 ?? ?? ?? ?? 49 8B D4 4C 8D 87 ?? ?? ?? ??");
}
}
}

View file

@ -0,0 +1,113 @@
using Dalamud.Game.ClientState.Actors.Types;
using Dalamud.Hooking;
using Dalamud.Plugin;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Dalamud.Game.ClientState
{
public class PartyList : ICollection, IDisposable
{
private ClientStateAddressResolver Address { get; }
private Dalamud dalamud;
private delegate long PartyListUpdateDelegate(IntPtr structBegin, long param2, char param3);
private Hook<PartyListUpdateDelegate> partyListUpdateHook;
private IntPtr partyListBegin;
private bool isReady = false;
public PartyList(Dalamud dalamud, ClientStateAddressResolver addressResolver)
{
Address = addressResolver;
this.dalamud = dalamud;
partyListUpdateHook = new Hook<PartyListUpdateDelegate>(Address.PartyListUpdate, new PartyListUpdateDelegate(PartyListUpdateDetour), this);
}
public void Enable()
{
partyListUpdateHook.Enable();
}
public void Dispose()
{
if (!this.isReady)
partyListUpdateHook.Dispose();
isReady = false;
}
private long PartyListUpdateDetour(IntPtr structBegin, long param2, char param3)
{
var result = partyListUpdateHook.Original(structBegin, param2, param3);
partyListBegin = structBegin + 0xB48;
partyListUpdateHook.Dispose();
isReady = true;
return result;
}
public PartyMember this[int index]
{
get
{
if (!this.isReady)
return null;
if (index >= Length)
return null;
var tblIndex = partyListBegin + index * 24;
var memberStruct = Marshal.PtrToStructure<Structs.PartyMember>(tblIndex);
return new PartyMember(dalamud.ClientState.Actors, memberStruct);
}
}
public void CopyTo(Array array, int index)
{
for (var i = 0; i < Length; i++)
{
array.SetValue(this[i], index);
index++;
}
}
private class PartyListEnumerator : IEnumerator
{
private readonly PartyList party;
private int currentIndex;
public PartyListEnumerator(PartyList list)
{
party = list;
}
public object Current => party[currentIndex];
public bool MoveNext()
{
currentIndex++;
return currentIndex != party.Length;
}
public void Reset()
{
currentIndex = 0;
}
}
public IEnumerator GetEnumerator()
{
return new PartyListEnumerator(this);
}
public int Length => !this.isReady ? 0 : Marshal.ReadByte(partyListBegin + 0xF0);
public int Count => Length;
public object SyncRoot => this;
public bool IsSynchronized => false;
}
}

View file

@ -0,0 +1,19 @@
using Dalamud.Game.ClientState.Actors;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Dalamud.Game.ClientState.Structs
{
[StructLayout(LayoutKind.Explicit)]
public struct PartyMember
{
[FieldOffset(0x0)] public IntPtr namePtr;
[FieldOffset(0x8)] public long unknown;
[FieldOffset(0x10)] public int actorId;
[FieldOffset(0x14)] public ObjectKind objectKind;
}
}