Change CollectionCache handling.

This commit is contained in:
Ottermandias 2023-05-01 18:43:49 +02:00
parent 7ab5c7311c
commit c2fb18ab53
4 changed files with 63 additions and 62 deletions

View file

@ -21,20 +21,18 @@ public class CollectionCacheManager : IDisposable
private readonly CommunicatorService _communicator; private readonly CommunicatorService _communicator;
private readonly TempModManager _tempMods; private readonly TempModManager _tempMods;
private readonly ModStorage _modStorage; private readonly ModStorage _modStorage;
private readonly CollectionStorage _storage;
private readonly ActiveCollections _active; private readonly ActiveCollections _active;
internal readonly MetaFileManager MetaFileManager; internal readonly MetaFileManager MetaFileManager;
private readonly Dictionary<ModCollection, CollectionCache> _caches = new(); public int Count { get; private set; }
public int Count public IEnumerable<ModCollection> Active
=> _caches.Count; => _storage.Where(c => c.HasCache);
public IEnumerable<(ModCollection Collection, CollectionCache Cache)> Active
=> _caches.Where(c => c.Key.Index > ModCollection.Empty.Index).Select(p => (p.Key, p.Value));
public CollectionCacheManager(FrameworkManager framework, CommunicatorService communicator, public CollectionCacheManager(FrameworkManager framework, CommunicatorService communicator,
TempModManager tempMods, ModStorage modStorage, MetaFileManager metaFileManager, ActiveCollections active) TempModManager tempMods, ModStorage modStorage, MetaFileManager metaFileManager, ActiveCollections active, CollectionStorage storage)
{ {
_framework = framework; _framework = framework;
_communicator = communicator; _communicator = communicator;
@ -42,6 +40,7 @@ public class CollectionCacheManager : IDisposable
_modStorage = modStorage; _modStorage = modStorage;
MetaFileManager = metaFileManager; MetaFileManager = metaFileManager;
_active = active; _active = active;
_storage = storage;
_communicator.CollectionChange.Subscribe(OnCollectionChange, -100); _communicator.CollectionChange.Subscribe(OnCollectionChange, -100);
_communicator.ModPathChanged.Subscribe(OnModChangeAddition, -100); _communicator.ModPathChanged.Subscribe(OnModChangeAddition, -100);
@ -72,12 +71,11 @@ public class CollectionCacheManager : IDisposable
/// <summary> Only creates a new cache, does not update an existing one. </summary> /// <summary> Only creates a new cache, does not update an existing one. </summary>
public bool CreateCache(ModCollection collection) public bool CreateCache(ModCollection collection)
{ {
if (_caches.ContainsKey(collection) || collection.Index == ModCollection.Empty.Index) if (collection.HasCache || collection.Index == ModCollection.Empty.Index)
return false; return false;
var cache = new CollectionCache(this, collection); collection._cache = new CollectionCache(this, collection);
_caches.Add(collection, cache); ++Count;
collection._cache = cache;
Penumbra.Log.Verbose($"Created new cache for collection {collection.AnonymizedName}."); Penumbra.Log.Verbose($"Created new cache for collection {collection.AnonymizedName}.");
return true; return true;
} }
@ -97,28 +95,34 @@ public class CollectionCacheManager : IDisposable
return; return;
Penumbra.Log.Debug($"[{Thread.CurrentThread.ManagedThreadId}] Recalculating effective file list for {collection.AnonymizedName}"); Penumbra.Log.Debug($"[{Thread.CurrentThread.ManagedThreadId}] Recalculating effective file list for {collection.AnonymizedName}");
if (!_caches.TryGetValue(collection, out var cache)) if (!collection.HasCache)
{ {
Penumbra.Log.Error( Penumbra.Log.Error(
$"[{Thread.CurrentThread.ManagedThreadId}] Recalculating effective file list for {collection.AnonymizedName} failed, no cache exists."); $"[{Thread.CurrentThread.ManagedThreadId}] Recalculating effective file list for {collection.AnonymizedName} failed, no cache exists.");
return; return;
} }
FullRecalculation(collection, cache); FullRecalculation(collection);
Penumbra.Log.Debug( Penumbra.Log.Debug(
$"[{Thread.CurrentThread.ManagedThreadId}] Recalculation of effective file list for {collection.AnonymizedName} finished."); $"[{Thread.CurrentThread.ManagedThreadId}] Recalculation of effective file list for {collection.AnonymizedName} finished.");
} }
private void FullRecalculation(ModCollection collection, CollectionCache cache) private void FullRecalculation(ModCollection collection)
{ {
var cache = collection._cache;
if (cache == null)
return;
cache.ResolvedFiles.Clear(); cache.ResolvedFiles.Clear();
cache.Meta.Reset(); cache.Meta.Reset();
cache._conflicts.Clear(); cache._conflicts.Clear();
// Add all forced redirects. // Add all forced redirects.
foreach (var tempMod in _tempMods.ModsForAllCollections.Concat( foreach (var tempMod in _tempMods.ModsForAllCollections
_tempMods.Mods.TryGetValue(collection, out var list) ? list : Array.Empty<TemporaryMod>())) .Concat(_tempMods.Mods.TryGetValue(collection, out var list)
? list
: Array.Empty<TemporaryMod>()))
cache.AddMod(tempMod, false); cache.AddMod(tempMod, false);
foreach (var mod in _modStorage) foreach (var mod in _modStorage)
@ -157,11 +161,11 @@ public class CollectionCacheManager : IDisposable
{ {
case ModPathChangeType.Deleted: case ModPathChangeType.Deleted:
case ModPathChangeType.StartingReload: case ModPathChangeType.StartingReload:
foreach (var collection in _caches.Keys.Where(c => c[mod.Index].Settings?.Enabled == true)) foreach (var collection in _storage.Where(c => c.HasCache && c[mod.Index].Settings?.Enabled == true))
collection._cache!.RemoveMod(mod, true); collection._cache!.RemoveMod(mod, true);
break; break;
case ModPathChangeType.Moved: case ModPathChangeType.Moved:
foreach (var collection in _caches.Keys.Where(c => c.HasCache && c[mod.Index].Settings?.Enabled == true)) foreach (var collection in _storage.Where(c => c.HasCache && c[mod.Index].Settings?.Enabled == true))
collection._cache!.ReloadMod(mod, true); collection._cache!.ReloadMod(mod, true);
break; break;
} }
@ -172,13 +176,13 @@ public class CollectionCacheManager : IDisposable
if (type is not (ModPathChangeType.Added or ModPathChangeType.Reloaded)) if (type is not (ModPathChangeType.Added or ModPathChangeType.Reloaded))
return; return;
foreach (var collection in _caches.Keys.Where(c => c[mod.Index].Settings?.Enabled == true)) foreach (var collection in _storage.Where(c => c.HasCache && c[mod.Index].Settings?.Enabled == true))
collection._cache!.AddMod(mod, true); collection._cache!.AddMod(mod, true);
} }
/// <summary> Apply a mod change to all collections with a cache. </summary> /// <summary> Apply a mod change to all collections with a cache. </summary>
private void OnGlobalModChange(TemporaryMod mod, bool created, bool removed) private void OnGlobalModChange(TemporaryMod mod, bool created, bool removed)
=> TempModManager.OnGlobalModChange(_caches.Keys, mod, created, removed); => TempModManager.OnGlobalModChange(_storage.Where(c => c.HasCache), mod, created, removed);
/// <summary> Remove a cache from a collection if it is active. </summary> /// <summary> Remove a cache from a collection if it is active. </summary>
private void RemoveCache(ModCollection? collection) private void RemoveCache(ModCollection? collection)
@ -198,7 +202,7 @@ public class CollectionCacheManager : IDisposable
{ {
if (type is ModOptionChangeType.PrepareChange) if (type is ModOptionChangeType.PrepareChange)
{ {
foreach (var collection in _caches.Keys.Where(collection => collection[mod.Index].Settings is { Enabled: true })) foreach (var collection in _storage.Where(collection => collection.HasCache && collection[mod.Index].Settings is { Enabled: true }))
collection._cache!.RemoveMod(mod, false); collection._cache!.RemoveMod(mod, false);
return; return;
@ -209,7 +213,7 @@ public class CollectionCacheManager : IDisposable
if (!recomputeList) if (!recomputeList)
return; return;
foreach (var collection in _caches.Keys.Where(collection => collection[mod.Index].Settings is { Enabled: true })) foreach (var collection in _storage.Where(collection => collection.HasCache && collection[mod.Index].Settings is { Enabled: true }))
{ {
if (reload) if (reload)
collection._cache!.ReloadMod(mod, true); collection._cache!.ReloadMod(mod, true);
@ -221,16 +225,17 @@ public class CollectionCacheManager : IDisposable
/// <summary> Increment the counter to ensure new files are loaded after applying meta changes. </summary> /// <summary> Increment the counter to ensure new files are loaded after applying meta changes. </summary>
private void IncrementCounters() private void IncrementCounters()
{ {
foreach (var (collection, _) in _caches) foreach (var collection in _storage.Where(c => c.HasCache))
++collection.ChangeCounter; ++collection.ChangeCounter;
MetaFileManager.CharacterUtility.LoadingFinished -= IncrementCounters; MetaFileManager.CharacterUtility.LoadingFinished -= IncrementCounters;
} }
private void OnModSettingChange(ModCollection collection, ModSettingChange type, Mod? mod, int oldValue, int groupIdx, bool _) private void OnModSettingChange(ModCollection collection, ModSettingChange type, Mod? mod, int oldValue, int groupIdx, bool _)
{ {
if (!_caches.TryGetValue(collection, out var cache)) if (!collection.HasCache)
return; return;
var cache = collection._cache!;
switch (type) switch (type)
{ {
case ModSettingChange.Inheritance: case ModSettingChange.Inheritance:
@ -259,7 +264,7 @@ public class CollectionCacheManager : IDisposable
break; break;
case ModSettingChange.MultiInheritance: case ModSettingChange.MultiInheritance:
case ModSettingChange.MultiEnableState: case ModSettingChange.MultiEnableState:
FullRecalculation(collection, cache); FullRecalculation(collection);
break; break;
} }
} }
@ -269,19 +274,17 @@ public class CollectionCacheManager : IDisposable
/// just recompute everything. /// just recompute everything.
/// </summary> /// </summary>
private void OnCollectionInheritanceChange(ModCollection collection, bool _) private void OnCollectionInheritanceChange(ModCollection collection, bool _)
{ => FullRecalculation(collection);
if (_caches.TryGetValue(collection, out var cache))
FullRecalculation(collection, cache);
}
/// <summary> Clear the current cache of a collection. </summary> /// <summary> Clear the current cache of a collection. </summary>
private void ClearCache(ModCollection collection) private void ClearCache(ModCollection collection)
{ {
if (!_caches.Remove(collection, out var cache)) if (!collection.HasCache)
return; return;
cache.Dispose(); collection._cache!.Dispose();
collection._cache = null; collection._cache = null;
--Count;
Penumbra.Log.Verbose($"Cleared cache of collection {collection.AnonymizedName}."); Penumbra.Log.Verbose($"Cleared cache of collection {collection.AnonymizedName}.");
} }

View file

@ -225,8 +225,8 @@ public class Penumbra : IDalamudPlugin
foreach (var (name, id, collection) in _collectionManager.Active.Individuals.Assignments) foreach (var (name, id, collection) in _collectionManager.Active.Individuals.Assignments)
sb.Append($"> **`{id[0].Incognito(name) + ':',-30}`** {collection.AnonymizedName}\n"); sb.Append($"> **`{id[0].Incognito(name) + ':',-30}`** {collection.AnonymizedName}\n");
foreach (var (collection, cache) in _collectionManager.Caches.Active) foreach (var collection in _collectionManager.Caches.Active)
PrintCollection(collection, cache); PrintCollection(collection, collection._cache!);
return sb.ToString(); return sb.ToString();
} }

View file

@ -5,6 +5,7 @@ using ImGuiNET;
using OtterGui.Raii; using OtterGui.Raii;
using Penumbra.Import.Structs; using Penumbra.Import.Structs;
using Penumbra.Mods.Manager; using Penumbra.Mods.Manager;
using Penumbra.Services;
namespace Penumbra.UI; namespace Penumbra.UI;
@ -36,7 +37,7 @@ public sealed class ImportPopup : Window
if (!_modImportManager.IsImporting(out var import)) if (!_modImportManager.IsImporting(out var import))
return; return;
const string importPopup = "##importPopup"; const string importPopup = "##PenumbraImportPopup";
if (!ImGui.IsPopupOpen(importPopup)) if (!ImGui.IsPopupOpen(importPopup))
ImGui.OpenPopup(importPopup); ImGui.OpenPopup(importPopup);

View file

@ -6,10 +6,8 @@ using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.Game.Group; using FFXIVClientStructs.FFXIV.Client.Game.Group;
using FFXIVClientStructs.FFXIV.Client.Game.Object; using FFXIVClientStructs.FFXIV.Client.Game.Object;
using FFXIVClientStructs.FFXIV.Client.System.Resource; using FFXIVClientStructs.FFXIV.Client.System.Resource;
using FFXIVClientStructs.Interop;
using ImGuiNET; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Raii;
using OtterGui.Widgets; using OtterGui.Widgets;
using Penumbra.Api; using Penumbra.Api;
using Penumbra.Collections.Manager; using Penumbra.Collections.Manager;
@ -148,37 +146,36 @@ public class DebugTab : ITab
} }
} }
using (var tree = TreeNode("Collections")) using (var tree = TreeNode($"Collections ({_collectionManager.Caches.Count}/{_collectionManager.Storage.Count - 1})###Collections"))
{ {
if (!tree) if (tree)
return; {
using var table = Table("##DebugCollectionsTable", 2, ImGuiTableFlags.SizingFixedFit);
using var table = Table("##DebugCollectionsTable", 2, ImGuiTableFlags.SizingFixedFit); if (table)
if (!table) foreach (var collection in _collectionManager.Storage)
return; PrintValue(collection.Name, collection.HasCache.ToString());
}
foreach (var collection in _collectionManager.Storage)
PrintValue(collection.Name, collection.HasCache.ToString());
} }
using (var tree = TreeNode("Mods")) var issues = _modManager.WithIndex().Count(p => p.Index != p.Value.Index);
using (var tree = TreeNode($"Mods ({issues} Issues)###Mods"))
{ {
if (!tree) if (tree)
return;
using var table = Table("##DebugModsTable", 3, ImGuiTableFlags.SizingFixedFit);
if (!table)
return;
var lastIndex = -1;
foreach (var mod in _modManager)
{ {
PrintValue(mod.Name, mod.Index.ToString("D5")); using var table = Table("##DebugModsTable", 3, ImGuiTableFlags.SizingFixedFit);
ImGui.TableNextColumn(); if (table)
var index = mod.Index; {
if (index != lastIndex + 1) var lastIndex = -1;
ImGui.TextUnformatted("!!!"); foreach (var mod in _modManager)
lastIndex = index; {
PrintValue(mod.Name, mod.Index.ToString("D5"));
ImGui.TableNextColumn();
var index = mod.Index;
if (index != lastIndex + 1)
ImGui.TextUnformatted("!!!");
lastIndex = index;
}
}
} }
} }
} }