mirror of
https://github.com/xivdev/Penumbra.git
synced 2026-02-02 14:04:37 +01:00
Track CollectionCache ResolvedFiles
This commit is contained in:
parent
13500264b7
commit
2b60f204e8
9 changed files with 198 additions and 75 deletions
|
|
@ -2,14 +2,37 @@ using OtterGui.Services;
|
|||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Collections;
|
||||
using Penumbra.Collections.Manager;
|
||||
using Penumbra.Communication;
|
||||
using Penumbra.Mods;
|
||||
using Penumbra.Mods.Editor;
|
||||
using Penumbra.Services;
|
||||
using Penumbra.String.Classes;
|
||||
|
||||
namespace Penumbra.Api.Api;
|
||||
|
||||
public class CollectionApi(CollectionManager collections, ApiHelpers helpers) : IPenumbraApiCollection, IApiService
|
||||
public class CollectionApi : IPenumbraApiCollection, IApiService, IDisposable
|
||||
{
|
||||
private readonly CollectionManager _collections;
|
||||
private readonly ApiHelpers _helpers;
|
||||
private readonly CommunicatorService _communicator;
|
||||
|
||||
public CollectionApi(CollectionManager collections, ApiHelpers helpers, CommunicatorService communicator)
|
||||
{
|
||||
_collections = collections;
|
||||
_helpers = helpers;
|
||||
_communicator = communicator;
|
||||
_communicator.ResolvedFileChanged.Subscribe(OnResolvedFileChange, Communication.ResolvedFileChanged.Priority.ApiResolvedFile);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_communicator.ResolvedFileChanged.Unsubscribe(OnResolvedFileChange);
|
||||
}
|
||||
|
||||
public event ResolvedFileChangedDelegate? ResolvedFileChanged;
|
||||
|
||||
public Dictionary<Guid, string> GetCollections()
|
||||
=> collections.Storage.ToDictionary(c => c.Identity.Id, c => c.Identity.Name);
|
||||
=> _collections.Storage.ToDictionary(c => c.Identity.Id, c => c.Identity.Name);
|
||||
|
||||
public List<(Guid Id, string Name)> GetCollectionsByIdentifier(string identifier)
|
||||
{
|
||||
|
|
@ -17,13 +40,13 @@ public class CollectionApi(CollectionManager collections, ApiHelpers helpers) :
|
|||
return [];
|
||||
|
||||
var list = new List<(Guid Id, string Name)>(4);
|
||||
if (Guid.TryParse(identifier, out var guid) && collections.Storage.ById(guid, out var collection) && collection != ModCollection.Empty)
|
||||
if (Guid.TryParse(identifier, out var guid) && _collections.Storage.ById(guid, out var collection) && collection != ModCollection.Empty)
|
||||
list.Add((collection.Identity.Id, collection.Identity.Name));
|
||||
else if (identifier.Length >= 8)
|
||||
list.AddRange(collections.Storage.Where(c => c.Identity.Identifier.StartsWith(identifier, StringComparison.OrdinalIgnoreCase))
|
||||
list.AddRange(_collections.Storage.Where(c => c.Identity.Identifier.StartsWith(identifier, StringComparison.OrdinalIgnoreCase))
|
||||
.Select(c => (c.Identity.Id, c.Identity.Name)));
|
||||
|
||||
list.AddRange(collections.Storage
|
||||
list.AddRange(_collections.Storage
|
||||
.Where(c => string.Equals(c.Identity.Name, identifier, StringComparison.OrdinalIgnoreCase)
|
||||
&& !list.Contains((c.Identity.Id, c.Identity.Name)))
|
||||
.Select(c => (c.Identity.Id, c.Identity.Name)));
|
||||
|
|
@ -32,7 +55,7 @@ public class CollectionApi(CollectionManager collections, ApiHelpers helpers) :
|
|||
|
||||
public Func<string, (string ModDirectory, string ModName)[]> CheckCurrentChangedItemFunc()
|
||||
{
|
||||
var weakRef = new WeakReference<CollectionManager>(collections);
|
||||
var weakRef = new WeakReference<CollectionManager>(_collections);
|
||||
return s =>
|
||||
{
|
||||
if (!weakRef.TryGetTarget(out var c))
|
||||
|
|
@ -45,11 +68,31 @@ public class CollectionApi(CollectionManager collections, ApiHelpers helpers) :
|
|||
};
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetResolvedFilesForCollection(Guid collectionId)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_collections.Storage.ById(collectionId, out var collection))
|
||||
collection = ModCollection.Empty;
|
||||
|
||||
if (collection.HasCache)
|
||||
return collection.ResolvedFiles.ToDictionary(kvp => kvp.Key.ToString(), kvp => kvp.Value.Path.ToString());
|
||||
|
||||
Penumbra.Log.Warning($"Collection {collectionId} does not exist or is not loaded.");
|
||||
return [];
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Penumbra.Log.Error($"Could not obtain Resolved Files for {collectionId}:\n{e}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<string, object?> GetChangedItemsForCollection(Guid collectionId)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!collections.Storage.ById(collectionId, out var collection))
|
||||
if (!_collections.Storage.ById(collectionId, out var collection))
|
||||
collection = ModCollection.Empty;
|
||||
|
||||
if (collection.HasCache)
|
||||
|
|
@ -70,7 +113,7 @@ public class CollectionApi(CollectionManager collections, ApiHelpers helpers) :
|
|||
if (!Enum.IsDefined(type))
|
||||
return null;
|
||||
|
||||
var collection = collections.Active.ByType((CollectionType)type);
|
||||
var collection = _collections.Active.ByType((CollectionType)type);
|
||||
return collection == null ? null : (collection.Identity.Id, collection.Identity.Name);
|
||||
}
|
||||
|
||||
|
|
@ -79,19 +122,19 @@ public class CollectionApi(CollectionManager collections, ApiHelpers helpers) :
|
|||
|
||||
public (bool ObjectValid, bool IndividualSet, (Guid Id, string Name) EffectiveCollection) GetCollectionForObject(int gameObjectIdx)
|
||||
{
|
||||
var id = helpers.AssociatedIdentifier(gameObjectIdx);
|
||||
var id = _helpers.AssociatedIdentifier(gameObjectIdx);
|
||||
if (!id.IsValid)
|
||||
return (false, false, (collections.Active.Default.Identity.Id, collections.Active.Default.Identity.Name));
|
||||
return (false, false, (_collections.Active.Default.Identity.Id, _collections.Active.Default.Identity.Name));
|
||||
|
||||
if (collections.Active.Individuals.TryGetValue(id, out var collection))
|
||||
if (_collections.Active.Individuals.TryGetValue(id, out var collection))
|
||||
return (true, true, (collection.Identity.Id, collection.Identity.Name));
|
||||
|
||||
helpers.AssociatedCollection(gameObjectIdx, out collection);
|
||||
_helpers.AssociatedCollection(gameObjectIdx, out collection);
|
||||
return (true, false, (collection.Identity.Id, collection.Identity.Name));
|
||||
}
|
||||
|
||||
public Guid[] GetCollectionByName(string name)
|
||||
=> collections.Storage.Where(c => string.Equals(name, c.Identity.Name, StringComparison.OrdinalIgnoreCase)).Select(c => c.Identity.Id)
|
||||
=> _collections.Storage.Where(c => string.Equals(name, c.Identity.Name, StringComparison.OrdinalIgnoreCase)).Select(c => c.Identity.Id)
|
||||
.ToArray();
|
||||
|
||||
public (PenumbraApiEc, (Guid Id, string Name)? OldCollection) SetCollection(ApiCollectionType type, Guid? collectionId,
|
||||
|
|
@ -100,7 +143,7 @@ public class CollectionApi(CollectionManager collections, ApiHelpers helpers) :
|
|||
if (!Enum.IsDefined(type))
|
||||
return (PenumbraApiEc.InvalidArgument, null);
|
||||
|
||||
var oldCollection = collections.Active.ByType((CollectionType)type);
|
||||
var oldCollection = _collections.Active.ByType((CollectionType)type);
|
||||
var old = oldCollection != null ? (oldCollection.Identity.Id, oldCollection.Identity.Name) : new ValueTuple<Guid, string>?();
|
||||
if (collectionId == null)
|
||||
{
|
||||
|
|
@ -110,11 +153,11 @@ public class CollectionApi(CollectionManager collections, ApiHelpers helpers) :
|
|||
if (!allowDelete || type is ApiCollectionType.Current or ApiCollectionType.Default or ApiCollectionType.Interface)
|
||||
return (PenumbraApiEc.AssignmentDeletionDisallowed, old);
|
||||
|
||||
collections.Active.RemoveSpecialCollection((CollectionType)type);
|
||||
_collections.Active.RemoveSpecialCollection((CollectionType)type);
|
||||
return (PenumbraApiEc.Success, old);
|
||||
}
|
||||
|
||||
if (!collections.Storage.ById(collectionId.Value, out var collection))
|
||||
if (!_collections.Storage.ById(collectionId.Value, out var collection))
|
||||
return (PenumbraApiEc.CollectionMissing, old);
|
||||
|
||||
if (old == null)
|
||||
|
|
@ -122,25 +165,25 @@ public class CollectionApi(CollectionManager collections, ApiHelpers helpers) :
|
|||
if (!allowCreateNew)
|
||||
return (PenumbraApiEc.AssignmentCreationDisallowed, old);
|
||||
|
||||
collections.Active.CreateSpecialCollection((CollectionType)type);
|
||||
_collections.Active.CreateSpecialCollection((CollectionType)type);
|
||||
}
|
||||
else if (old.Value.Item1 == collection.Identity.Id)
|
||||
{
|
||||
return (PenumbraApiEc.NothingChanged, old);
|
||||
}
|
||||
|
||||
collections.Active.SetCollection(collection, (CollectionType)type);
|
||||
_collections.Active.SetCollection(collection, (CollectionType)type);
|
||||
return (PenumbraApiEc.Success, old);
|
||||
}
|
||||
|
||||
public (PenumbraApiEc, (Guid Id, string Name)? OldCollection) SetCollectionForObject(int gameObjectIdx, Guid? collectionId,
|
||||
bool allowCreateNew, bool allowDelete)
|
||||
{
|
||||
var id = helpers.AssociatedIdentifier(gameObjectIdx);
|
||||
var id = _helpers.AssociatedIdentifier(gameObjectIdx);
|
||||
if (!id.IsValid)
|
||||
return (PenumbraApiEc.InvalidIdentifier, (collections.Active.Default.Identity.Id, collections.Active.Default.Identity.Name));
|
||||
return (PenumbraApiEc.InvalidIdentifier, (_collections.Active.Default.Identity.Id, _collections.Active.Default.Identity.Name));
|
||||
|
||||
var oldCollection = collections.Active.Individuals.TryGetValue(id, out var c) ? c : null;
|
||||
var oldCollection = _collections.Active.Individuals.TryGetValue(id, out var c) ? c : null;
|
||||
var old = oldCollection != null ? (oldCollection.Identity.Id, oldCollection.Identity.Name) : new ValueTuple<Guid, string>?();
|
||||
if (collectionId == null)
|
||||
{
|
||||
|
|
@ -150,12 +193,12 @@ public class CollectionApi(CollectionManager collections, ApiHelpers helpers) :
|
|||
if (!allowDelete)
|
||||
return (PenumbraApiEc.AssignmentDeletionDisallowed, old);
|
||||
|
||||
var idx = collections.Active.Individuals.Index(id);
|
||||
collections.Active.RemoveIndividualCollection(idx);
|
||||
var idx = _collections.Active.Individuals.Index(id);
|
||||
_collections.Active.RemoveIndividualCollection(idx);
|
||||
return (PenumbraApiEc.Success, old);
|
||||
}
|
||||
|
||||
if (!collections.Storage.ById(collectionId.Value, out var collection))
|
||||
if (!_collections.Storage.ById(collectionId.Value, out var collection))
|
||||
return (PenumbraApiEc.CollectionMissing, old);
|
||||
|
||||
if (old == null)
|
||||
|
|
@ -163,15 +206,21 @@ public class CollectionApi(CollectionManager collections, ApiHelpers helpers) :
|
|||
if (!allowCreateNew)
|
||||
return (PenumbraApiEc.AssignmentCreationDisallowed, old);
|
||||
|
||||
var ids = collections.Active.Individuals.GetGroup(id);
|
||||
collections.Active.CreateIndividualCollection(ids);
|
||||
var ids = _collections.Active.Individuals.GetGroup(id);
|
||||
_collections.Active.CreateIndividualCollection(ids);
|
||||
}
|
||||
else if (old.Value.Item1 == collection.Identity.Id)
|
||||
{
|
||||
return (PenumbraApiEc.NothingChanged, old);
|
||||
}
|
||||
|
||||
collections.Active.SetCollection(collection, CollectionType.Individual, collections.Active.Individuals.Index(id));
|
||||
_collections.Active.SetCollection(collection, CollectionType.Individual, _collections.Active.Individuals.Index(id));
|
||||
return (PenumbraApiEc.Success, old);
|
||||
}
|
||||
|
||||
private void OnResolvedFileChange(ModCollection collection, ResolvedFileChange type, Utf8GamePath gamePath, FullPath newPath, FullPath oldPath, IMod? mod)
|
||||
{
|
||||
// Penumbra.Log.Debug($"[API]{{{collection.Identity.Name}}} | {{{mod}}} | {type} Redirect of [ {gamePath} ] ([ {oldPath} ] -> [ {newPath} ])");
|
||||
ResolvedFileChanged?.Invoke(type, collection.Identity.Id, mod?.Name ?? string.Empty, gamePath.ToString(), oldPath.ToString(), newPath.ToString());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using Dalamud.Interface;
|
||||
using Dalamud.Plugin.Services;
|
||||
using OtterGui.Services;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Collections;
|
||||
using Penumbra.Collections.Manager;
|
||||
using Penumbra.Communication;
|
||||
|
|
@ -85,7 +86,7 @@ public class DalamudSubstitutionProvider : IDisposable, IApiService
|
|||
ResetSubstitutions(enumerable);
|
||||
}
|
||||
|
||||
private void OnResolvedFileChange(ModCollection collection, ResolvedFileChanged.Type type, Utf8GamePath key, FullPath _1, FullPath _2,
|
||||
private void OnResolvedFileChange(ModCollection collection, ResolvedFileChange type, Utf8GamePath key, FullPath _1, FullPath _2,
|
||||
IMod? _3)
|
||||
{
|
||||
if (_activeCollectionData.Interface != collection)
|
||||
|
|
@ -93,13 +94,13 @@ public class DalamudSubstitutionProvider : IDisposable, IApiService
|
|||
|
||||
switch (type)
|
||||
{
|
||||
case ResolvedFileChanged.Type.Added:
|
||||
case ResolvedFileChanged.Type.Removed:
|
||||
case ResolvedFileChanged.Type.Replaced:
|
||||
case ResolvedFileChange.Added:
|
||||
case ResolvedFileChange.Removed:
|
||||
case ResolvedFileChange.Replaced:
|
||||
ResetSubstitutions([key]);
|
||||
break;
|
||||
case ResolvedFileChanged.Type.FullRecomputeStart:
|
||||
case ResolvedFileChanged.Type.FullRecomputeFinished:
|
||||
case ResolvedFileChange.FullRecomputeStart:
|
||||
case ResolvedFileChange.FullRecomputeFinished:
|
||||
ResetSubstitutions(collection.ResolvedFiles.Keys);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,12 +24,14 @@ public sealed class IpcProviders : IDisposable, IApiService
|
|||
[
|
||||
IpcSubscribers.GetCollections.Provider(pi, api.Collection),
|
||||
IpcSubscribers.GetCollectionsByIdentifier.Provider(pi, api.Collection),
|
||||
IpcSubscribers.GetResolvedFilesForCollection.Provider(pi, api.Collection),
|
||||
IpcSubscribers.GetChangedItemsForCollection.Provider(pi, api.Collection),
|
||||
IpcSubscribers.GetCollection.Provider(pi, api.Collection),
|
||||
IpcSubscribers.GetCollectionForObject.Provider(pi, api.Collection),
|
||||
IpcSubscribers.SetCollection.Provider(pi, api.Collection),
|
||||
IpcSubscribers.SetCollectionForObject.Provider(pi, api.Collection),
|
||||
IpcSubscribers.CheckCurrentChangedItemFunc.Provider(pi, api.Collection),
|
||||
IpcSubscribers.ResolvedFileChanged.Provider(pi, api.Collection),
|
||||
|
||||
IpcSubscribers.ConvertTextureFile.Provider(pi, api.Editing),
|
||||
IpcSubscribers.ConvertTextureData.Provider(pi, api.Editing),
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using OtterGui;
|
|||
using OtterGui.Raii;
|
||||
using OtterGui.Services;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Api.Helpers;
|
||||
using Penumbra.Api.IpcSubscribers;
|
||||
using Penumbra.Collections.Manager;
|
||||
using Penumbra.GameData.Data;
|
||||
|
|
@ -13,8 +14,18 @@ using ImGuiClip = OtterGui.ImGuiClip;
|
|||
|
||||
namespace Penumbra.Api.IpcTester;
|
||||
|
||||
public class CollectionsIpcTester(IDalamudPluginInterface pi) : IUiService
|
||||
public class CollectionsIpcTester : IUiService, IDisposable
|
||||
{
|
||||
private readonly IDalamudPluginInterface _pi;
|
||||
public readonly EventSubscriber<ResolvedFileChange, Guid, string, string, string, string> ResolveFileChange;
|
||||
|
||||
private ResolvedFileChange _lastResolvedFileChangeType;
|
||||
private Guid _lastResolvedFileChangeCollection = Guid.Empty;
|
||||
private string _lastResolvedFileChangeMod = string.Empty;
|
||||
private string _lastResolvedFileChangeGamePath = string.Empty;
|
||||
private string _lastResolvedFileChangeOldFilePath = string.Empty;
|
||||
private string _lastResolvedFileChangeNewFilePath = string.Empty;
|
||||
|
||||
private int _objectIdx;
|
||||
private string _collectionIdString = string.Empty;
|
||||
private Guid? _collectionId;
|
||||
|
|
@ -23,10 +34,23 @@ public class CollectionsIpcTester(IDalamudPluginInterface pi) : IUiService
|
|||
private ApiCollectionType _type = ApiCollectionType.Yourself;
|
||||
|
||||
private Dictionary<Guid, string> _collections = [];
|
||||
private (string, string)[] _resolvedFiles= [];
|
||||
private (string, ChangedItemType, uint)[] _changedItems = [];
|
||||
private PenumbraApiEc _returnCode = PenumbraApiEc.Success;
|
||||
private (Guid Id, string Name)? _oldCollection;
|
||||
|
||||
public CollectionsIpcTester(IDalamudPluginInterface pi)
|
||||
{
|
||||
_pi = pi;
|
||||
ResolveFileChange = ResolvedFileChanged.Subscriber(pi, UpdateLastResolvedChange);
|
||||
ResolveFileChange.Disable();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ResolveFileChange.Dispose();
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
using var _ = ImRaii.TreeNode("Collections");
|
||||
|
|
@ -45,11 +69,17 @@ public class CollectionsIpcTester(IDalamudPluginInterface pi) : IUiService
|
|||
return;
|
||||
|
||||
IpcTester.DrawIntro("Last Return Code", _returnCode.ToString());
|
||||
|
||||
IpcTester.DrawIntro(ResolvedFileChanged.Label, "Last Resolved File Change");
|
||||
ImGui.TextUnformatted(_lastResolvedFileChangeMod.Length > 0
|
||||
? $"{_lastResolvedFileChangeType} of {_lastResolvedFileChangeMod} in {_lastResolvedFileChangeCollection} for game path {_lastResolvedFileChangeGamePath} from {_lastResolvedFileChangeOldFilePath} to {_lastResolvedFileChangeNewFilePath}"
|
||||
: "None");
|
||||
|
||||
if (_oldCollection != null)
|
||||
ImGui.TextUnformatted(!_oldCollection.HasValue ? "Created" : _oldCollection.ToString());
|
||||
|
||||
IpcTester.DrawIntro(GetCollectionsByIdentifier.Label, "Collection Identifier");
|
||||
var collectionList = new GetCollectionsByIdentifier(pi).Invoke(_collectionIdString);
|
||||
var collectionList = new GetCollectionsByIdentifier(_pi).Invoke(_collectionIdString);
|
||||
if (collectionList.Count == 0)
|
||||
{
|
||||
DrawCollection(null);
|
||||
|
|
@ -68,27 +98,27 @@ public class CollectionsIpcTester(IDalamudPluginInterface pi) : IUiService
|
|||
}
|
||||
|
||||
IpcTester.DrawIntro(GetCollection.Label, "Current Collection");
|
||||
DrawCollection(new GetCollection(pi).Invoke(ApiCollectionType.Current));
|
||||
DrawCollection(new GetCollection(_pi).Invoke(ApiCollectionType.Current));
|
||||
|
||||
IpcTester.DrawIntro(GetCollection.Label, "Default Collection");
|
||||
DrawCollection(new GetCollection(pi).Invoke(ApiCollectionType.Default));
|
||||
DrawCollection(new GetCollection(_pi).Invoke(ApiCollectionType.Default));
|
||||
|
||||
IpcTester.DrawIntro(GetCollection.Label, "Interface Collection");
|
||||
DrawCollection(new GetCollection(pi).Invoke(ApiCollectionType.Interface));
|
||||
DrawCollection(new GetCollection(_pi).Invoke(ApiCollectionType.Interface));
|
||||
|
||||
IpcTester.DrawIntro(GetCollection.Label, "Special Collection");
|
||||
DrawCollection(new GetCollection(pi).Invoke(_type));
|
||||
DrawCollection(new GetCollection(_pi).Invoke(_type));
|
||||
|
||||
IpcTester.DrawIntro(GetCollections.Label, "Collections");
|
||||
DrawCollectionPopup();
|
||||
if (ImGui.Button("Get##Collections"))
|
||||
{
|
||||
_collections = new GetCollections(pi).Invoke();
|
||||
_collections = new GetCollections(_pi).Invoke();
|
||||
ImGui.OpenPopup("Collections");
|
||||
}
|
||||
|
||||
IpcTester.DrawIntro(GetCollectionForObject.Label, "Get Object Collection");
|
||||
var (valid, individual, effectiveCollection) = new GetCollectionForObject(pi).Invoke(_objectIdx);
|
||||
var (valid, individual, effectiveCollection) = new GetCollectionForObject(_pi).Invoke(_objectIdx);
|
||||
DrawCollection(effectiveCollection);
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted($"({(valid ? "Valid" : "Invalid")} Object{(individual ? ", Individual Assignment)" : ")")}");
|
||||
|
|
@ -96,24 +126,34 @@ public class CollectionsIpcTester(IDalamudPluginInterface pi) : IUiService
|
|||
IpcTester.DrawIntro(SetCollection.Label, "Set Special Collection");
|
||||
if (ImGui.Button("Set##SpecialCollection"))
|
||||
(_returnCode, _oldCollection) =
|
||||
new SetCollection(pi).Invoke(_type, _collectionId.GetValueOrDefault(Guid.Empty), _allowCreation, _allowDeletion);
|
||||
new SetCollection(_pi).Invoke(_type, _collectionId.GetValueOrDefault(Guid.Empty), _allowCreation, _allowDeletion);
|
||||
ImGui.TableNextColumn();
|
||||
if (ImGui.Button("Remove##SpecialCollection"))
|
||||
(_returnCode, _oldCollection) = new SetCollection(pi).Invoke(_type, null, _allowCreation, _allowDeletion);
|
||||
(_returnCode, _oldCollection) = new SetCollection(_pi).Invoke(_type, null, _allowCreation, _allowDeletion);
|
||||
|
||||
IpcTester.DrawIntro(SetCollectionForObject.Label, "Set Object Collection");
|
||||
if (ImGui.Button("Set##ObjectCollection"))
|
||||
(_returnCode, _oldCollection) = new SetCollectionForObject(pi).Invoke(_objectIdx, _collectionId.GetValueOrDefault(Guid.Empty),
|
||||
(_returnCode, _oldCollection) = new SetCollectionForObject(_pi).Invoke(_objectIdx, _collectionId.GetValueOrDefault(Guid.Empty),
|
||||
_allowCreation, _allowDeletion);
|
||||
ImGui.TableNextColumn();
|
||||
if (ImGui.Button("Remove##ObjectCollection"))
|
||||
(_returnCode, _oldCollection) = new SetCollectionForObject(pi).Invoke(_objectIdx, null, _allowCreation, _allowDeletion);
|
||||
(_returnCode, _oldCollection) = new SetCollectionForObject(_pi).Invoke(_objectIdx, null, _allowCreation, _allowDeletion);
|
||||
|
||||
IpcTester.DrawIntro(GetResolvedFilesForCollection.Label, "Resolved Files List");
|
||||
DrawResolvedFilesPopup();
|
||||
if (ImGui.Button("Get##ResolvedFiles"))
|
||||
{
|
||||
var files = new GetResolvedFilesForCollection(_pi).Invoke(_collectionId.GetValueOrDefault(Guid.Empty));
|
||||
_resolvedFiles = files.Select(kvp => (kvp.Key, kvp.Value)).ToArray();
|
||||
ImGui.OpenPopup("Resolved Files List");
|
||||
}
|
||||
|
||||
|
||||
IpcTester.DrawIntro(GetChangedItemsForCollection.Label, "Changed Item List");
|
||||
DrawChangedItemPopup();
|
||||
if (ImGui.Button("Get##ChangedItems"))
|
||||
{
|
||||
var items = new GetChangedItemsForCollection(pi).Invoke(_collectionId.GetValueOrDefault(Guid.Empty));
|
||||
var items = new GetChangedItemsForCollection(_pi).Invoke(_collectionId.GetValueOrDefault(Guid.Empty));
|
||||
_changedItems = items.Select(kvp =>
|
||||
{
|
||||
var (type, id) = kvp.Value.ToApiObject();
|
||||
|
|
@ -123,10 +163,33 @@ public class CollectionsIpcTester(IDalamudPluginInterface pi) : IUiService
|
|||
}
|
||||
IpcTester.DrawIntro(RedrawCollectionMembers.Label, "Redraw Collection Members");
|
||||
if (ImGui.Button("Redraw##ObjectCollection"))
|
||||
new RedrawCollectionMembers(pi).Invoke(collectionList[0].Id, RedrawType.Redraw);
|
||||
new RedrawCollectionMembers(_pi).Invoke(collectionList[0].Id, RedrawType.Redraw);
|
||||
|
||||
}
|
||||
|
||||
private void DrawResolvedFilesPopup()
|
||||
{
|
||||
// calculate the width by getting the max width of the longest string in each item.
|
||||
var width = _resolvedFiles.Length > 0
|
||||
? ImGui.CalcTextSize(_resolvedFiles.OrderByDescending(i => i.Item1.Length + i.Item2.Length).Select(i => i.Item1 + i.Item2).First()).X : 500f;
|
||||
ImGui.SetNextWindowSize(ImGuiHelpers.ScaledVector2(width, 500));
|
||||
using var p = ImRaii.Popup("Resolved Files List");
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
using (var table = ImRaii.Table("##ResolvedFiles", 2, ImGuiTableFlags.SizingFixedFit))
|
||||
{
|
||||
if (table)
|
||||
ImGuiClip.ClippedDraw(_resolvedFiles, t =>
|
||||
{
|
||||
ImGuiUtil.DrawTableColumn(t.Item1);
|
||||
ImGuiUtil.DrawTableColumn(t.Item2);
|
||||
}, ImGui.GetTextLineHeightWithSpacing());
|
||||
}
|
||||
if (ImGui.Button("Close", -Vector2.UnitX) || !ImGui.IsWindowFocused())
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
|
||||
private void DrawChangedItemPopup()
|
||||
{
|
||||
ImGui.SetNextWindowSize(ImGuiHelpers.ScaledVector2(500, 500));
|
||||
|
|
@ -186,4 +249,14 @@ public class CollectionsIpcTester(IDalamudPluginInterface pi) : IUiService
|
|||
ImGuiUtil.CopyOnClickSelectable(collection.Value.Id.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLastResolvedChange(ResolvedFileChange type, Guid collection, string mod, string gamePath, string oldFilePath, string newFilePath)
|
||||
{
|
||||
_lastResolvedFileChangeType = type;
|
||||
_lastResolvedFileChangeCollection = collection;
|
||||
_lastResolvedFileChangeMod = mod;
|
||||
_lastResolvedFileChangeGamePath = gamePath;
|
||||
_lastResolvedFileChangeOldFilePath = oldFilePath;
|
||||
_lastResolvedFileChangeNewFilePath = newFilePath;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ public class IpcTester(
|
|||
return;
|
||||
|
||||
Penumbra.Log.Debug("[IPCTester] Subscribed to IPC events for IPC tester.");
|
||||
collectionsIpcTester.ResolveFileChange.Enable();
|
||||
gameStateIpcTester.GameObjectResourcePathResolved.Enable();
|
||||
gameStateIpcTester.CharacterBaseCreated.Enable();
|
||||
gameStateIpcTester.CharacterBaseCreating.Enable();
|
||||
|
|
@ -111,6 +112,7 @@ public class IpcTester(
|
|||
|
||||
Penumbra.Log.Debug("[IPCTester] Unsubscribed from IPC events for IPC tester.");
|
||||
_subscribed = false;
|
||||
collectionsIpcTester.ResolveFileChange.Disable();
|
||||
gameStateIpcTester.GameObjectResourcePathResolved.Disable();
|
||||
gameStateIpcTester.CharacterBaseCreated.Disable();
|
||||
gameStateIpcTester.CharacterBaseCreating.Disable();
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
using Dalamud.Interface.ImGuiNotification;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Extensions;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.GameData.Data;
|
||||
using Penumbra.Meta.Manipulations;
|
||||
using Penumbra.Mods;
|
||||
using Penumbra.Communication;
|
||||
using Penumbra.Mods.Editor;
|
||||
using Penumbra.String.Classes;
|
||||
using Penumbra.Util;
|
||||
using Penumbra.GameData.Data;
|
||||
using OtterGui.Extensions;
|
||||
|
||||
namespace Penumbra.Collections.Cache;
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ public sealed class CollectionCache : IDisposable
|
|||
private readonly CollectionCacheManager _manager;
|
||||
private readonly ModCollection _collection;
|
||||
public readonly CollectionModData ModData = new();
|
||||
private readonly SortedList<string, (SingleArray<IMod>, IIdentifiedObjectData)> _changedItems = [];
|
||||
private readonly SortedList<string, (SingleArray<IMod>, IIdentifiedObjectData)> _changedItems = [];
|
||||
public readonly ConcurrentDictionary<Utf8GamePath, ModPath> ResolvedFiles = new();
|
||||
public readonly CustomResourceCache CustomResources;
|
||||
public readonly MetaCache Meta;
|
||||
|
|
@ -149,20 +149,20 @@ public sealed class CollectionCache : IDisposable
|
|||
{
|
||||
ResolvedFiles.TryAdd(path, new ModPath(Mod.ForcedFiles, fullPath));
|
||||
CustomResources.Invalidate(path);
|
||||
InvokeResolvedFileChange(_collection, ResolvedFileChanged.Type.Replaced, path, fullPath, modPath.Path,
|
||||
InvokeResolvedFileChange(_collection, ResolvedFileChange.Replaced, path, fullPath, modPath.Path,
|
||||
Mod.ForcedFiles);
|
||||
}
|
||||
else
|
||||
{
|
||||
CustomResources.Invalidate(path);
|
||||
InvokeResolvedFileChange(_collection, ResolvedFileChanged.Type.Removed, path, FullPath.Empty, modPath.Path, null);
|
||||
InvokeResolvedFileChange(_collection, ResolvedFileChange.Removed, path, FullPath.Empty, modPath.Path, null);
|
||||
}
|
||||
}
|
||||
else if (fullPath.FullName.Length > 0)
|
||||
{
|
||||
ResolvedFiles.TryAdd(path, new ModPath(Mod.ForcedFiles, fullPath));
|
||||
CustomResources.Invalidate(path);
|
||||
InvokeResolvedFileChange(_collection, ResolvedFileChanged.Type.Added, path, fullPath, FullPath.Empty, Mod.ForcedFiles);
|
||||
InvokeResolvedFileChange(_collection, ResolvedFileChange.Added, path, fullPath, FullPath.Empty, Mod.ForcedFiles);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -186,10 +186,9 @@ public sealed class CollectionCache : IDisposable
|
|||
{
|
||||
CustomResources.Invalidate(path);
|
||||
if (mp.Mod != mod)
|
||||
Penumbra.Log.Warning(
|
||||
$"Invalid mod state, removing {mod.Name} and associated file {path} returned current mod {mp.Mod.Name}.");
|
||||
Penumbra.Log.Warning($"Invalid mod state, removing {mod.Name} and associated file {path} returned current mod {mp.Mod.Name}.");
|
||||
else
|
||||
_manager.ResolvedFileChanged.Invoke(_collection, ResolvedFileChanged.Type.Removed, path, FullPath.Empty, mp.Path, mp.Mod);
|
||||
_manager.ResolvedFileChanged.Invoke(_collection, ResolvedFileChange.Removed, path, FullPath.Empty, mp.Path, mp.Mod);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -272,7 +271,7 @@ public sealed class CollectionCache : IDisposable
|
|||
}
|
||||
|
||||
/// <summary> Invoke only if not in a full recalculation. </summary>
|
||||
private void InvokeResolvedFileChange(ModCollection collection, ResolvedFileChanged.Type type, Utf8GamePath key, FullPath value,
|
||||
private void InvokeResolvedFileChange(ModCollection collection, ResolvedFileChange type, Utf8GamePath key, FullPath value,
|
||||
FullPath old, IMod? mod)
|
||||
{
|
||||
if (Calculating == -1)
|
||||
|
|
@ -315,7 +314,7 @@ public sealed class CollectionCache : IDisposable
|
|||
{
|
||||
ModData.AddPath(mod, path);
|
||||
CustomResources.Invalidate(path);
|
||||
InvokeResolvedFileChange(_collection, ResolvedFileChanged.Type.Added, path, file, FullPath.Empty, mod);
|
||||
InvokeResolvedFileChange(_collection, ResolvedFileChange.Added, path, file, FullPath.Empty, mod);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -330,7 +329,7 @@ public sealed class CollectionCache : IDisposable
|
|||
ResolvedFiles[path] = new ModPath(mod, file);
|
||||
ModData.AddPath(mod, path);
|
||||
CustomResources.Invalidate(path);
|
||||
InvokeResolvedFileChange(_collection, ResolvedFileChanged.Type.Replaced, path, file, modPath.Path, mod);
|
||||
InvokeResolvedFileChange(_collection, ResolvedFileChange.Replaced, path, file, modPath.Path, mod);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ public class CollectionCacheManager : IDisposable, IService
|
|||
cache.Calculating = Environment.CurrentManagedThreadId;
|
||||
try
|
||||
{
|
||||
ResolvedFileChanged.Invoke(collection, ResolvedFileChanged.Type.FullRecomputeStart, Utf8GamePath.Empty, FullPath.Empty,
|
||||
ResolvedFileChanged.Invoke(collection, ResolvedFileChange.FullRecomputeStart, Utf8GamePath.Empty, FullPath.Empty,
|
||||
FullPath.Empty, null);
|
||||
cache.ResolvedFiles.Clear();
|
||||
cache.Meta.Reset();
|
||||
|
|
@ -189,7 +189,7 @@ public class CollectionCacheManager : IDisposable, IService
|
|||
collection.Counters.IncrementChange();
|
||||
|
||||
MetaFileManager.ApplyDefaultFiles(collection);
|
||||
ResolvedFileChanged.Invoke(collection, ResolvedFileChanged.Type.FullRecomputeFinished, Utf8GamePath.Empty, FullPath.Empty,
|
||||
ResolvedFileChanged.Invoke(collection, ResolvedFileChange.FullRecomputeFinished, Utf8GamePath.Empty, FullPath.Empty,
|
||||
FullPath.Empty,
|
||||
null);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
using OtterGui.Classes;
|
||||
using Penumbra.Api.Api;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Collections;
|
||||
using Penumbra.Mods.Editor;
|
||||
using Penumbra.String.Classes;
|
||||
|
|
@ -16,20 +18,14 @@ namespace Penumbra.Communication;
|
|||
/// <item>Parameter is the mod responsible for the new redirection if any. </item>
|
||||
/// </list> </summary>
|
||||
public sealed class ResolvedFileChanged()
|
||||
: EventWrapper<ModCollection, ResolvedFileChanged.Type, Utf8GamePath, FullPath, FullPath, IMod?, ResolvedFileChanged.Priority>(
|
||||
: EventWrapper<ModCollection, ResolvedFileChange, Utf8GamePath, FullPath, FullPath, IMod?, ResolvedFileChanged.Priority>(
|
||||
nameof(ResolvedFileChanged))
|
||||
{
|
||||
public enum Type
|
||||
{
|
||||
Added,
|
||||
Removed,
|
||||
Replaced,
|
||||
FullRecomputeStart,
|
||||
FullRecomputeFinished,
|
||||
}
|
||||
|
||||
public enum Priority
|
||||
{
|
||||
/// <seealso cref="CollectionApi.OnResolvedFileChange"/>
|
||||
ApiResolvedFile = int.MinValue,
|
||||
|
||||
/// <seealso cref="Api.DalamudSubstitutionProvider.OnResolvedFileChange"/>
|
||||
DalamudSubstitutionProvider = 0,
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using Dalamud.Utility.Signatures;
|
|||
using FFXIVClientStructs.FFXIV.Client.System.Scheduler.Resource;
|
||||
using Lumina.Excel.Sheets;
|
||||
using OtterGui.Services;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Collections;
|
||||
using Penumbra.Communication;
|
||||
using Penumbra.GameData;
|
||||
|
|
@ -41,15 +42,15 @@ public unsafe class SchedulerResourceManagementService : IService, IDisposable
|
|||
interop.InitializeFromAttributes(this);
|
||||
}
|
||||
|
||||
private void OnResolvedFileChange(ModCollection collection, ResolvedFileChanged.Type type, Utf8GamePath gamePath, FullPath oldPath,
|
||||
private void OnResolvedFileChange(ModCollection collection, ResolvedFileChange type, Utf8GamePath gamePath, FullPath oldPath,
|
||||
FullPath newPath, IMod? mod)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ResolvedFileChanged.Type.Added:
|
||||
case ResolvedFileChange.Added:
|
||||
CheckFile(gamePath);
|
||||
return;
|
||||
case ResolvedFileChanged.Type.FullRecomputeFinished:
|
||||
case ResolvedFileChange.FullRecomputeFinished:
|
||||
foreach (var path in collection.ResolvedFiles.Keys)
|
||||
CheckFile(path);
|
||||
return;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue