diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs
index 5717669a9..99b1c08e5 100644
--- a/Dalamud/Dalamud.cs
+++ b/Dalamud/Dalamud.cs
@@ -110,6 +110,7 @@ namespace Dalamud {
}
this.Framework.Enable();
+ this.ClientState.Enable();
this.BotManager.Start();
@@ -147,7 +148,8 @@ namespace Dalamud {
this.InterfaceManager.Dispose();
- Framework.Dispose();
+ this.Framework.Dispose();
+ this.ClientState.Dispose();
this.BotManager.Dispose();
diff --git a/Dalamud/Game/ClientState/ClientState.cs b/Dalamud/Game/ClientState/ClientState.cs
index 7deecca02..0aed29e98 100644
--- a/Dalamud/Game/ClientState/ClientState.cs
+++ b/Dalamud/Game/ClientState/ClientState.cs
@@ -1,8 +1,12 @@
+using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Dalamud.Game.ClientState.Actors;
using Dalamud.Game.ClientState.Actors.Types;
using Dalamud.Game.Internal;
+using Dalamud.Game.Internal.Network;
+using Dalamud.Hooking;
+using Lumina.Excel.GeneratedSheets;
using Serilog;
namespace Dalamud.Game.ClientState
@@ -10,7 +14,7 @@ namespace Dalamud.Game.ClientState
///
/// This class represents the state of the game client at the time of access.
///
- public class ClientState : INotifyPropertyChanged {
+ public class ClientState : INotifyPropertyChanged, IDisposable {
public event PropertyChangedEventHandler PropertyChanged;
private ClientStateAddressResolver Address { get; }
@@ -36,10 +40,35 @@ namespace Dalamud.Game.ClientState
}
}
+ #region TerritoryType
+
+ // TODO: The hooking logic for this should go into a separate class.
+ [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
+ private delegate IntPtr SetupTerritoryTypeDelegate(IntPtr manager, ushort terriType);
+
+ private readonly Hook setupTerritoryTypeHook;
+
///
/// The current Territory the player resides in.
///
- public uint TerritoryType => (uint) Marshal.ReadInt32(Address.TerritoryType);
+ public ushort TerritoryType;
+
+ ///
+ /// Event that gets fired when the current Territory changes.
+ ///
+ public EventHandler TerritoryChanged;
+
+ private IntPtr SetupTerritoryTypeDetour(IntPtr manager, ushort terriType)
+ {
+ this.TerritoryType = terriType;
+ this.TerritoryChanged?.Invoke(this, terriType);
+
+ Log.Debug("TerritoryType changed: {0}", terriType);
+
+ return this.setupTerritoryTypeHook.Original(manager, terriType);
+ }
+
+ #endregion
///
/// The content ID of the local character.
@@ -69,11 +98,23 @@ namespace Dalamud.Game.ClientState
this.JobGauges = new JobGauges(Address);
- Log.Verbose("TerritoryType address {TerritoryType}", Address.TerritoryType);
+ Log.Verbose("SetupTerritoryType address {SetupTerritoryType}", Address.SetupTerritoryType);
+
+ this.setupTerritoryTypeHook = new Hook(Address.SetupTerritoryType,
+ new SetupTerritoryTypeDelegate(SetupTerritoryTypeDetour),
+ this);
dalamud.Framework.OnUpdateEvent += FrameworkOnOnUpdateEvent;
}
+ public void Enable() {
+ this.setupTerritoryTypeHook.Enable();
+ }
+
+ public void Dispose() {
+ this.setupTerritoryTypeHook.Dispose();
+ }
+
private void FrameworkOnOnUpdateEvent(Framework framework) {
// ignored
}
diff --git a/Dalamud/Game/ClientState/ClientStateAddressResolver.cs b/Dalamud/Game/ClientState/ClientStateAddressResolver.cs
index b3ef8d650..8d6bab2de 100644
--- a/Dalamud/Game/ClientState/ClientStateAddressResolver.cs
+++ b/Dalamud/Game/ClientState/ClientStateAddressResolver.cs
@@ -4,16 +4,20 @@ using Dalamud.Game.Internal;
namespace Dalamud.Game.ClientState
{
public sealed class ClientStateAddressResolver : BaseAddressResolver {
+ // Static offsets
public IntPtr ActorTable { get; private set; }
public IntPtr LocalContentId { get; private set; }
public IntPtr JobGaugeData { get; private set; }
- public IntPtr TerritoryType { get; private set; }
+
+ // Functions
+ public IntPtr SetupTerritoryType { get; private set; }
protected override void Setup64Bit(SigScanner sig) {
ActorTable = sig.GetStaticAddressFromSig("48 8D 0D ?? ?? ?? ?? 85 ED", 0) + 0x148;
LocalContentId = sig.GetStaticAddressFromSig("48 8B 05 ?? ?? ?? ?? 48 89 86 ?? ?? ?? ??", 0);
JobGaugeData = sig.GetStaticAddressFromSig("E8 ?? ?? ?? ?? FF C6 48 8D 5B 0C", 0xB9) + 0x10;
- TerritoryType = sig.GetStaticAddressFromSig("48 83 EC 20 81 3D ?? ?? ?? ?? ?? ?? ?? ?? 49 8B F8", 0);
+
+ SetupTerritoryType = sig.ScanText("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B F9 66 89 91 ?? ?? ?? ??");
}
}
}
diff --git a/Dalamud/Game/Internal/Framework.cs b/Dalamud/Game/Internal/Framework.cs
index 54e37c224..78250a17b 100644
--- a/Dalamud/Game/Internal/Framework.cs
+++ b/Dalamud/Game/Internal/Framework.cs
@@ -17,6 +17,9 @@ namespace Dalamud.Game.Internal {
public delegate void OnUpdateDelegate(Framework framework);
+ ///
+ /// Event that gets fired every time the game framework updates.
+ ///
public event OnUpdateDelegate OnUpdateEvent;
private Hook updateHook;