diff --git a/Dalamud/Game/ClientState/Fates/Fate.cs b/Dalamud/Game/ClientState/Fates/Fate.cs
index 504b690c3..c40a8960e 100644
--- a/Dalamud/Game/ClientState/Fates/Fate.cs
+++ b/Dalamud/Game/ClientState/Fates/Fate.cs
@@ -1,3 +1,4 @@
+using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using Dalamud.Data;
@@ -6,10 +7,12 @@ using Dalamud.Memory;
using Lumina.Excel;
+using CSFateContext = FFXIVClientStructs.FFXIV.Client.Game.Fate.FateContext;
+
namespace Dalamud.Game.ClientState.Fates;
///
-/// Interface representing an fate entry that can be seen in the current area.
+/// Interface representing a fate entry that can be seen in the current area.
///
public interface IFate : IEquatable
{
@@ -111,133 +114,96 @@ public interface IFate : IEquatable
///
/// Gets the address of this Fate in memory.
///
- IntPtr Address { get; }
+ nint Address { get; }
}
///
-/// This class represents an FFXIV Fate.
+/// This struct represents a Fate.
///
-internal unsafe partial class Fate
+/// A pointer to the FateContext.
+internal readonly unsafe struct Fate(CSFateContext* ptr) : IFate
{
- ///
- /// Initializes a new instance of the class.
- ///
- /// The address of this fate in memory.
- internal Fate(IntPtr address)
- {
- this.Address = address;
- }
-
///
- public IntPtr Address { get; }
-
- private FFXIVClientStructs.FFXIV.Client.Game.Fate.FateContext* Struct => (FFXIVClientStructs.FFXIV.Client.Game.Fate.FateContext*)this.Address;
-
- public static bool operator ==(Fate fate1, Fate fate2)
- {
- if (fate1 is null || fate2 is null)
- return Equals(fate1, fate2);
-
- return fate1.Equals(fate2);
- }
-
- public static bool operator !=(Fate fate1, Fate fate2) => !(fate1 == fate2);
-
- ///
- /// Gets a value indicating whether this Fate is still valid in memory.
- ///
- /// The fate to check.
- /// True or false.
- public static bool IsValid(Fate fate)
- {
- var clientState = Service.GetNullable();
-
- if (fate == null || clientState == null)
- return false;
-
- if (clientState.LocalContentId == 0)
- return false;
-
- return true;
- }
-
- ///
- /// Gets a value indicating whether this actor is still valid in memory.
- ///
- /// True or false.
- public bool IsValid() => IsValid(this);
+ public nint Address => (nint)ptr;
///
- bool IEquatable.Equals(IFate other) => this.FateId == other?.FateId;
-
- ///
- public override bool Equals(object obj) => ((IEquatable)this).Equals(obj as IFate);
-
- ///
- public override int GetHashCode() => this.FateId.GetHashCode();
-}
-
-///
-/// This class represents an FFXIV Fate.
-///
-internal unsafe partial class Fate : IFate
-{
- ///
- public ushort FateId => this.Struct->FateId;
+ public ushort FateId => ptr->FateId;
///
public RowRef GameData => LuminaUtils.CreateRef(this.FateId);
///
- public int StartTimeEpoch => this.Struct->StartTimeEpoch;
+ public int StartTimeEpoch => ptr->StartTimeEpoch;
///
- public short Duration => this.Struct->Duration;
+ public short Duration => ptr->Duration;
///
public long TimeRemaining => this.StartTimeEpoch + this.Duration - DateTimeOffset.Now.ToUnixTimeSeconds();
///
- public SeString Name => MemoryHelper.ReadSeString(&this.Struct->Name);
+ public SeString Name => MemoryHelper.ReadSeString(&ptr->Name);
///
- public SeString Description => MemoryHelper.ReadSeString(&this.Struct->Description);
+ public SeString Description => MemoryHelper.ReadSeString(&ptr->Description);
///
- public SeString Objective => MemoryHelper.ReadSeString(&this.Struct->Objective);
+ public SeString Objective => MemoryHelper.ReadSeString(&ptr->Objective);
///
- public FateState State => (FateState)this.Struct->State;
+ public FateState State => (FateState)ptr->State;
///
- public byte HandInCount => this.Struct->HandInCount;
+ public byte HandInCount => ptr->HandInCount;
///
- public byte Progress => this.Struct->Progress;
+ public byte Progress => ptr->Progress;
///
- public bool HasBonus => this.Struct->IsBonus;
+ public bool HasBonus => ptr->IsBonus;
///
- public uint IconId => this.Struct->IconId;
+ public uint IconId => ptr->IconId;
///
- public byte Level => this.Struct->Level;
+ public byte Level => ptr->Level;
///
- public byte MaxLevel => this.Struct->MaxLevel;
+ public byte MaxLevel => ptr->MaxLevel;
///
- public Vector3 Position => this.Struct->Location;
+ public Vector3 Position => ptr->Location;
///
- public float Radius => this.Struct->Radius;
+ public float Radius => ptr->Radius;
///
- public uint MapIconId => this.Struct->MapIconId;
+ public uint MapIconId => ptr->MapIconId;
///
/// Gets the territory this is located in.
///
- public RowRef TerritoryType => LuminaUtils.CreateRef(this.Struct->MapMarkers[0].MapMarkerData.TerritoryTypeId);
+ public RowRef TerritoryType => LuminaUtils.CreateRef(ptr->MapMarkers[0].MapMarkerData.TerritoryTypeId);
+
+ public static bool operator ==(Fate x, Fate y) => x.Equals(y);
+
+ public static bool operator !=(Fate x, Fate y) => !(x == y);
+
+ ///
+ public bool Equals(IFate? other)
+ {
+ return this.FateId == other.FateId;
+ }
+
+ ///
+ public override bool Equals([NotNullWhen(true)] object? obj)
+ {
+ return obj is Fate fate && this.Equals(fate);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ return this.FateId.GetHashCode();
+ }
}
diff --git a/Dalamud/Game/ClientState/Fates/FateTable.cs b/Dalamud/Game/ClientState/Fates/FateTable.cs
index 942d1561f..a6edf4a18 100644
--- a/Dalamud/Game/ClientState/Fates/FateTable.cs
+++ b/Dalamud/Game/ClientState/Fates/FateTable.cs
@@ -5,6 +5,7 @@ using Dalamud.IoC;
using Dalamud.IoC.Internal;
using Dalamud.Plugin.Services;
+using CSFateContext = FFXIVClientStructs.FFXIV.Client.Game.Fate.FateContext;
using CSFateManager = FFXIVClientStructs.FFXIV.Client.Game.Fate.FateManager;
namespace Dalamud.Game.ClientState.Fates;
@@ -25,7 +26,7 @@ internal sealed partial class FateTable : IServiceType, IFateTable
}
///
- public unsafe IntPtr Address => (nint)CSFateManager.Instance();
+ public unsafe nint Address => (nint)CSFateManager.Instance();
///
public unsafe int Length
@@ -72,30 +73,29 @@ internal sealed partial class FateTable : IServiceType, IFateTable
}
///
- public unsafe IntPtr GetFateAddress(int index)
+ public unsafe nint GetFateAddress(int index)
{
if (index >= this.Length)
- return IntPtr.Zero;
+ return 0;
var fateManager = CSFateManager.Instance();
if (fateManager == null)
- return IntPtr.Zero;
+ return 0;
- return (IntPtr)fateManager->Fates[index].Value;
+ return (nint)fateManager->Fates[index].Value;
}
///
- public IFate? CreateFateReference(IntPtr offset)
+ public unsafe IFate? CreateFateReference(IntPtr address)
{
- var clientState = Service.Get();
+ if (address == 0)
+ return null;
+ var clientState = Service.Get();
if (clientState.LocalContentId == 0)
return null;
- if (offset == IntPtr.Zero)
- return null;
-
- return new Fate(offset);
+ return new Fate((CSFateContext*)address);
}
}