This commit is contained in:
2025-12-16 06:31:29 +09:00
parent bdfcf254a8
commit 4444a88746
32 changed files with 1204 additions and 464 deletions

View File

@@ -324,7 +324,28 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
EnsureIsOnFramework();
playerPointer ??= GetPlayerPtr();
if (playerPointer == IntPtr.Zero) return IntPtr.Zero;
return _objectTable.GetObjectAddress(((GameObject*)playerPointer)->ObjectIndex + 1);
var playerAddress = playerPointer.Value;
var ownerEntityId = ((Character*)playerAddress)->EntityId;
if (ownerEntityId == 0) return IntPtr.Zero;
if (playerAddress == _actorObjectService.LocalPlayerAddress)
{
var localOwned = _actorObjectService.LocalMinionOrMountAddress;
if (localOwned != nint.Zero)
{
return localOwned;
}
}
var ownedObject = FindOwnedObject(ownerEntityId, playerAddress, static kind =>
kind == DalamudObjectKind.MountType || kind == DalamudObjectKind.Companion);
if (ownedObject != nint.Zero)
{
return ownedObject;
}
return _objectTable.GetObjectAddress(((GameObject*)playerAddress)->ObjectIndex + 1);
}
public async Task<IntPtr> GetMinionOrMountAsync(IntPtr? playerPointer = null)
@@ -347,6 +368,62 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
return await RunOnFrameworkThread(() => GetPetPtr(playerPointer)).ConfigureAwait(false);
}
private unsafe nint FindOwnedObject(uint ownerEntityId, nint ownerAddress, Func<DalamudObjectKind, bool> matchesKind)
{
if (ownerEntityId == 0)
{
return nint.Zero;
}
foreach (var obj in _objectTable)
{
if (obj is null || obj.Address == nint.Zero || obj.Address == ownerAddress)
{
continue;
}
if (!matchesKind(obj.ObjectKind))
{
continue;
}
var candidate = (GameObject*)obj.Address;
if (ResolveOwnerId(candidate) == ownerEntityId)
{
return obj.Address;
}
}
return nint.Zero;
}
private static unsafe uint ResolveOwnerId(GameObject* gameObject)
{
if (gameObject == null)
{
return 0;
}
if (gameObject->OwnerId != 0)
{
return gameObject->OwnerId;
}
var character = (Character*)gameObject;
if (character == null)
{
return 0;
}
if (character->CompanionOwnerId != 0)
{
return character->CompanionOwnerId;
}
var parent = character->GetParentCharacter();
return parent != null ? parent->EntityId : 0;
}
public async Task<IPlayerCharacter> GetPlayerCharacterAsync()
{
return await RunOnFrameworkThread(GetPlayerCharacter).ConfigureAwait(false);
@@ -393,6 +470,24 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
return await RunOnFrameworkThread(() => _cid.Value.ToString().GetHash256()).ConfigureAwait(false);
}
public static unsafe bool TryGetHashedCID(IPlayerCharacter? playerCharacter, out string hashedCid)
{
hashedCid = string.Empty;
if (playerCharacter == null)
return false;
var address = playerCharacter.Address;
if (address == nint.Zero)
return false;
var cid = ((BattleChara*)address)->Character.ContentId;
if (cid == 0)
return false;
hashedCid = cid.ToString().GetHash256();
return true;
}
public unsafe static string GetHashedCIDFromPlayerPointer(nint ptr)
{
return ((BattleChara*)ptr)->Character.ContentId.ToString().GetHash256();
@@ -516,17 +611,13 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
var fileName = Path.GetFileNameWithoutExtension(callerFilePath);
await _performanceCollector.LogPerformance(this, $"RunOnFramework:Act/{fileName}>{callerMember}:{callerLineNumber}", async () =>
{
if (!_framework.IsInFrameworkUpdateThread)
if (_framework.IsInFrameworkUpdateThread)
{
await _framework.RunOnFrameworkThread(act).ContinueWith((_) => Task.CompletedTask).ConfigureAwait(false);
while (_framework.IsInFrameworkUpdateThread) // yield the thread again, should technically never be triggered
{
_logger.LogTrace("Still on framework");
await Task.Delay(1).ConfigureAwait(false);
}
}
else
act();
return;
}
await _framework.RunOnFrameworkThread(act).ConfigureAwait(false);
}).ConfigureAwait(false);
}
@@ -535,18 +626,12 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
var fileName = Path.GetFileNameWithoutExtension(callerFilePath);
return await _performanceCollector.LogPerformance(this, $"RunOnFramework:Func<{typeof(T)}>/{fileName}>{callerMember}:{callerLineNumber}", async () =>
{
if (!_framework.IsInFrameworkUpdateThread)
if (_framework.IsInFrameworkUpdateThread)
{
var result = await _framework.RunOnFrameworkThread(func).ContinueWith((task) => task.Result).ConfigureAwait(false);
while (_framework.IsInFrameworkUpdateThread) // yield the thread again, should technically never be triggered
{
_logger.LogTrace("Still on framework");
await Task.Delay(1).ConfigureAwait(false);
}
return result;
return func.Invoke();
}
return func.Invoke();
return await _framework.RunOnFrameworkThread(func).ConfigureAwait(false);
}).ConfigureAwait(false);
}