|
|
|
|
@@ -174,65 +174,85 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase, IHighP
|
|
|
|
|
|
|
|
|
|
private unsafe void CheckAndUpdateObject(bool allowPublish)
|
|
|
|
|
{
|
|
|
|
|
var prevAddr = Address;
|
|
|
|
|
var prevDrawObj = DrawObjectAddress;
|
|
|
|
|
string? nameString = null;
|
|
|
|
|
|
|
|
|
|
var nextAddr = _getAddress();
|
|
|
|
|
|
|
|
|
|
if (nextAddr != IntPtr.Zero && !PtrGuard.LooksLikePtr(nextAddr))
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
nextAddr = IntPtr.Zero;
|
|
|
|
|
}
|
|
|
|
|
var prevAddr = Address;
|
|
|
|
|
var prevDrawObj = DrawObjectAddress;
|
|
|
|
|
string? nameString = null;
|
|
|
|
|
|
|
|
|
|
if (nextAddr != IntPtr.Zero &&
|
|
|
|
|
!PtrGuard.IsReadable(nextAddr, (nuint)sizeof(FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject)))
|
|
|
|
|
{
|
|
|
|
|
nextAddr = IntPtr.Zero;
|
|
|
|
|
}
|
|
|
|
|
var nextAddr = _getAddress();
|
|
|
|
|
|
|
|
|
|
Address = nextAddr;
|
|
|
|
|
|
|
|
|
|
if (Address != IntPtr.Zero)
|
|
|
|
|
{
|
|
|
|
|
var gameObject = (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)Address;
|
|
|
|
|
|
|
|
|
|
var draw = (nint)gameObject->DrawObject;
|
|
|
|
|
|
|
|
|
|
if (!PtrGuard.LooksLikePtr(draw) || !PtrGuard.IsReadable(draw, (nuint)sizeof(DrawObject)))
|
|
|
|
|
draw = 0;
|
|
|
|
|
|
|
|
|
|
DrawObjectAddress = draw;
|
|
|
|
|
EntityId = gameObject->EntityId;
|
|
|
|
|
|
|
|
|
|
if (PtrGuard.IsReadable(Address, (nuint)sizeof(Character)))
|
|
|
|
|
if (nextAddr != IntPtr.Zero && !PtrGuard.LooksLikePtr(nextAddr))
|
|
|
|
|
{
|
|
|
|
|
var chara = (Character*)Address;
|
|
|
|
|
nameString = chara->GameObject.NameString;
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(nameString) && !string.Equals(nameString, Name, StringComparison.Ordinal))
|
|
|
|
|
Name = nameString;
|
|
|
|
|
nextAddr = IntPtr.Zero;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DrawObjectAddress = IntPtr.Zero;
|
|
|
|
|
EntityId = uint.MaxValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CurrentDrawCondition = (Address != IntPtr.Zero && DrawObjectAddress != IntPtr.Zero)
|
|
|
|
|
? IsBeingDrawnUnsafe()
|
|
|
|
|
: DrawCondition.DrawObjectZero;
|
|
|
|
|
if (nextAddr != IntPtr.Zero &&
|
|
|
|
|
!PtrGuard.IsReadable(nextAddr, (nuint)sizeof(FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject)))
|
|
|
|
|
{
|
|
|
|
|
nextAddr = IntPtr.Zero;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_haltProcessing || !allowPublish) return;
|
|
|
|
|
Address = nextAddr;
|
|
|
|
|
|
|
|
|
|
bool drawObjDiff = DrawObjectAddress != prevDrawObj;
|
|
|
|
|
bool addrDiff = Address != prevAddr;
|
|
|
|
|
if (Address != IntPtr.Zero)
|
|
|
|
|
{
|
|
|
|
|
var gameObject = (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)Address;
|
|
|
|
|
|
|
|
|
|
var draw = (nint)gameObject->DrawObject;
|
|
|
|
|
|
|
|
|
|
if (!PtrGuard.LooksLikePtr(draw) || !PtrGuard.IsReadable(draw, (nuint)sizeof(DrawObject)))
|
|
|
|
|
draw = 0;
|
|
|
|
|
|
|
|
|
|
DrawObjectAddress = draw;
|
|
|
|
|
EntityId = gameObject->EntityId;
|
|
|
|
|
|
|
|
|
|
if (PtrGuard.IsReadable(Address, (nuint)sizeof(Character)))
|
|
|
|
|
{
|
|
|
|
|
var chara = (Character*)Address;
|
|
|
|
|
nameString = chara->GameObject.NameString;
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(nameString) && !string.Equals(nameString, Name, StringComparison.Ordinal))
|
|
|
|
|
Name = nameString;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DrawObjectAddress = IntPtr.Zero;
|
|
|
|
|
EntityId = uint.MaxValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CurrentDrawCondition = (Address != IntPtr.Zero && DrawObjectAddress != IntPtr.Zero)
|
|
|
|
|
? IsBeingDrawnUnsafe()
|
|
|
|
|
: DrawCondition.DrawObjectZero;
|
|
|
|
|
|
|
|
|
|
if (_haltProcessing || !allowPublish) return;
|
|
|
|
|
|
|
|
|
|
bool drawObjDiff = DrawObjectAddress != prevDrawObj;
|
|
|
|
|
bool addrDiff = Address != prevAddr;
|
|
|
|
|
|
|
|
|
|
if (Address == IntPtr.Zero || DrawObjectAddress == IntPtr.Zero)
|
|
|
|
|
{
|
|
|
|
|
if (addrDiff || drawObjDiff)
|
|
|
|
|
{
|
|
|
|
|
CurrentDrawCondition = DrawCondition.DrawObjectZero;
|
|
|
|
|
Logger.LogTrace("[{this}] Changed", this);
|
|
|
|
|
if (_isOwnedObject && ObjectKind != ObjectKind.Player)
|
|
|
|
|
Mediator.Publish(new ClearCacheForObjectMessage(this));
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!PtrGuard.IsReadable(Address, (nuint)sizeof(Character)) ||
|
|
|
|
|
!PtrGuard.IsReadable(DrawObjectAddress, (nuint)sizeof(DrawObject)))
|
|
|
|
|
{
|
|
|
|
|
Logger.LogTrace("[{this}] Pointers became invalid during update", this);
|
|
|
|
|
Address = IntPtr.Zero;
|
|
|
|
|
DrawObjectAddress = IntPtr.Zero;
|
|
|
|
|
CurrentDrawCondition = DrawCondition.DrawObjectZero;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Address != IntPtr.Zero && DrawObjectAddress != IntPtr.Zero
|
|
|
|
|
&& PtrGuard.IsReadable(Address, (nuint)sizeof(Character))
|
|
|
|
|
&& PtrGuard.IsReadable(DrawObjectAddress, (nuint)sizeof(DrawObject)))
|
|
|
|
|
{
|
|
|
|
|
var chara = (Character*)Address;
|
|
|
|
|
var drawObj = (DrawObject*)DrawObjectAddress;
|
|
|
|
|
|
|
|
|
|
@@ -315,12 +335,11 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase, IHighP
|
|
|
|
|
Mediator.Publish(new CreateCacheForObjectMessage(this));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (addrDiff || drawObjDiff)
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Address = IntPtr.Zero;
|
|
|
|
|
DrawObjectAddress = IntPtr.Zero;
|
|
|
|
|
CurrentDrawCondition = DrawCondition.DrawObjectZero;
|
|
|
|
|
Logger.LogTrace("[{this}] Changed", this);
|
|
|
|
|
if (_isOwnedObject && ObjectKind != ObjectKind.Player)
|
|
|
|
|
Mediator.Publish(new ClearCacheForObjectMessage(this));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -443,11 +462,18 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase, IHighP
|
|
|
|
|
{
|
|
|
|
|
if (Address == IntPtr.Zero) return DrawCondition.ObjectZero;
|
|
|
|
|
if (DrawObjectAddress == IntPtr.Zero) return DrawCondition.DrawObjectZero;
|
|
|
|
|
|
|
|
|
|
if (!PtrGuard.IsReadable(Address, (nuint)sizeof(FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject)))
|
|
|
|
|
return DrawCondition.ObjectZero;
|
|
|
|
|
|
|
|
|
|
var visibilityFlags = ((FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)Address)->RenderFlags;
|
|
|
|
|
if (visibilityFlags != VisibilityFlags.None) return DrawCondition.RenderFlags;
|
|
|
|
|
|
|
|
|
|
if (ObjectKind == ObjectKind.Player)
|
|
|
|
|
{
|
|
|
|
|
if (!PtrGuard.IsReadable(DrawObjectAddress, (nuint)sizeof(CharacterBase)))
|
|
|
|
|
return DrawCondition.DrawObjectZero;
|
|
|
|
|
|
|
|
|
|
var modelInSlotLoaded = (((CharacterBase*)DrawObjectAddress)->HasModelInSlotLoaded != 0);
|
|
|
|
|
if (modelInSlotLoaded) return DrawCondition.ModelInSlotLoaded;
|
|
|
|
|
var modelFilesInSlotLoaded = (((CharacterBase*)DrawObjectAddress)->HasModelFilesInSlotLoaded != 0);
|
|
|
|
|
|