diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index e35fe6dcf..d9d284b15 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -43,6 +43,7 @@ + diff --git a/Dalamud/Game/ClientState/Actors/ActorTable.cs b/Dalamud/Game/ClientState/Actors/ActorTable.cs index 760a4e492..4e45901eb 100644 --- a/Dalamud/Game/ClientState/Actors/ActorTable.cs +++ b/Dalamud/Game/ClientState/Actors/ActorTable.cs @@ -6,13 +6,16 @@ using System.Runtime.InteropServices; using Dalamud.Game.ClientState.Actors.Types; using Dalamud.Game.ClientState.Actors.Types.NonPlayer; using Dalamud.Hooking; +using JetBrains.Annotations; using Serilog; namespace Dalamud.Game.ClientState.Actors { /// /// This collection represents the currently spawned FFXIV actors. /// - public class ActorTable : IReadOnlyCollection, ICollection, IDisposable { + public class ActorTable : IReadOnlyCollection, ICollection { + + private const int ActorTableLength = 424; #region temporary imports for crash workaround @@ -29,14 +32,6 @@ namespace Dalamud.Game.ClientState.Actors { private ClientStateAddressResolver Address { get; } private Dalamud dalamud; - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - private delegate IntPtr SomeActorTableAccessDelegate(IntPtr manager, IntPtr offset); - - private Hook someActorTableAccessHook; - - private bool isReady = false; - private IntPtr realActorTablePtr; - /// /// Set up the actor table collection. /// @@ -45,27 +40,7 @@ namespace Dalamud.Game.ClientState.Actors { Address = addressResolver; this.dalamud = dalamud; - this.someActorTableAccessHook = new Hook( - 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); + Log.Verbose("Actor table address {ActorTable}", Address.ActorTable); } /// @@ -73,24 +48,17 @@ namespace Dalamud.Game.ClientState.Actors { /// /// Spawn index. /// at the specified spawn index. + [CanBeNull] public Actor this[int index] { get { - if (!this.isReady) - return null; - - if (this.someActorTableAccessHook != null) { - this.someActorTableAccessHook.Dispose(); - this.someActorTableAccessHook = null; - } - if (index >= Length) return null; - var tblIndex = this.realActorTablePtr + 8 + index * 8; + var tblIndex = Address.ActorTable + index * 8; 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) return null; @@ -154,7 +122,7 @@ namespace Dalamud.Game.ClientState.Actors { /// /// The amount of currently spawned actors. /// - public int Length => !this.isReady ? 0 : Marshal.ReadInt32(this.realActorTablePtr); + public int Length => ActorTableLength; int IReadOnlyCollection.Count => Length; diff --git a/Dalamud/Game/ClientState/ClientState.cs b/Dalamud/Game/ClientState/ClientState.cs index aff9b2ec8..96b0b40f1 100644 --- a/Dalamud/Game/ClientState/ClientState.cs +++ b/Dalamud/Game/ClientState/ClientState.cs @@ -6,6 +6,7 @@ using Dalamud.Game.ClientState.Actors.Types; using Dalamud.Game.Internal; using Dalamud.Game.Internal.Network; using Dalamud.Hooking; +using JetBrains.Annotations; using Lumina.Excel.GeneratedSheets; using Serilog; @@ -29,6 +30,7 @@ namespace Dalamud.Game.ClientState /// /// The local player character, if one is present. /// + [CanBeNull] public PlayerCharacter LocalPlayer { get { var actor = this.Actors[0]; @@ -122,13 +124,11 @@ 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(); } diff --git a/Dalamud/Game/ClientState/ClientStateAddressResolver.cs b/Dalamud/Game/ClientState/ClientStateAddressResolver.cs index 45ed5577a..dd559b623 100644 --- a/Dalamud/Game/ClientState/ClientStateAddressResolver.cs +++ b/Dalamud/Game/ClientState/ClientStateAddressResolver.cs @@ -5,19 +5,22 @@ namespace Dalamud.Game.ClientState { public sealed class ClientStateAddressResolver : BaseAddressResolver { // 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 JobGaugeData { get; private set; } public IntPtr KeyboardState { get; private set; } // Functions public IntPtr SetupTerritoryType { get; private set; } - public IntPtr SomeActorTableAccess { 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 ?? ?? ?? ??"); + // We don't need those anymore, but maybe someone else will - let's leave them here for good measure + //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); JobGaugeData = sig.GetStaticAddressFromSig("E8 ?? ?? ?? ?? FF C6 48 8D 5B 0C", 0xB9) + 0x10; diff --git a/Dalamud/Interface/DalamudDataWindow.cs b/Dalamud/Interface/DalamudDataWindow.cs index cb1607fb8..5232ba3e8 100644 --- a/Dalamud/Interface/DalamudDataWindow.cs +++ b/Dalamud/Interface/DalamudDataWindow.cs @@ -69,12 +69,11 @@ namespace Dalamud.Interface var stateString = string.Empty; // LocalPlayer is null in a number of situations (at least with the current visible-actors list) // 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."); - } - else - { + } else if (this.dalamud.ClientState.LocalPlayer == null) { + ImGui.TextUnformatted("LocalPlayer null."); + } else { stateString += $"FrameworkBase: {this.dalamud.Framework.Address.BaseAddress.ToInt64():X}\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++) { var actor = this.dalamud.ClientState.Actors[i]; + if (actor == null) + continue; + stateString += $"{actor.Address.ToInt64():X}:{actor.ActorId:X}[{i}] - {actor.ObjectKind} - {actor.Name} - {actor.Position.X} {actor.Position.Y} {actor.Position.Z}\n";