From 73af509885d1aa69086798bd35daff19384dd524 Mon Sep 17 00:00:00 2001 From: Asriel Camora Date: Tue, 28 Nov 2023 10:28:37 -0800 Subject: [PATCH 1/6] Add GetGameObjectResourceTrees ipc method --- Penumbra.Api | 2 +- Penumbra/Api/PenumbraApi.cs | 9 +++++ Penumbra/Api/PenumbraIpcProviders.cs | 3 ++ .../ResourceTree/ResourceTreeApiHelper.cs | 35 +++++++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/Penumbra.Api b/Penumbra.Api index 80f9793e..3f3af19d 160000 --- a/Penumbra.Api +++ b/Penumbra.Api @@ -1 +1 @@ -Subproject commit 80f9793ef2ddaa50246b7112fde4d9b2098d8823 +Subproject commit 3f3af19d11ec4d7a83ee6c17810eb55ec4237675 diff --git a/Penumbra/Api/PenumbraApi.cs b/Penumbra/Api/PenumbraApi.cs index 0ae4fcca..7b2e09d0 100644 --- a/Penumbra/Api/PenumbraApi.cs +++ b/Penumbra/Api/PenumbraApi.cs @@ -1075,6 +1075,15 @@ public class PenumbraApi : IDisposable, IPenumbraApi return resDictionaries.AsReadOnly(); } + public IEnumerable?[] GetGameObjectResourceTrees(bool withUIData, params ushort[] gameObjects) + { + var characters = gameObjects.Select(index => _dalamud.Objects[index]).OfType(); + var resourceTrees = _resourceTreeFactory.FromCharacters(characters, withUIData ? ResourceTreeFactory.Flags.WithUiData : 0); + var resDictionary = ResourceTreeApiHelper.EncapsulateResourceTrees(resourceTrees); + + return Array.ConvertAll(gameObjects, obj => resDictionary.TryGetValue(obj, out var nodes) ? nodes : null); + } + // TODO: cleanup when incrementing API public string GetMetaManipulations(string characterName) diff --git a/Penumbra/Api/PenumbraIpcProviders.cs b/Penumbra/Api/PenumbraIpcProviders.cs index b72073fb..289fc38b 100644 --- a/Penumbra/Api/PenumbraIpcProviders.cs +++ b/Penumbra/Api/PenumbraIpcProviders.cs @@ -130,6 +130,8 @@ public class PenumbraIpcProviders : IDisposable FuncProvider>> GetPlayerResourcesOfType; + internal readonly FuncProvider?[]> GetGameObjectResourceTrees; + public PenumbraIpcProviders(DalamudServices dalamud, IPenumbraApi api, ModManager modManager, CollectionManager collections, TempModManager tempMods, TempCollectionManager tempCollections, SaveService saveService, Configuration config) { @@ -254,6 +256,7 @@ public class PenumbraIpcProviders : IDisposable GetPlayerResourcePaths = Ipc.GetPlayerResourcePaths.Provider(pi, Api.GetPlayerResourcePaths); GetGameObjectResourcesOfType = Ipc.GetGameObjectResourcesOfType.Provider(pi, Api.GetGameObjectResourcesOfType); GetPlayerResourcesOfType = Ipc.GetPlayerResourcesOfType.Provider(pi, Api.GetPlayerResourcesOfType); + GetGameObjectResourceTrees = Ipc.GetGameObjectResourceTrees.Provider(pi, Api.GetGameObjectResourceTrees); Tester = new IpcTester(config, dalamud, this, modManager, collections, tempMods, tempCollections, saveService); diff --git a/Penumbra/Interop/ResourceTree/ResourceTreeApiHelper.cs b/Penumbra/Interop/ResourceTree/ResourceTreeApiHelper.cs index 6c1e4d1e..3df47086 100644 --- a/Penumbra/Interop/ResourceTree/ResourceTreeApiHelper.cs +++ b/Penumbra/Interop/ResourceTree/ResourceTreeApiHelper.cs @@ -1,5 +1,7 @@ using Dalamud.Game.ClientState.Objects.Types; +using Penumbra.Api; using Penumbra.Api.Enums; +using Penumbra.String.Classes; using Penumbra.UI; namespace Penumbra.Interop.ResourceTree; @@ -71,4 +73,37 @@ internal static class ResourceTreeApiHelper return resDictionaries.ToDictionary(pair => pair.Key, pair => (IReadOnlyDictionary)pair.Value.AsReadOnly()); } + + public static Dictionary> EncapsulateResourceTrees(IEnumerable<(Character, ResourceTree)> resourceTrees) + { + static Ipc.ResourceNode GetIpcNode(ResourceNode[] tree, ResourceNode node) => + new() + { + ChildrenIndices = node.Children.Select(c => Array.IndexOf(tree, c)).ToArray(), + Type = node.Type, + Icon = ChangedItemDrawer.ToApiIcon(node.Icon), + Name = node.Name, + GamePath = node.GamePath.Equals(Utf8GamePath.Empty) ? null : node.GamePath.ToString(), + ActualPath = node.FullPath.ToString(), + ObjectAddress = node.ObjectAddress, + ResourceHandle = node.ResourceHandle, + }; + + static IEnumerable GetIpcNodes(ResourceTree tree) + { + var nodes = tree.FlatNodes.ToArray(); + return nodes.Select(n => GetIpcNode(nodes, n)).ToArray(); + } + + var resDictionary = new Dictionary>(4); + foreach (var (gameObject, resourceTree) in resourceTrees) + { + if (resDictionary.ContainsKey(gameObject.ObjectIndex)) + continue; + + resDictionary.Add(gameObject.ObjectIndex, GetIpcNodes(resourceTree)); + } + + return resDictionary; + } } From 0f03e0484c33ee9c87d239c8f1fa097b43e2bdda Mon Sep 17 00:00:00 2001 From: Asriel Camora Date: Tue, 28 Nov 2023 10:46:03 -0800 Subject: [PATCH 2/6] Add ipc GetPlayerResourceTrees, change ipc resource node to be nested --- Penumbra.Api | 2 +- Penumbra/Api/PenumbraApi.cs | 8 ++++++++ Penumbra/Api/PenumbraIpcProviders.cs | 4 +++- .../Interop/ResourceTree/ResourceTreeApiHelper.cs | 11 ++++------- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/Penumbra.Api b/Penumbra.Api index 3f3af19d..1fa1839a 160000 --- a/Penumbra.Api +++ b/Penumbra.Api @@ -1 +1 @@ -Subproject commit 3f3af19d11ec4d7a83ee6c17810eb55ec4237675 +Subproject commit 1fa1839aef7ddd4a90f53e9642403f950579c2eb diff --git a/Penumbra/Api/PenumbraApi.cs b/Penumbra/Api/PenumbraApi.cs index 7b2e09d0..1e79099c 100644 --- a/Penumbra/Api/PenumbraApi.cs +++ b/Penumbra/Api/PenumbraApi.cs @@ -1084,6 +1084,14 @@ public class PenumbraApi : IDisposable, IPenumbraApi return Array.ConvertAll(gameObjects, obj => resDictionary.TryGetValue(obj, out var nodes) ? nodes : null); } + public IReadOnlyDictionary> GetPlayerResourceTrees(bool withUIData) + { + var resourceTrees = _resourceTreeFactory.FromObjectTable(ResourceTreeFactory.Flags.LocalPlayerRelatedOnly + | (withUIData ? ResourceTreeFactory.Flags.WithUiData : 0)); + var resDictionary = ResourceTreeApiHelper.EncapsulateResourceTrees(resourceTrees); + + return resDictionary.AsReadOnly(); + } // TODO: cleanup when incrementing API public string GetMetaManipulations(string characterName) diff --git a/Penumbra/Api/PenumbraIpcProviders.cs b/Penumbra/Api/PenumbraIpcProviders.cs index 289fc38b..9f1e79b9 100644 --- a/Penumbra/Api/PenumbraIpcProviders.cs +++ b/Penumbra/Api/PenumbraIpcProviders.cs @@ -131,6 +131,7 @@ public class PenumbraIpcProviders : IDisposable GetPlayerResourcesOfType; internal readonly FuncProvider?[]> GetGameObjectResourceTrees; + internal readonly FuncProvider>> GetPlayerResourceTrees; public PenumbraIpcProviders(DalamudServices dalamud, IPenumbraApi api, ModManager modManager, CollectionManager collections, TempModManager tempMods, TempCollectionManager tempCollections, SaveService saveService, Configuration config) @@ -256,7 +257,8 @@ public class PenumbraIpcProviders : IDisposable GetPlayerResourcePaths = Ipc.GetPlayerResourcePaths.Provider(pi, Api.GetPlayerResourcePaths); GetGameObjectResourcesOfType = Ipc.GetGameObjectResourcesOfType.Provider(pi, Api.GetGameObjectResourcesOfType); GetPlayerResourcesOfType = Ipc.GetPlayerResourcesOfType.Provider(pi, Api.GetPlayerResourcesOfType); - GetGameObjectResourceTrees = Ipc.GetGameObjectResourceTrees.Provider(pi, Api.GetGameObjectResourceTrees); + GetGameObjectResourceTrees = Ipc.GetGameObjectResourceTrees.Provider(pi, Api.GetGameObjectResourceTrees); + GetPlayerResourceTrees = Ipc.GetPlayerResourceTrees.Provider(pi, Api.GetPlayerResourceTrees); Tester = new IpcTester(config, dalamud, this, modManager, collections, tempMods, tempCollections, saveService); diff --git a/Penumbra/Interop/ResourceTree/ResourceTreeApiHelper.cs b/Penumbra/Interop/ResourceTree/ResourceTreeApiHelper.cs index 3df47086..02e0f380 100644 --- a/Penumbra/Interop/ResourceTree/ResourceTreeApiHelper.cs +++ b/Penumbra/Interop/ResourceTree/ResourceTreeApiHelper.cs @@ -76,10 +76,9 @@ internal static class ResourceTreeApiHelper public static Dictionary> EncapsulateResourceTrees(IEnumerable<(Character, ResourceTree)> resourceTrees) { - static Ipc.ResourceNode GetIpcNode(ResourceNode[] tree, ResourceNode node) => + static Ipc.ResourceNode GetIpcNode(ResourceNode node) => new() { - ChildrenIndices = node.Children.Select(c => Array.IndexOf(tree, c)).ToArray(), Type = node.Type, Icon = ChangedItemDrawer.ToApiIcon(node.Icon), Name = node.Name, @@ -87,13 +86,11 @@ internal static class ResourceTreeApiHelper ActualPath = node.FullPath.ToString(), ObjectAddress = node.ObjectAddress, ResourceHandle = node.ResourceHandle, + Children = node.Children.Select(GetIpcNode).ToArray(), }; - static IEnumerable GetIpcNodes(ResourceTree tree) - { - var nodes = tree.FlatNodes.ToArray(); - return nodes.Select(n => GetIpcNode(nodes, n)).ToArray(); - } + static IEnumerable GetIpcNodes(ResourceTree tree) => + tree.Nodes.Select(GetIpcNode).ToArray(); var resDictionary = new Dictionary>(4); foreach (var (gameObject, resourceTree) in resourceTrees) From d647a62e82fef780cfe36a63d457d260937475e8 Mon Sep 17 00:00:00 2001 From: Asriel Camora Date: Tue, 28 Nov 2023 12:33:19 -0800 Subject: [PATCH 3/6] Add ResourceTree ipc structure --- Penumbra.Api | 2 +- Penumbra/Api/PenumbraApi.cs | 4 ++-- Penumbra/Api/PenumbraIpcProviders.cs | 4 ++-- .../Interop/ResourceTree/ResourceTreeApiHelper.cs | 15 ++++++++++----- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/Penumbra.Api b/Penumbra.Api index 1fa1839a..3567cf22 160000 --- a/Penumbra.Api +++ b/Penumbra.Api @@ -1 +1 @@ -Subproject commit 1fa1839aef7ddd4a90f53e9642403f950579c2eb +Subproject commit 3567cf225b469dd5bb5f723e96e2abaaa4d16a1c diff --git a/Penumbra/Api/PenumbraApi.cs b/Penumbra/Api/PenumbraApi.cs index 1e79099c..8974e823 100644 --- a/Penumbra/Api/PenumbraApi.cs +++ b/Penumbra/Api/PenumbraApi.cs @@ -1075,7 +1075,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi return resDictionaries.AsReadOnly(); } - public IEnumerable?[] GetGameObjectResourceTrees(bool withUIData, params ushort[] gameObjects) + public Ipc.ResourceTree?[] GetGameObjectResourceTrees(bool withUIData, params ushort[] gameObjects) { var characters = gameObjects.Select(index => _dalamud.Objects[index]).OfType(); var resourceTrees = _resourceTreeFactory.FromCharacters(characters, withUIData ? ResourceTreeFactory.Flags.WithUiData : 0); @@ -1084,7 +1084,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi return Array.ConvertAll(gameObjects, obj => resDictionary.TryGetValue(obj, out var nodes) ? nodes : null); } - public IReadOnlyDictionary> GetPlayerResourceTrees(bool withUIData) + public IReadOnlyDictionary GetPlayerResourceTrees(bool withUIData) { var resourceTrees = _resourceTreeFactory.FromObjectTable(ResourceTreeFactory.Flags.LocalPlayerRelatedOnly | (withUIData ? ResourceTreeFactory.Flags.WithUiData : 0)); diff --git a/Penumbra/Api/PenumbraIpcProviders.cs b/Penumbra/Api/PenumbraIpcProviders.cs index 9f1e79b9..10980f98 100644 --- a/Penumbra/Api/PenumbraIpcProviders.cs +++ b/Penumbra/Api/PenumbraIpcProviders.cs @@ -130,8 +130,8 @@ public class PenumbraIpcProviders : IDisposable FuncProvider>> GetPlayerResourcesOfType; - internal readonly FuncProvider?[]> GetGameObjectResourceTrees; - internal readonly FuncProvider>> GetPlayerResourceTrees; + internal readonly FuncProvider GetGameObjectResourceTrees; + internal readonly FuncProvider> GetPlayerResourceTrees; public PenumbraIpcProviders(DalamudServices dalamud, IPenumbraApi api, ModManager modManager, CollectionManager collections, TempModManager tempMods, TempCollectionManager tempCollections, SaveService saveService, Configuration config) diff --git a/Penumbra/Interop/ResourceTree/ResourceTreeApiHelper.cs b/Penumbra/Interop/ResourceTree/ResourceTreeApiHelper.cs index 02e0f380..df34c51a 100644 --- a/Penumbra/Interop/ResourceTree/ResourceTreeApiHelper.cs +++ b/Penumbra/Interop/ResourceTree/ResourceTreeApiHelper.cs @@ -74,7 +74,7 @@ internal static class ResourceTreeApiHelper pair => (IReadOnlyDictionary)pair.Value.AsReadOnly()); } - public static Dictionary> EncapsulateResourceTrees(IEnumerable<(Character, ResourceTree)> resourceTrees) + public static Dictionary EncapsulateResourceTrees(IEnumerable<(Character, ResourceTree)> resourceTrees) { static Ipc.ResourceNode GetIpcNode(ResourceNode node) => new() @@ -89,16 +89,21 @@ internal static class ResourceTreeApiHelper Children = node.Children.Select(GetIpcNode).ToArray(), }; - static IEnumerable GetIpcNodes(ResourceTree tree) => - tree.Nodes.Select(GetIpcNode).ToArray(); + static Ipc.ResourceTree GetIpcTree(ResourceTree tree) => + new() + { + Name = tree.Name, + RaceCode = (ushort)tree.RaceCode, + Nodes = tree.Nodes.Select(GetIpcNode).ToArray(), + }; - var resDictionary = new Dictionary>(4); + var resDictionary = new Dictionary(4); foreach (var (gameObject, resourceTree) in resourceTrees) { if (resDictionary.ContainsKey(gameObject.ObjectIndex)) continue; - resDictionary.Add(gameObject.ObjectIndex, GetIpcNodes(resourceTree)); + resDictionary.Add(gameObject.ObjectIndex, GetIpcTree(resourceTree)); } return resDictionary; From bb3d3657ed7d487acb4e575a6f91b76051bfef00 Mon Sep 17 00:00:00 2001 From: Asriel Camora Date: Tue, 28 Nov 2023 12:33:37 -0800 Subject: [PATCH 4/6] Add ResourceTree ipc tests --- Penumbra/Api/IpcTester.cs | 103 +++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/Penumbra/Api/IpcTester.cs b/Penumbra/Api/IpcTester.cs index 675a61a3..f7b740b9 100644 --- a/Penumbra/Api/IpcTester.cs +++ b/Penumbra/Api/IpcTester.cs @@ -16,8 +16,8 @@ using Penumbra.Services; using Penumbra.UI; using Penumbra.Collections.Manager; using Dalamud.Plugin.Services; -using ImGuiScene; using Penumbra.GameData.Structs; +using Penumbra.GameData.Enums; namespace Penumbra.Api; @@ -1437,6 +1437,8 @@ public class IpcTester : IDisposable private (string, IReadOnlyDictionary?)[]? _lastPlayerResourcePaths; private (string, IReadOnlyDictionary?)[]? _lastGameObjectResourcesOfType; private (string, IReadOnlyDictionary?)[]? _lastPlayerResourcesOfType; + private (string, Ipc.ResourceTree?)[]? _lastGameObjectResourceTrees; + private (string, Ipc.ResourceTree)[]? _lastPlayerResourceTrees; private TimeSpan _lastCallDuration; public ResourceTree(DalamudPluginInterface pi, IObjectTable objects) @@ -1523,11 +1525,46 @@ public class IpcTester : IDisposable ImGui.OpenPopup(nameof(Ipc.GetPlayerResourcesOfType)); } + DrawIntro(Ipc.GetGameObjectResourceTrees.Label, "Get GameObject resource trees"); + if (ImGui.Button("Get##GameObjectResourceTrees")) + { + var gameObjects = GetSelectedGameObjects(); + var subscriber = Ipc.GetGameObjectResourceTrees.Subscriber(_pi); + _stopwatch.Restart(); + var trees = subscriber.Invoke(_withUIData, gameObjects); + + _lastCallDuration = _stopwatch.Elapsed; + _lastGameObjectResourceTrees = gameObjects + .Select(i => GameObjectToString(i)) + .Zip(trees) + .ToArray(); + + ImGui.OpenPopup(nameof(Ipc.GetGameObjectResourceTrees)); + } + + DrawIntro(Ipc.GetPlayerResourceTrees.Label, "Get local player resource trees"); + if (ImGui.Button("Get##PlayerResourceTrees")) + { + var subscriber = Ipc.GetPlayerResourceTrees.Subscriber(_pi); + _stopwatch.Restart(); + var trees = subscriber.Invoke(_withUIData); + + _lastCallDuration = _stopwatch.Elapsed; + _lastPlayerResourceTrees = trees + .Select(pair => (GameObjectToString(pair.Key), pair.Value)) + .ToArray(); + + ImGui.OpenPopup(nameof(Ipc.GetPlayerResourceTrees)); + } + DrawPopup(nameof(Ipc.GetGameObjectResourcePaths), ref _lastGameObjectResourcePaths, DrawResourcePaths, _lastCallDuration); DrawPopup(nameof(Ipc.GetPlayerResourcePaths), ref _lastPlayerResourcePaths, DrawResourcePaths, _lastCallDuration); DrawPopup(nameof(Ipc.GetGameObjectResourcesOfType), ref _lastGameObjectResourcesOfType, DrawResourcesOfType, _lastCallDuration); DrawPopup(nameof(Ipc.GetPlayerResourcesOfType), ref _lastPlayerResourcesOfType, DrawResourcesOfType, _lastCallDuration); + + DrawPopup(nameof(Ipc.GetGameObjectResourceTrees), ref _lastGameObjectResourceTrees, DrawResourceTrees, _lastCallDuration); + DrawPopup(nameof(Ipc.GetPlayerResourceTrees), ref _lastPlayerResourceTrees, DrawResourceTrees!, _lastCallDuration); } private static void DrawPopup(string popupId, ref T? result, Action drawResult, TimeSpan duration) where T : class @@ -1638,6 +1675,70 @@ public class IpcTester : IDisposable }); } + private void DrawResourceTrees((string, Ipc.ResourceTree?)[] result) + { + DrawWithHeaders(result, tree => + { + ImGui.TextUnformatted($"Name: {tree.Name}\nRaceCode: {(GenderRace)tree.RaceCode}"); + + using var table = ImRaii.Table(string.Empty, _withUIData ? 7 : 5, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.Resizable); + if (!table) + return; + + if (_withUIData) + { + ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthStretch, 0.5f); + ImGui.TableSetupColumn("Type", ImGuiTableColumnFlags.WidthStretch, 0.1f); + ImGui.TableSetupColumn("Icon", ImGuiTableColumnFlags.WidthStretch, 0.15f); + } + else + { + ImGui.TableSetupColumn("Type", ImGuiTableColumnFlags.WidthStretch, 0.5f); + } + ImGui.TableSetupColumn("Game Path", ImGuiTableColumnFlags.WidthStretch, 0.5f); + ImGui.TableSetupColumn("Actual Path", ImGuiTableColumnFlags.WidthStretch, 0.5f); + ImGui.TableSetupColumn("Object Address", ImGuiTableColumnFlags.WidthStretch, 0.2f); + ImGui.TableSetupColumn("Resource Handle", ImGuiTableColumnFlags.WidthStretch, 0.2f); + ImGui.TableHeadersRow(); + + void DrawNode(Ipc.ResourceNode node) + { + ImGui.TableNextRow(); + ImGui.TableNextColumn(); + var hasChildren = node.Children.Any(); + using var treeNode = ImRaii.TreeNode( + $"{(_withUIData ? (node.Name ?? "Unknown") : node.Type)}##{node.ObjectAddress:X8}", + hasChildren ? + ImGuiTreeNodeFlags.SpanFullWidth : + (ImGuiTreeNodeFlags.SpanFullWidth | ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.NoTreePushOnOpen)); + if (_withUIData) + { + ImGui.TableNextColumn(); + TextUnformattedMono(node.Type.ToString()); + ImGui.TableNextColumn(); + TextUnformattedMono(node.Icon.ToString()); + } + ImGui.TableNextColumn(); + ImGui.TextUnformatted(node.GamePath ?? "Unknown"); + ImGui.TableNextColumn(); + ImGui.TextUnformatted(node.ActualPath); + ImGui.TableNextColumn(); + TextUnformattedMono($"0x{node.ObjectAddress:X8}"); + ImGui.TableNextColumn(); + TextUnformattedMono($"0x{node.ResourceHandle:X8}"); + + if (treeNode) + { + foreach (var child in node.Children) + DrawNode(child); + } + } + + foreach (var node in tree.Nodes) + DrawNode(node); + }); + } + private static void TextUnformattedMono(string text) { using var _ = ImRaii.PushFont(UiBuilder.MonoFont); From eb0e334437e07c276c72bf0bab9aa7b758054b20 Mon Sep 17 00:00:00 2001 From: Asriel Camora Date: Thu, 30 Nov 2023 09:53:16 -0800 Subject: [PATCH 5/6] Add ResourceTree ipc disposes --- Penumbra/Api/PenumbraIpcProviders.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Penumbra/Api/PenumbraIpcProviders.cs b/Penumbra/Api/PenumbraIpcProviders.cs index 10980f98..a564588b 100644 --- a/Penumbra/Api/PenumbraIpcProviders.cs +++ b/Penumbra/Api/PenumbraIpcProviders.cs @@ -375,6 +375,8 @@ public class PenumbraIpcProviders : IDisposable GetPlayerResourcePaths.Dispose(); GetGameObjectResourcesOfType.Dispose(); GetPlayerResourcesOfType.Dispose(); + GetGameObjectResourceTrees.Dispose(); + GetPlayerResourceTrees.Dispose(); Disposed.Invoke(); Disposed.Dispose(); From b595a0da0ff0ceb81e428b87518b2ab487293bf7 Mon Sep 17 00:00:00 2001 From: Asriel Camora Date: Thu, 30 Nov 2023 10:01:49 -0800 Subject: [PATCH 6/6] Replace ResourceTree IEnumerables with lists --- Penumbra.Api | 2 +- Penumbra/Interop/ResourceTree/ResourceTreeApiHelper.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Penumbra.Api b/Penumbra.Api index 3567cf22..e2f578a9 160000 --- a/Penumbra.Api +++ b/Penumbra.Api @@ -1 +1 @@ -Subproject commit 3567cf225b469dd5bb5f723e96e2abaaa4d16a1c +Subproject commit e2f578a903f4e2de6c5967eb92f1b5a0a413d287 diff --git a/Penumbra/Interop/ResourceTree/ResourceTreeApiHelper.cs b/Penumbra/Interop/ResourceTree/ResourceTreeApiHelper.cs index df34c51a..386caf9d 100644 --- a/Penumbra/Interop/ResourceTree/ResourceTreeApiHelper.cs +++ b/Penumbra/Interop/ResourceTree/ResourceTreeApiHelper.cs @@ -86,7 +86,7 @@ internal static class ResourceTreeApiHelper ActualPath = node.FullPath.ToString(), ObjectAddress = node.ObjectAddress, ResourceHandle = node.ResourceHandle, - Children = node.Children.Select(GetIpcNode).ToArray(), + Children = node.Children.Select(GetIpcNode).ToList(), }; static Ipc.ResourceTree GetIpcTree(ResourceTree tree) => @@ -94,7 +94,7 @@ internal static class ResourceTreeApiHelper { Name = tree.Name, RaceCode = (ushort)tree.RaceCode, - Nodes = tree.Nodes.Select(GetIpcNode).ToArray(), + Nodes = tree.Nodes.Select(GetIpcNode).ToList(), }; var resDictionary = new Dictionary(4);