Merge remote-tracking branch 'Exter-N/72'

This commit is contained in:
Ottermandias 2025-03-28 00:59:14 +01:00
commit 6cbc8bd58f
3 changed files with 45 additions and 33 deletions

@ -1 +1 @@
Subproject commit 9ae4a97110fff005a54213815086ce950d4d8b2d
Subproject commit 1158cf404a16979d0b7e12f7bbcbbc651da16add

View file

@ -23,24 +23,35 @@ public class ResourceTreeFactory(
Configuration config,
ActorManager actors,
PathState pathState,
IFramework framework,
ModManager modManager) : IService
{
private static readonly string ParentDirectoryPrefix = $"..{Path.DirectorySeparatorChar}";
private TreeBuildCache CreateTreeBuildCache()
=> new(objects, gameData, actors);
=> new(framework.IsInFrameworkUpdateThread ? objects : null, gameData, actors);
private TreeBuildCache CreateTreeBuildCache(Flags flags)
=> !framework.IsInFrameworkUpdateThread && flags.HasFlag(Flags.PopulateObjectTableData)
? framework.RunOnFrameworkThread(CreateTreeBuildCache).Result
: CreateTreeBuildCache();
public IEnumerable<ICharacter> GetLocalPlayerRelatedCharacters()
{
var cache = CreateTreeBuildCache();
return cache.GetLocalPlayerRelatedCharacters();
}
=> framework.RunOnFrameworkThread(() =>
{
var cache = CreateTreeBuildCache();
return cache.GetLocalPlayerRelatedCharacters();
}).Result;
public IEnumerable<(ICharacter Character, ResourceTree ResourceTree)> FromObjectTable(
Flags flags)
{
var cache = CreateTreeBuildCache();
var characters = (flags & Flags.LocalPlayerRelatedOnly) != 0 ? cache.GetLocalPlayerRelatedCharacters() : cache.GetCharacters();
var (cache, characters) = framework.RunOnFrameworkThread(() =>
{
var cache = CreateTreeBuildCache();
var characters = ((flags & Flags.LocalPlayerRelatedOnly) != 0 ? cache.GetLocalPlayerRelatedCharacters() : cache.GetCharacters()).ToArray();
return (cache, characters);
}).Result;
foreach (var character in characters)
{
@ -53,7 +64,7 @@ public class ResourceTreeFactory(
public IEnumerable<(ICharacter Character, ResourceTree ResourceTree)> FromCharacters(
IEnumerable<ICharacter> characters, Flags flags)
{
var cache = CreateTreeBuildCache();
var cache = CreateTreeBuildCache(flags);
foreach (var character in characters)
{
var tree = FromCharacter(character, cache, flags);
@ -63,7 +74,7 @@ public class ResourceTreeFactory(
}
public ResourceTree? FromCharacter(ICharacter character, Flags flags)
=> FromCharacter(character, CreateTreeBuildCache(), flags);
=> FromCharacter(character, CreateTreeBuildCache(flags), flags);
private unsafe ResourceTree? FromCharacter(ICharacter character, TreeBuildCache cache, Flags flags)
{
@ -80,7 +91,7 @@ public class ResourceTreeFactory(
return null;
var localPlayerRelated = cache.IsLocalPlayerRelated(character);
var (name, anonymizedName, related) = GetCharacterName(character);
var (name, anonymizedName, related) = GetCharacterName((GameObject*)character.Address);
var networked = character.EntityId != 0xE0000000;
var tree = new ResourceTree(name, anonymizedName, character.ObjectIndex, (nint)gameObjStruct, (nint)drawObjStruct, localPlayerRelated, related,
networked, collectionResolveData.ModCollection.Identity.Name, collectionResolveData.ModCollection.Identity.AnonymizedName);
@ -183,36 +194,37 @@ public class ResourceTreeFactory(
}
}
private unsafe (string Name, string AnonymizedName, bool PlayerRelated) GetCharacterName(ICharacter character)
private unsafe (string Name, string AnonymizedName, bool PlayerRelated) GetCharacterName(GameObject* character)
{
var identifier = actors.FromObject((GameObject*)character.Address, out var owner, true, false, false);
var identifier = actors.FromObject(character, out var owner, true, false, false);
var identifierStr = identifier.ToString();
return (identifierStr, identifier.Incognito(identifierStr), IsPlayerRelated(identifier, owner));
}
private unsafe bool IsPlayerRelated(ICharacter? character)
private unsafe bool IsPlayerRelated(GameObject* character)
{
if (character == null)
if (character is null)
return false;
var identifier = actors.FromObject((GameObject*)character.Address, out var owner, true, false, false);
var identifier = actors.FromObject(character, out var owner, true, false, false);
return IsPlayerRelated(identifier, owner);
}
private bool IsPlayerRelated(ActorIdentifier identifier, Actor owner)
private unsafe bool IsPlayerRelated(ActorIdentifier identifier, Actor owner)
=> identifier.Type switch
{
IdentifierType.Player => true,
IdentifierType.Owned => IsPlayerRelated(objects.Objects.CreateObjectReference(owner) as ICharacter),
IdentifierType.Owned => IsPlayerRelated(owner.AsObject),
_ => false,
};
[Flags]
public enum Flags
{
RedactExternalPaths = 1,
WithUiData = 2,
LocalPlayerRelatedOnly = 4,
WithOwnership = 8,
RedactExternalPaths = 1,
WithUiData = 2,
LocalPlayerRelatedOnly = 4,
WithOwnership = 8,
PopulateObjectTableData = 16,
}
}

View file

@ -12,14 +12,15 @@ using Penumbra.String.Classes;
namespace Penumbra.Interop.ResourceTree;
internal readonly struct TreeBuildCache(ObjectManager objects, IDataManager dataManager, ActorManager actors)
internal readonly struct TreeBuildCache(ObjectManager? objects, IDataManager dataManager, ActorManager actors)
{
private readonly Dictionary<FullPath, IReadOnlyDictionary<uint, Name>?> _shaderPackageNames = [];
private readonly IGameObject? _player = objects?.GetDalamudObject(0);
public unsafe bool IsLocalPlayerRelated(ICharacter character)
{
var player = objects.GetDalamudObject(0);
if (player == null)
if (_player is null)
return false;
var gameObject = (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)character.Address;
@ -28,27 +29,26 @@ internal readonly struct TreeBuildCache(ObjectManager objects, IDataManager data
return actualIndex switch
{
< 2 => true,
< (int)ScreenActor.CutsceneStart => gameObject->OwnerId == player.EntityId,
< (int)ScreenActor.CutsceneStart => gameObject->OwnerId == _player.EntityId,
_ => false,
};
}
public IEnumerable<ICharacter> GetCharacters()
=> objects.Objects.OfType<ICharacter>();
=> objects is not null ? objects.Objects.OfType<ICharacter>() : [];
public IEnumerable<ICharacter> GetLocalPlayerRelatedCharacters()
{
var player = objects.GetDalamudObject(0);
if (player == null)
if (_player is null)
yield break;
yield return (ICharacter)player;
yield return (ICharacter)_player;
var minion = objects.GetDalamudObject(1);
if (minion != null)
var minion = objects!.GetDalamudObject(1);
if (minion is not null)
yield return (ICharacter)minion;
var playerId = player.EntityId;
var playerId = _player.EntityId;
for (var i = 2; i < ObjectIndex.CutsceneStart.Index; i += 2)
{
if (objects.GetDalamudObject(i) is ICharacter owned && owned.OwnerId == playerId)