mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-15 05:04:15 +01:00
feat: new actor table shenanigans
This commit is contained in:
parent
03e4a4d25c
commit
f80a4e7432
5 changed files with 26 additions and 52 deletions
|
|
@ -43,6 +43,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CheapLoc" Version="1.1.3" />
|
<PackageReference Include="CheapLoc" Version="1.1.3" />
|
||||||
|
<PackageReference Include="JetBrains.Annotations" Version="2020.1.0" />
|
||||||
<PackageReference Include="Lumina" Version="1.1.1" />
|
<PackageReference Include="Lumina" Version="1.1.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||||
<PackageReference Include="PropertyChanged.Fody" Version="2.6.1" />
|
<PackageReference Include="PropertyChanged.Fody" Version="2.6.1" />
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,16 @@ using System.Runtime.InteropServices;
|
||||||
using Dalamud.Game.ClientState.Actors.Types;
|
using Dalamud.Game.ClientState.Actors.Types;
|
||||||
using Dalamud.Game.ClientState.Actors.Types.NonPlayer;
|
using Dalamud.Game.ClientState.Actors.Types.NonPlayer;
|
||||||
using Dalamud.Hooking;
|
using Dalamud.Hooking;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
namespace Dalamud.Game.ClientState.Actors {
|
namespace Dalamud.Game.ClientState.Actors {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This collection represents the currently spawned FFXIV actors.
|
/// This collection represents the currently spawned FFXIV actors.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ActorTable : IReadOnlyCollection<Actor>, ICollection, IDisposable {
|
public class ActorTable : IReadOnlyCollection<Actor>, ICollection {
|
||||||
|
|
||||||
|
private const int ActorTableLength = 424;
|
||||||
|
|
||||||
#region temporary imports for crash workaround
|
#region temporary imports for crash workaround
|
||||||
|
|
||||||
|
|
@ -29,14 +32,6 @@ namespace Dalamud.Game.ClientState.Actors {
|
||||||
private ClientStateAddressResolver Address { get; }
|
private ClientStateAddressResolver Address { get; }
|
||||||
private Dalamud dalamud;
|
private Dalamud dalamud;
|
||||||
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
|
|
||||||
private delegate IntPtr SomeActorTableAccessDelegate(IntPtr manager, IntPtr offset);
|
|
||||||
|
|
||||||
private Hook<SomeActorTableAccessDelegate> someActorTableAccessHook;
|
|
||||||
|
|
||||||
private bool isReady = false;
|
|
||||||
private IntPtr realActorTablePtr;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set up the actor table collection.
|
/// Set up the actor table collection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -45,27 +40,7 @@ namespace Dalamud.Game.ClientState.Actors {
|
||||||
Address = addressResolver;
|
Address = addressResolver;
|
||||||
this.dalamud = dalamud;
|
this.dalamud = dalamud;
|
||||||
|
|
||||||
this.someActorTableAccessHook = new Hook<SomeActorTableAccessDelegate>(
|
Log.Verbose("Actor table address {ActorTable}", Address.ActorTable);
|
||||||
Address.SomeActorTableAccess, new SomeActorTableAccessDelegate(SomeActorTableAccessDetour), this);
|
|
||||||
|
|
||||||
Log.Verbose("Actor table address {ActorTable}", Address.ViewportActorTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Enable() {
|
|
||||||
this.someActorTableAccessHook.Enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose() {
|
|
||||||
if (!this.isReady)
|
|
||||||
this.someActorTableAccessHook.Dispose();
|
|
||||||
|
|
||||||
this.isReady = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IntPtr SomeActorTableAccessDetour(IntPtr manager, IntPtr offset) {
|
|
||||||
this.realActorTablePtr = offset;
|
|
||||||
this.isReady = true;
|
|
||||||
return this.someActorTableAccessHook.Original(manager, offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -73,24 +48,17 @@ namespace Dalamud.Game.ClientState.Actors {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="index">Spawn index.</param>
|
/// <param name="index">Spawn index.</param>
|
||||||
/// <returns><see cref="Actor" /> at the specified spawn index.</returns>
|
/// <returns><see cref="Actor" /> at the specified spawn index.</returns>
|
||||||
|
[CanBeNull]
|
||||||
public Actor this[int index] {
|
public Actor this[int index] {
|
||||||
get {
|
get {
|
||||||
if (!this.isReady)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (this.someActorTableAccessHook != null) {
|
|
||||||
this.someActorTableAccessHook.Dispose();
|
|
||||||
this.someActorTableAccessHook = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index >= Length)
|
if (index >= Length)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var tblIndex = this.realActorTablePtr + 8 + index * 8;
|
var tblIndex = Address.ActorTable + index * 8;
|
||||||
|
|
||||||
var offset = Marshal.ReadIntPtr(tblIndex);
|
var offset = Marshal.ReadIntPtr(tblIndex);
|
||||||
|
|
||||||
//Log.Verbose("Actor at {0} for {1}", offset.ToInt64().ToString("X"), index);
|
Log.Debug($"Reading actor {index} at {tblIndex.ToInt64():X} pointing to {offset.ToInt64():X}");
|
||||||
|
|
||||||
if (offset == IntPtr.Zero)
|
if (offset == IntPtr.Zero)
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -154,7 +122,7 @@ namespace Dalamud.Game.ClientState.Actors {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The amount of currently spawned actors.
|
/// The amount of currently spawned actors.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Length => !this.isReady ? 0 : Marshal.ReadInt32(this.realActorTablePtr);
|
public int Length => ActorTableLength;
|
||||||
|
|
||||||
int IReadOnlyCollection<Actor>.Count => Length;
|
int IReadOnlyCollection<Actor>.Count => Length;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using Dalamud.Game.ClientState.Actors.Types;
|
||||||
using Dalamud.Game.Internal;
|
using Dalamud.Game.Internal;
|
||||||
using Dalamud.Game.Internal.Network;
|
using Dalamud.Game.Internal.Network;
|
||||||
using Dalamud.Hooking;
|
using Dalamud.Hooking;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using Lumina.Excel.GeneratedSheets;
|
using Lumina.Excel.GeneratedSheets;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
|
|
@ -29,6 +30,7 @@ namespace Dalamud.Game.ClientState
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The local player character, if one is present.
|
/// The local player character, if one is present.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[CanBeNull]
|
||||||
public PlayerCharacter LocalPlayer {
|
public PlayerCharacter LocalPlayer {
|
||||||
get {
|
get {
|
||||||
var actor = this.Actors[0];
|
var actor = this.Actors[0];
|
||||||
|
|
@ -122,13 +124,11 @@ namespace Dalamud.Game.ClientState
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Enable() {
|
public void Enable() {
|
||||||
this.Actors.Enable();
|
|
||||||
this.PartyList.Enable();
|
this.PartyList.Enable();
|
||||||
this.setupTerritoryTypeHook.Enable();
|
this.setupTerritoryTypeHook.Enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
this.Actors.Dispose();
|
|
||||||
this.PartyList.Dispose();
|
this.PartyList.Dispose();
|
||||||
this.setupTerritoryTypeHook.Dispose();
|
this.setupTerritoryTypeHook.Dispose();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,19 +5,22 @@ namespace Dalamud.Game.ClientState
|
||||||
{
|
{
|
||||||
public sealed class ClientStateAddressResolver : BaseAddressResolver {
|
public sealed class ClientStateAddressResolver : BaseAddressResolver {
|
||||||
// Static offsets
|
// Static offsets
|
||||||
public IntPtr ViewportActorTable { get; private set; }
|
public IntPtr ActorTable { get; private set; }
|
||||||
|
//public IntPtr ViewportActorTable { get; private set; }
|
||||||
public IntPtr LocalContentId { get; private set; }
|
public IntPtr LocalContentId { get; private set; }
|
||||||
public IntPtr JobGaugeData { get; private set; }
|
public IntPtr JobGaugeData { get; private set; }
|
||||||
public IntPtr KeyboardState { get; private set; }
|
public IntPtr KeyboardState { get; private set; }
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
public IntPtr SetupTerritoryType { get; private set; }
|
public IntPtr SetupTerritoryType { get; private set; }
|
||||||
public IntPtr SomeActorTableAccess { get; private set; }
|
//public IntPtr SomeActorTableAccess { get; private set; }
|
||||||
public IntPtr PartyListUpdate { get; private set; }
|
public IntPtr PartyListUpdate { get; private set; }
|
||||||
|
|
||||||
protected override void Setup64Bit(SigScanner sig) {
|
protected override void Setup64Bit(SigScanner sig) {
|
||||||
ViewportActorTable = sig.GetStaticAddressFromSig("48 8D 0D ?? ?? ?? ?? 85 ED", 0) + 0x148;
|
// We don't need those anymore, but maybe someone else will - let's leave them here for good measure
|
||||||
SomeActorTableAccess = sig.ScanText("E8 ?? ?? ?? ?? 48 8D 55 A0 48 8D 8E ?? ?? ?? ??");
|
//ViewportActorTable = sig.GetStaticAddressFromSig("48 8D 0D ?? ?? ?? ?? 85 ED", 0) + 0x148;
|
||||||
|
//SomeActorTableAccess = sig.ScanText("E8 ?? ?? ?? ?? 48 8D 55 A0 48 8D 8E ?? ?? ?? ??");
|
||||||
|
ActorTable = sig.GetStaticAddressFromSig("88 91 ?? ?? ?? ?? 48 8D 3D ?? ?? ?? ??", 0x0);
|
||||||
|
|
||||||
LocalContentId = sig.GetStaticAddressFromSig("48 8B 05 ?? ?? ?? ?? 48 89 86 ?? ?? ?? ??", 0);
|
LocalContentId = sig.GetStaticAddressFromSig("48 8B 05 ?? ?? ?? ?? 48 89 86 ?? ?? ?? ??", 0);
|
||||||
JobGaugeData = sig.GetStaticAddressFromSig("E8 ?? ?? ?? ?? FF C6 48 8D 5B 0C", 0xB9) + 0x10;
|
JobGaugeData = sig.GetStaticAddressFromSig("E8 ?? ?? ?? ?? FF C6 48 8D 5B 0C", 0xB9) + 0x10;
|
||||||
|
|
|
||||||
|
|
@ -69,12 +69,11 @@ namespace Dalamud.Interface
|
||||||
var stateString = string.Empty;
|
var stateString = string.Empty;
|
||||||
// LocalPlayer is null in a number of situations (at least with the current visible-actors list)
|
// LocalPlayer is null in a number of situations (at least with the current visible-actors list)
|
||||||
// which would crash here.
|
// which would crash here.
|
||||||
if (this.dalamud.ClientState.Actors.Length == 0 || this.dalamud.ClientState.LocalPlayer == null)
|
if (this.dalamud.ClientState.Actors.Length == 0) {
|
||||||
{
|
|
||||||
ImGui.TextUnformatted("Data not ready.");
|
ImGui.TextUnformatted("Data not ready.");
|
||||||
}
|
} else if (this.dalamud.ClientState.LocalPlayer == null) {
|
||||||
else
|
ImGui.TextUnformatted("LocalPlayer null.");
|
||||||
{
|
} else {
|
||||||
stateString += $"FrameworkBase: {this.dalamud.Framework.Address.BaseAddress.ToInt64():X}\n";
|
stateString += $"FrameworkBase: {this.dalamud.Framework.Address.BaseAddress.ToInt64():X}\n";
|
||||||
|
|
||||||
stateString += $"ActorTableLen: {this.dalamud.ClientState.Actors.Length}\n";
|
stateString += $"ActorTableLen: {this.dalamud.ClientState.Actors.Length}\n";
|
||||||
|
|
@ -88,6 +87,9 @@ namespace Dalamud.Interface
|
||||||
for (var i = 0; i < this.dalamud.ClientState.Actors.Length; i++) {
|
for (var i = 0; i < this.dalamud.ClientState.Actors.Length; i++) {
|
||||||
var actor = this.dalamud.ClientState.Actors[i];
|
var actor = this.dalamud.ClientState.Actors[i];
|
||||||
|
|
||||||
|
if (actor == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
stateString +=
|
stateString +=
|
||||||
$"{actor.Address.ToInt64():X}:{actor.ActorId:X}[{i}] - {actor.ObjectKind} - {actor.Name} - {actor.Position.X} {actor.Position.Y} {actor.Position.Z}\n";
|
$"{actor.Address.ToInt64():X}:{actor.ActorId:X}[{i}] - {actor.ObjectKind} - {actor.Name} - {actor.Position.X} {actor.Position.Y} {actor.Position.Z}\n";
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue