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(); } ///