diff --git a/OtterGui b/OtterGui
index 6969f4c0..d59cf504 160000
--- a/OtterGui
+++ b/OtterGui
@@ -1 +1 @@
-Subproject commit 6969f4c05b2fab57e0dc30ae249be7c23cd81fa4
+Subproject commit d59cf50483fc81af5deb871bac76f70d42d7b8c1
diff --git a/Penumbra/Collections/Cache/CollectionCache.cs b/Penumbra/Collections/Cache/CollectionCache.cs
index 56539526..e753c8c8 100644
--- a/Penumbra/Collections/Cache/CollectionCache.cs
+++ b/Penumbra/Collections/Cache/CollectionCache.cs
@@ -3,6 +3,7 @@ using OtterGui.Classes;
using Penumbra.Meta.Manipulations;
using Penumbra.Mods;
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -127,19 +128,13 @@ public class CollectionCache : IDisposable
{
if (!CheckFullPath(path, fullPath))
return;
-
- if (ResolvedFiles.Remove(path, out var modPath))
- ModData.RemovePath(modPath.Mod, path);
- ResolvedFiles.Add(path, new ModPath(Mod.ForcedFiles, fullPath));
- ModData.AddPath(Mod.ForcedFiles, path);
+
+ _manager.ForceFile(this, path, fullPath);
}
/// Force a file resolve to be removed.
internal void RemovePath(Utf8GamePath path)
- {
- if (ResolvedFiles.Remove(path, out var modPath))
- ModData.RemovePath(modPath.Mod, path);
- }
+ => _manager.ForceFile(this, path, FullPath.Empty);
public void ReloadMod(IMod mod, bool addMetaChanges)
{
@@ -153,7 +148,7 @@ public class CollectionCache : IDisposable
var (paths, manipulations) = ModData.RemoveMod(mod);
if (addMetaChanges)
- ++_collection.ChangeCounter;
+ ++_collection.ChangeCounter;
foreach (var path in paths)
{
diff --git a/Penumbra/Collections/Cache/CollectionCacheManager.cs b/Penumbra/Collections/Cache/CollectionCacheManager.cs
index 5417aa19..d7408e9b 100644
--- a/Penumbra/Collections/Cache/CollectionCacheManager.cs
+++ b/Penumbra/Collections/Cache/CollectionCacheManager.cs
@@ -1,9 +1,11 @@
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using Dalamud.Game;
using OtterGui.Classes;
using Penumbra.Api;
using Penumbra.Api.Enums;
@@ -13,6 +15,7 @@ using Penumbra.Meta;
using Penumbra.Mods;
using Penumbra.Mods.Manager;
using Penumbra.Services;
+using Penumbra.String.Classes;
namespace Penumbra.Collections.Cache;
@@ -27,6 +30,8 @@ public class CollectionCacheManager : IDisposable
internal readonly MetaFileManager MetaFileManager;
+ private readonly ConcurrentQueue<(CollectionCache, Utf8GamePath, FullPath)> _forcedFileQueue = new();
+
private int _count;
public int Count
@@ -48,13 +53,15 @@ public class CollectionCacheManager : IDisposable
if (!_active.Individuals.IsLoaded)
_active.Individuals.Loaded += CreateNecessaryCaches;
+ _framework.Framework.Update += OnFramework;
_communicator.CollectionChange.Subscribe(OnCollectionChange, CollectionChange.Priority.CollectionCacheManager);
_communicator.ModPathChanged.Subscribe(OnModChangeAddition, ModPathChanged.Priority.CollectionCacheManagerAddition);
_communicator.ModPathChanged.Subscribe(OnModChangeRemoval, ModPathChanged.Priority.CollectionCacheManagerRemoval);
_communicator.TemporaryGlobalModChange.Subscribe(OnGlobalModChange, TemporaryGlobalModChange.Priority.CollectionCacheManager);
_communicator.ModOptionChanged.Subscribe(OnModOptionChange, ModOptionChanged.Priority.CollectionCacheManager);
_communicator.ModSettingChanged.Subscribe(OnModSettingChange, ModSettingChanged.Priority.CollectionCacheManager);
- _communicator.CollectionInheritanceChanged.Subscribe(OnCollectionInheritanceChange, CollectionInheritanceChanged.Priority.CollectionCacheManager);
+ _communicator.CollectionInheritanceChanged.Subscribe(OnCollectionInheritanceChange,
+ CollectionInheritanceChanged.Priority.CollectionCacheManager);
_communicator.ModDiscoveryStarted.Subscribe(OnModDiscoveryStarted, ModDiscoveryStarted.Priority.CollectionCacheManager);
_communicator.ModDiscoveryFinished.Subscribe(OnModDiscoveryFinished, ModDiscoveryFinished.Priority.CollectionCacheManager);
@@ -95,6 +102,9 @@ public class CollectionCacheManager : IDisposable
=> _framework.RegisterImportant(nameof(CalculateEffectiveFileList) + collection.Name,
() => CalculateEffectiveFileListInternal(collection));
+ public void ForceFile(CollectionCache cache, Utf8GamePath path, FullPath fullPath)
+ => _forcedFileQueue.Enqueue((cache, path, fullPath));
+
private void CalculateEffectiveFileListInternal(ModCollection collection)
{
// Skip the empty collection.
@@ -163,9 +173,14 @@ public class CollectionCacheManager : IDisposable
else
{
RemoveCache(old);
-
if (type is not CollectionType.Inactive && newCollection != null && newCollection.Index != 0 && CreateCache(newCollection))
CalculateEffectiveFileList(newCollection);
+
+ if (type is CollectionType.Default)
+ if (newCollection != null)
+ MetaFileManager.ApplyDefaultFiles(newCollection);
+ else
+ MetaFileManager.CharacterUtility.ResetAll();
}
}
@@ -338,4 +353,18 @@ public class CollectionCacheManager : IDisposable
var tasks = Active.Select(c => Task.Run(() => CalculateEffectiveFileListInternal(c))).ToArray();
Task.WaitAll(tasks);
}
+
+ ///
+ /// Update forced files only on framework.
+ ///
+ private void OnFramework(Framework _)
+ {
+ while (_forcedFileQueue.TryDequeue(out var tuple))
+ {
+ if (tuple.Item1.ResolvedFiles.Remove(tuple.Item2, out var modPath))
+ tuple.Item1.ModData.RemovePath(modPath.Mod, tuple.Item2);
+ if (tuple.Item3.FullName.Length > 0)
+ tuple.Item1.ResolvedFiles.Add(tuple.Item2, new ModPath(Mod.ForcedFiles, tuple.Item3));
+ }
+ }
}
diff --git a/Penumbra/Meta/MetaFileManager.cs b/Penumbra/Meta/MetaFileManager.cs
index 8e764b14..1cb3319e 100644
--- a/Penumbra/Meta/MetaFileManager.cs
+++ b/Penumbra/Meta/MetaFileManager.cs
@@ -84,13 +84,16 @@ public unsafe class MetaFileManager
: CharacterUtility.TemporarilySetResource(metaIndex, (nint)file.Data, file.Length)
: MetaList.MetaReverter.Disabled;
- public void ApplyDefaultFiles(ModCollection collection)
+ public void ApplyDefaultFiles(ModCollection? collection)
{
if (ActiveCollections.Default != collection || !CharacterUtility.Ready || !Config.EnableMods)
return;
ResidentResources.Reload();
- collection._cache?.Meta.SetFiles();
+ if (collection?._cache == null)
+ CharacterUtility.ResetAll();
+ else
+ collection._cache.Meta.SetFiles();
}
///