From 67305d507a4e496202a66096050a9ffadedc5f52 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Fri, 27 Dec 2024 11:36:30 +0100 Subject: [PATCH] Extract ModCollectionIdentity. --- OtterGui | 2 +- Penumbra/Api/Api/CollectionApi.cs | 32 +++++----- Penumbra/Api/Api/GameStateApi.cs | 4 +- Penumbra/Api/Api/ModSettingsApi.cs | 6 +- Penumbra/Api/IpcTester/TemporaryIpcTester.cs | 6 +- Penumbra/Api/TempModManager.cs | 4 +- Penumbra/Collections/Cache/CollectionCache.cs | 2 +- .../Cache/CollectionCacheManager.cs | 36 +++++------ .../Collections/CollectionAutoSelector.cs | 2 +- .../Manager/ActiveCollectionMigration.cs | 2 +- .../Collections/Manager/ActiveCollections.cs | 46 +++++++------- .../Collections/Manager/CollectionStorage.cs | 36 +++++------ .../Manager/IndividualCollections.Files.cs | 10 +-- .../Collections/Manager/InheritanceManager.cs | 14 ++--- .../Manager/TempCollectionManager.cs | 16 ++--- Penumbra/Collections/ModCollection.cs | 63 ++++++------------- Penumbra/Collections/ModCollectionIdentity.cs | 42 +++++++++++++ Penumbra/Collections/ModCollectionSave.cs | 16 ++--- Penumbra/Collections/ResolveData.cs | 2 +- Penumbra/CommandHandler.cs | 22 +++---- .../Interop/Hooks/Meta/AtchCallerHook1.cs | 2 +- .../Interop/Hooks/Meta/AtchCallerHook2.cs | 2 +- Penumbra/Interop/PathResolving/MetaState.cs | 2 +- .../Interop/PathResolving/PathDataHandler.cs | 8 +-- .../Processing/ImcFilePostProcessor.cs | 2 +- .../ResourceTree/ResourceTreeFactory.cs | 2 +- Penumbra/Mods/TemporaryMod.cs | 10 +-- Penumbra/Penumbra.cs | 12 ++-- Penumbra/Services/ConfigMigrationService.cs | 8 +-- Penumbra/Services/CrashHandlerService.cs | 4 +- Penumbra/Services/FilenameService.cs | 2 +- Penumbra/UI/Classes/CollectionSelectHeader.cs | 25 ++++---- Penumbra/UI/CollectionTab/CollectionCombo.cs | 4 +- Penumbra/UI/CollectionTab/CollectionPanel.cs | 16 ++--- .../UI/CollectionTab/CollectionSelector.cs | 6 +- Penumbra/UI/CollectionTab/InheritanceUi.cs | 10 +-- Penumbra/UI/ModsTab/ModPanelCollectionsTab.cs | 6 +- Penumbra/UI/ModsTab/ModPanelSettingsTab.cs | 2 +- .../UI/ResourceWatcher/ResourceWatcher.cs | 2 +- .../ResourceWatcher/ResourceWatcherTable.cs | 2 +- Penumbra/UI/Tabs/Debug/DebugTab.cs | 22 +++---- Penumbra/UI/Tabs/ModsTab.cs | 4 +- Penumbra/UI/TutorialService.cs | 6 +- 43 files changed, 270 insertions(+), 252 deletions(-) create mode 100644 Penumbra/Collections/ModCollectionIdentity.cs diff --git a/OtterGui b/OtterGui index d9caded5..fcc96daa 160000 --- a/OtterGui +++ b/OtterGui @@ -1 +1 @@ -Subproject commit d9caded5efb7c9db0a273a43bb5f6d53cf4ace7f +Subproject commit fcc96daa02633f673325c14aeea6b6b568924f1e diff --git a/Penumbra/Api/Api/CollectionApi.cs b/Penumbra/Api/Api/CollectionApi.cs index 04299187..964da1a5 100644 --- a/Penumbra/Api/Api/CollectionApi.cs +++ b/Penumbra/Api/Api/CollectionApi.cs @@ -8,7 +8,7 @@ namespace Penumbra.Api.Api; public class CollectionApi(CollectionManager collections, ApiHelpers helpers) : IPenumbraApiCollection, IApiService { public Dictionary GetCollections() - => collections.Storage.ToDictionary(c => c.Id, c => c.Name); + => collections.Storage.ToDictionary(c => c.Identity.Id, c => c.Identity.Name); public List<(Guid Id, string Name)> GetCollectionsByIdentifier(string identifier) { @@ -17,14 +17,14 @@ public class CollectionApi(CollectionManager collections, ApiHelpers helpers) : 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) - list.Add((collection.Id, collection.Name)); + list.Add((collection.Identity.Id, collection.Identity.Name)); else if (identifier.Length >= 8) - list.AddRange(collections.Storage.Where(c => c.Identifier.StartsWith(identifier, StringComparison.OrdinalIgnoreCase)) - .Select(c => (c.Id, c.Name))); + 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 - .Where(c => string.Equals(c.Name, identifier, StringComparison.OrdinalIgnoreCase) && !list.Contains((c.Id, c.Name))) - .Select(c => (c.Id, c.Name))); + .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))); return list; } @@ -54,7 +54,7 @@ public class CollectionApi(CollectionManager collections, ApiHelpers helpers) : return null; var collection = collections.Active.ByType((CollectionType)type); - return collection == null ? null : (collection.Id, collection.Name); + return collection == null ? null : (collection.Identity.Id, collection.Identity.Name); } internal (Guid Id, string Name)? GetCollection(byte type) @@ -64,17 +64,17 @@ public class CollectionApi(CollectionManager collections, ApiHelpers helpers) : { var id = helpers.AssociatedIdentifier(gameObjectIdx); if (!id.IsValid) - return (false, false, (collections.Active.Default.Id, collections.Active.Default.Name)); + return (false, false, (collections.Active.Default.Identity.Id, collections.Active.Default.Identity.Name)); if (collections.Active.Individuals.TryGetValue(id, out var collection)) - return (true, true, (collection.Id, collection.Name)); + return (true, true, (collection.Identity.Id, collection.Identity.Name)); helpers.AssociatedCollection(gameObjectIdx, out collection); - return (true, false, (collection.Id, collection.Name)); + return (true, false, (collection.Identity.Id, collection.Identity.Name)); } public Guid[] GetCollectionByName(string name) - => collections.Storage.Where(c => string.Equals(name, c.Name, StringComparison.OrdinalIgnoreCase)).Select(c => c.Id).ToArray(); + => 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, bool allowCreateNew, bool allowDelete) @@ -83,7 +83,7 @@ public class CollectionApi(CollectionManager collections, ApiHelpers helpers) : return (PenumbraApiEc.InvalidArgument, null); var oldCollection = collections.Active.ByType((CollectionType)type); - var old = oldCollection != null ? (oldCollection.Id, oldCollection.Name) : new ValueTuple?(); + var old = oldCollection != null ? (oldCollection.Identity.Id, oldCollection.Identity.Name) : new ValueTuple?(); if (collectionId == null) { if (old == null) @@ -106,7 +106,7 @@ public class CollectionApi(CollectionManager collections, ApiHelpers helpers) : collections.Active.CreateSpecialCollection((CollectionType)type); } - else if (old.Value.Item1 == collection.Id) + else if (old.Value.Item1 == collection.Identity.Id) { return (PenumbraApiEc.NothingChanged, old); } @@ -120,10 +120,10 @@ public class CollectionApi(CollectionManager collections, ApiHelpers helpers) : { var id = helpers.AssociatedIdentifier(gameObjectIdx); if (!id.IsValid) - return (PenumbraApiEc.InvalidIdentifier, (collections.Active.Default.Id, collections.Active.Default.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 old = oldCollection != null ? (oldCollection.Id, oldCollection.Name) : new ValueTuple?(); + var old = oldCollection != null ? (oldCollection.Identity.Id, oldCollection.Identity.Name) : new ValueTuple?(); if (collectionId == null) { if (old == null) @@ -148,7 +148,7 @@ public class CollectionApi(CollectionManager collections, ApiHelpers helpers) : var ids = collections.Active.Individuals.GetGroup(id); collections.Active.CreateIndividualCollection(ids); } - else if (old.Value.Item1 == collection.Id) + else if (old.Value.Item1 == collection.Identity.Id) { return (PenumbraApiEc.NothingChanged, old); } diff --git a/Penumbra/Api/Api/GameStateApi.cs b/Penumbra/Api/Api/GameStateApi.cs index c2cae32b..7f70c6bf 100644 --- a/Penumbra/Api/Api/GameStateApi.cs +++ b/Penumbra/Api/Api/GameStateApi.cs @@ -61,7 +61,7 @@ public class GameStateApi : IPenumbraApiGameState, IApiService, IDisposable public unsafe (nint GameObject, (Guid Id, string Name) Collection) GetDrawObjectInfo(nint drawObject) { var data = _collectionResolver.IdentifyCollection((DrawObject*)drawObject, true); - return (data.AssociatedGameObject, (data.ModCollection.Id, data.ModCollection.Name)); + return (data.AssociatedGameObject, (Id: data.ModCollection.Identity.Id, Name: data.ModCollection.Identity.Name)); } public int GetCutsceneParentIndex(int actorIdx) @@ -93,5 +93,5 @@ public class GameStateApi : IPenumbraApiGameState, IApiService, IDisposable } private void OnCreatedCharacterBase(nint gameObject, ModCollection collection, nint drawObject) - => CreatedCharacterBase?.Invoke(gameObject, collection.Id, drawObject); + => CreatedCharacterBase?.Invoke(gameObject, collection.Identity.Id, drawObject); } diff --git a/Penumbra/Api/Api/ModSettingsApi.cs b/Penumbra/Api/Api/ModSettingsApi.cs index 8c34c249..3dc900fc 100644 --- a/Penumbra/Api/Api/ModSettingsApi.cs +++ b/Penumbra/Api/Api/ModSettingsApi.cs @@ -77,7 +77,7 @@ public class ModSettingsApi : IPenumbraApiModSettings, IApiService, IDisposable if (!_collectionManager.Storage.ById(collectionId, out var collection)) return (PenumbraApiEc.CollectionMissing, null); - var settings = collection.Id == Guid.Empty + var settings = collection.Identity.Id == Guid.Empty ? null : ignoreInheritance ? collection.Settings[mod.Index] @@ -217,7 +217,7 @@ public class ModSettingsApi : IPenumbraApiModSettings, IApiService, IDisposable var collection = _collectionResolver.PlayerCollection(); var (settings, parent) = collection[mod.Index]; if (settings is { Enabled: true }) - ModSettingChanged?.Invoke(ModSettingChange.Edited, collection.Id, mod.Identifier, parent != collection); + ModSettingChanged?.Invoke(ModSettingChange.Edited, collection.Identity.Id, mod.Identifier, parent != collection); } private void OnModPathChange(ModPathChangeType type, Mod mod, DirectoryInfo? _1, DirectoryInfo? _2) @@ -227,7 +227,7 @@ public class ModSettingsApi : IPenumbraApiModSettings, IApiService, IDisposable } private void OnModSettingChange(ModCollection collection, ModSettingChange type, Mod? mod, Setting _1, int _2, bool inherited) - => ModSettingChanged?.Invoke(type, collection.Id, mod?.ModPath.Name ?? string.Empty, inherited); + => ModSettingChanged?.Invoke(type, collection.Identity.Id, mod?.ModPath.Name ?? string.Empty, inherited); private void OnModOptionEdited(ModOptionChangeType type, Mod mod, IModGroup? group, IModOption? option, IModDataContainer? container, int moveIndex) diff --git a/Penumbra/Api/IpcTester/TemporaryIpcTester.cs b/Penumbra/Api/IpcTester/TemporaryIpcTester.cs index f6d1c9eb..f3c23831 100644 --- a/Penumbra/Api/IpcTester/TemporaryIpcTester.cs +++ b/Penumbra/Api/IpcTester/TemporaryIpcTester.cs @@ -146,10 +146,10 @@ public class TemporaryIpcTester( using (ImRaii.PushFont(UiBuilder.MonoFont)) { ImGui.TableNextColumn(); - ImGuiUtil.CopyOnClickSelectable(collection.Identifier); + ImGuiUtil.CopyOnClickSelectable(collection.Identity.Identifier); } - ImGuiUtil.DrawTableColumn(collection.Name); + ImGuiUtil.DrawTableColumn(collection.Identity.Name); ImGuiUtil.DrawTableColumn(collection.ResolvedFiles.Count.ToString()); ImGuiUtil.DrawTableColumn(collection.MetaCache?.Count.ToString() ?? "0"); ImGuiUtil.DrawTableColumn(string.Join(", ", @@ -199,7 +199,7 @@ public class TemporaryIpcTester( { PrintList("All", tempMods.ModsForAllCollections); foreach (var (collection, list) in tempMods.Mods) - PrintList(collection.Name, list); + PrintList(collection.Identity.Name, list); } } } diff --git a/Penumbra/Api/TempModManager.cs b/Penumbra/Api/TempModManager.cs index 0b52e64a..b3c6066a 100644 --- a/Penumbra/Api/TempModManager.cs +++ b/Penumbra/Api/TempModManager.cs @@ -85,13 +85,13 @@ public class TempModManager : IDisposable, IService { if (removed) { - Penumbra.Log.Verbose($"Removing temporary Mod {mod.Name} from {collection.AnonymizedName}."); + Penumbra.Log.Verbose($"Removing temporary Mod {mod.Name} from {collection.Identity.AnonymizedName}."); collection.Remove(mod); _communicator.ModSettingChanged.Invoke(collection, ModSettingChange.TemporaryMod, null, Setting.False, 0, false); } else { - Penumbra.Log.Verbose($"Adding {(created ? "new " : string.Empty)}temporary Mod {mod.Name} to {collection.AnonymizedName}."); + Penumbra.Log.Verbose($"Adding {(created ? "new " : string.Empty)}temporary Mod {mod.Name} to {collection.Identity.AnonymizedName}."); collection.Apply(mod, created); _communicator.ModSettingChanged.Invoke(collection, ModSettingChange.TemporaryMod, null, Setting.True, 0, false); } diff --git a/Penumbra/Collections/Cache/CollectionCache.cs b/Penumbra/Collections/Cache/CollectionCache.cs index bc431e88..ad902aac 100644 --- a/Penumbra/Collections/Cache/CollectionCache.cs +++ b/Penumbra/Collections/Cache/CollectionCache.cs @@ -31,7 +31,7 @@ public sealed class CollectionCache : IDisposable public int Calculating = -1; public string AnonymizedName - => _collection.AnonymizedName; + => _collection.Identity.AnonymizedName; public IEnumerable> AllConflicts => ConflictDict.Values; diff --git a/Penumbra/Collections/Cache/CollectionCacheManager.cs b/Penumbra/Collections/Cache/CollectionCacheManager.cs index c3e00502..0a851154 100644 --- a/Penumbra/Collections/Cache/CollectionCacheManager.cs +++ b/Penumbra/Collections/Cache/CollectionCacheManager.cs @@ -114,16 +114,16 @@ public class CollectionCacheManager : IDisposable, IService /// Only creates a new cache, does not update an existing one. public bool CreateCache(ModCollection collection) { - if (collection.Index == ModCollection.Empty.Index) + if (collection.Identity.Index == ModCollection.Empty.Identity.Index) return false; if (collection._cache != null) return false; collection._cache = new CollectionCache(this, collection); - if (collection.Index > 0) + if (collection.Identity.Index > 0) Interlocked.Increment(ref _count); - Penumbra.Log.Verbose($"Created new cache for collection {collection.AnonymizedName}."); + Penumbra.Log.Verbose($"Created new cache for collection {collection.Identity.AnonymizedName}."); return true; } @@ -132,32 +132,32 @@ public class CollectionCacheManager : IDisposable, IService /// Does not create caches. /// public void CalculateEffectiveFileList(ModCollection collection) - => _framework.RegisterImportant(nameof(CalculateEffectiveFileList) + collection.Identifier, + => _framework.RegisterImportant(nameof(CalculateEffectiveFileList) + collection.Identity.Identifier, () => CalculateEffectiveFileListInternal(collection)); private void CalculateEffectiveFileListInternal(ModCollection collection) { // Skip the empty collection. - if (collection.Index == 0) + if (collection.Identity.Index == 0) return; - Penumbra.Log.Debug($"[{Environment.CurrentManagedThreadId}] Recalculating effective file list for {collection.AnonymizedName}"); + Penumbra.Log.Debug($"[{Environment.CurrentManagedThreadId}] Recalculating effective file list for {collection.Identity.AnonymizedName}"); if (!collection.HasCache) { Penumbra.Log.Error( - $"[{Environment.CurrentManagedThreadId}] Recalculating effective file list for {collection.AnonymizedName} failed, no cache exists."); + $"[{Environment.CurrentManagedThreadId}] Recalculating effective file list for {collection.Identity.AnonymizedName} failed, no cache exists."); } else if (collection._cache!.Calculating != -1) { Penumbra.Log.Error( - $"[{Environment.CurrentManagedThreadId}] Recalculating effective file list for {collection.AnonymizedName} failed, already in calculation on [{collection._cache!.Calculating}]."); + $"[{Environment.CurrentManagedThreadId}] Recalculating effective file list for {collection.Identity.AnonymizedName} failed, already in calculation on [{collection._cache!.Calculating}]."); } else { FullRecalculation(collection); Penumbra.Log.Debug( - $"[{Environment.CurrentManagedThreadId}] Recalculation of effective file list for {collection.AnonymizedName} finished."); + $"[{Environment.CurrentManagedThreadId}] Recalculation of effective file list for {collection.Identity.AnonymizedName} finished."); } } @@ -213,7 +213,7 @@ public class CollectionCacheManager : IDisposable, IService else { RemoveCache(old); - if (type is not CollectionType.Inactive && newCollection != null && newCollection.Index != 0 && CreateCache(newCollection)) + if (type is not CollectionType.Inactive && newCollection != null && newCollection.Identity.Index != 0 && CreateCache(newCollection)) CalculateEffectiveFileList(newCollection); if (type is CollectionType.Default) @@ -258,12 +258,12 @@ public class CollectionCacheManager : IDisposable, IService private void RemoveCache(ModCollection? collection) { if (collection != null - && collection.Index > ModCollection.Empty.Index - && collection.Index != _active.Default.Index - && collection.Index != _active.Interface.Index - && collection.Index != _active.Current.Index - && _active.SpecialAssignments.All(c => c.Value.Index != collection.Index) - && _active.Individuals.All(c => c.Collection.Index != collection.Index)) + && collection.Identity.Index > ModCollection.Empty.Identity.Index + && collection.Identity.Index != _active.Default.Identity.Index + && collection.Identity.Index != _active.Interface.Identity.Index + && collection.Identity.Index != _active.Current.Identity.Index + && _active.SpecialAssignments.All(c => c.Value.Identity.Index != collection.Identity.Index) + && _active.Individuals.All(c => c.Collection.Identity.Index != collection.Identity.Index)) ClearCache(collection); } @@ -359,9 +359,9 @@ public class CollectionCacheManager : IDisposable, IService collection._cache!.Dispose(); collection._cache = null; - if (collection.Index > 0) + if (collection.Identity.Index > 0) Interlocked.Decrement(ref _count); - Penumbra.Log.Verbose($"Cleared cache of collection {collection.AnonymizedName}."); + Penumbra.Log.Verbose($"Cleared cache of collection {collection.Identity.AnonymizedName}."); } /// diff --git a/Penumbra/Collections/CollectionAutoSelector.cs b/Penumbra/Collections/CollectionAutoSelector.cs index e24fa6a9..68dac914 100644 --- a/Penumbra/Collections/CollectionAutoSelector.cs +++ b/Penumbra/Collections/CollectionAutoSelector.cs @@ -59,7 +59,7 @@ public sealed class CollectionAutoSelector : IService, IDisposable return; var collection = _resolver.PlayerCollection(); - Penumbra.Log.Debug($"Setting current collection to {collection.Identifier} through automatic collection selection."); + Penumbra.Log.Debug($"Setting current collection to {collection.Identity.Identifier} through automatic collection selection."); _collections.SetCollection(collection, CollectionType.Current); } diff --git a/Penumbra/Collections/Manager/ActiveCollectionMigration.cs b/Penumbra/Collections/Manager/ActiveCollectionMigration.cs index 19f781fc..b4af0998 100644 --- a/Penumbra/Collections/Manager/ActiveCollectionMigration.cs +++ b/Penumbra/Collections/Manager/ActiveCollectionMigration.cs @@ -48,7 +48,7 @@ public static class ActiveCollectionMigration if (!storage.ByName(collectionName, out var collection)) { Penumbra.Messager.NotificationMessage( - $"Last choice of <{player}>'s Collection {collectionName} is not available, reset to {ModCollection.Empty.Name}.", NotificationType.Warning); + $"Last choice of <{player}>'s Collection {collectionName} is not available, reset to {ModCollection.Empty.Identity.Name}.", NotificationType.Warning); dict.Add(player, ModCollection.Empty); } else diff --git a/Penumbra/Collections/Manager/ActiveCollections.cs b/Penumbra/Collections/Manager/ActiveCollections.cs index 60f9a427..07fcb430 100644 --- a/Penumbra/Collections/Manager/ActiveCollections.cs +++ b/Penumbra/Collections/Manager/ActiveCollections.cs @@ -219,7 +219,7 @@ public class ActiveCollections : ISavable, IDisposable, IService _ => null, }; - if (oldCollection == null || collection == oldCollection || collection.Index >= _storage.Count) + if (oldCollection == null || collection == oldCollection || collection.Identity.Index >= _storage.Count) return; switch (collectionType) @@ -262,13 +262,13 @@ public class ActiveCollections : ISavable, IDisposable, IService var jObj = new JObject { { nameof(Version), Version }, - { nameof(Default), Default.Id }, - { nameof(Interface), Interface.Id }, - { nameof(Current), Current.Id }, + { nameof(Default), Default.Identity.Id }, + { nameof(Interface), Interface.Identity.Id }, + { nameof(Current), Current.Identity.Id }, }; foreach (var (type, collection) in SpecialCollections.WithIndex().Where(p => p.Value != null) .Select(p => ((CollectionType)p.Index, p.Value!))) - jObj.Add(type.ToString(), collection.Id); + jObj.Add(type.ToString(), collection.Identity.Id); jObj.Add(nameof(Individuals), Individuals.ToJObject()); using var j = new JsonTextWriter(writer); @@ -300,7 +300,7 @@ public class ActiveCollections : ISavable, IDisposable, IService if (oldCollection == Interface) SetCollection(ModCollection.Empty, CollectionType.Interface); if (oldCollection == Current) - SetCollection(Default.Index > ModCollection.Empty.Index ? Default : _storage.DefaultNamed, CollectionType.Current); + SetCollection(Default.Identity.Index > ModCollection.Empty.Identity.Index ? Default : _storage.DefaultNamed, CollectionType.Current); for (var i = 0; i < SpecialCollections.Length; ++i) { @@ -325,11 +325,11 @@ public class ActiveCollections : ISavable, IDisposable, IService { var configChanged = false; // Load the default collection. If the name does not exist take the empty collection. - var defaultName = jObject[nameof(Default)]?.ToObject() ?? ModCollection.Empty.Name; + var defaultName = jObject[nameof(Default)]?.ToObject() ?? ModCollection.Empty.Identity.Name; if (!_storage.ByName(defaultName, out var defaultCollection)) { Penumbra.Messager.NotificationMessage( - $"Last choice of {TutorialService.DefaultCollection} {defaultName} is not available, reset to {ModCollection.Empty.Name}.", + $"Last choice of {TutorialService.DefaultCollection} {defaultName} is not available, reset to {ModCollection.Empty.Identity.Name}.", NotificationType.Warning); Default = ModCollection.Empty; configChanged = true; @@ -340,11 +340,11 @@ public class ActiveCollections : ISavable, IDisposable, IService } // Load the interface collection. If no string is set, use the name of whatever was set as Default. - var interfaceName = jObject[nameof(Interface)]?.ToObject() ?? Default.Name; + var interfaceName = jObject[nameof(Interface)]?.ToObject() ?? Default.Identity.Name; if (!_storage.ByName(interfaceName, out var interfaceCollection)) { Penumbra.Messager.NotificationMessage( - $"Last choice of {TutorialService.InterfaceCollection} {interfaceName} is not available, reset to {ModCollection.Empty.Name}.", + $"Last choice of {TutorialService.InterfaceCollection} {interfaceName} is not available, reset to {ModCollection.Empty.Identity.Name}.", NotificationType.Warning); Interface = ModCollection.Empty; configChanged = true; @@ -355,11 +355,11 @@ public class ActiveCollections : ISavable, IDisposable, IService } // Load the current collection. - var currentName = jObject[nameof(Current)]?.ToObject() ?? Default.Name; + var currentName = jObject[nameof(Current)]?.ToObject() ?? Default.Identity.Name; if (!_storage.ByName(currentName, out var currentCollection)) { Penumbra.Messager.NotificationMessage( - $"Last choice of {TutorialService.SelectedCollection} {currentName} is not available, reset to {ModCollection.DefaultCollectionName}.", + $"Last choice of {TutorialService.SelectedCollection} {currentName} is not available, reset to {ModCollectionIdentity.DefaultCollectionName}.", NotificationType.Warning); Current = _storage.DefaultNamed; configChanged = true; @@ -404,7 +404,7 @@ public class ActiveCollections : ISavable, IDisposable, IService if (!_storage.ById(defaultId, out var defaultCollection)) { Penumbra.Messager.NotificationMessage( - $"Last choice of {TutorialService.DefaultCollection} {defaultId} is not available, reset to {ModCollection.Empty.Name}.", + $"Last choice of {TutorialService.DefaultCollection} {defaultId} is not available, reset to {ModCollection.Empty.Identity.Name}.", NotificationType.Warning); Default = ModCollection.Empty; configChanged = true; @@ -415,11 +415,11 @@ public class ActiveCollections : ISavable, IDisposable, IService } // Load the interface collection. If no string is set, use the name of whatever was set as Default. - var interfaceId = jObject[nameof(Interface)]?.ToObject() ?? Default.Id; + var interfaceId = jObject[nameof(Interface)]?.ToObject() ?? Default.Identity.Id; if (!_storage.ById(interfaceId, out var interfaceCollection)) { Penumbra.Messager.NotificationMessage( - $"Last choice of {TutorialService.InterfaceCollection} {interfaceId} is not available, reset to {ModCollection.Empty.Name}.", + $"Last choice of {TutorialService.InterfaceCollection} {interfaceId} is not available, reset to {ModCollection.Empty.Identity.Name}.", NotificationType.Warning); Interface = ModCollection.Empty; configChanged = true; @@ -430,11 +430,11 @@ public class ActiveCollections : ISavable, IDisposable, IService } // Load the current collection. - var currentId = jObject[nameof(Current)]?.ToObject() ?? _storage.DefaultNamed.Id; + var currentId = jObject[nameof(Current)]?.ToObject() ?? _storage.DefaultNamed.Identity.Id; if (!_storage.ById(currentId, out var currentCollection)) { Penumbra.Messager.NotificationMessage( - $"Last choice of {TutorialService.SelectedCollection} {currentId} is not available, reset to {ModCollection.DefaultCollectionName}.", + $"Last choice of {TutorialService.SelectedCollection} {currentId} is not available, reset to {ModCollectionIdentity.DefaultCollectionName}.", NotificationType.Warning); Current = _storage.DefaultNamed; configChanged = true; @@ -587,7 +587,7 @@ public class ActiveCollections : ISavable, IDisposable, IService case IdentifierType.Player when id.HomeWorld != ushort.MaxValue: { var global = ByType(CollectionType.Individual, _actors.CreatePlayer(id.PlayerName, ushort.MaxValue)); - return global?.Index == checkAssignment.Index + return (global != null ? global.Identity.Index : null) == checkAssignment.Identity.Index ? "Assignment is redundant due to an identical Any-World assignment existing.\nYou can remove it." : string.Empty; } @@ -596,12 +596,12 @@ public class ActiveCollections : ISavable, IDisposable, IService { var global = ByType(CollectionType.Individual, _actors.CreateOwned(id.PlayerName, ushort.MaxValue, id.Kind, id.DataId)); - if (global?.Index == checkAssignment.Index) + if ((global != null ? global.Identity.Index : null) == checkAssignment.Identity.Index) return "Assignment is redundant due to an identical Any-World assignment existing.\nYou can remove it."; } var unowned = ByType(CollectionType.Individual, _actors.CreateNpc(id.Kind, id.DataId)); - return unowned?.Index == checkAssignment.Index + return (unowned != null ? unowned.Identity.Index : null) == checkAssignment.Identity.Index ? "Assignment is redundant due to an identical unowned NPC assignment existing.\nYou can remove it." : string.Empty; } @@ -617,7 +617,7 @@ public class ActiveCollections : ISavable, IDisposable, IService if (maleNpc == null) { maleNpc = Default; - if (maleNpc.Index != checkAssignment.Index) + if (maleNpc.Identity.Index != checkAssignment.Identity.Index) return string.Empty; collection1 = CollectionType.Default; @@ -626,7 +626,7 @@ public class ActiveCollections : ISavable, IDisposable, IService if (femaleNpc == null) { femaleNpc = Default; - if (femaleNpc.Index != checkAssignment.Index) + if (femaleNpc.Identity.Index != checkAssignment.Identity.Index) return string.Empty; collection2 = CollectionType.Default; @@ -646,7 +646,7 @@ public class ActiveCollections : ISavable, IDisposable, IService if (assignment == null) continue; - if (assignment.Index == checkAssignment.Index) + if (assignment.Identity.Index == checkAssignment.Identity.Index) return $"Assignment is currently redundant due to overwriting {parentType.ToName()} with an identical collection.\nYou can remove it."; } diff --git a/Penumbra/Collections/Manager/CollectionStorage.cs b/Penumbra/Collections/Manager/CollectionStorage.cs index cdbe11dc..2ed395ae 100644 --- a/Penumbra/Collections/Manager/CollectionStorage.cs +++ b/Penumbra/Collections/Manager/CollectionStorage.cs @@ -41,7 +41,7 @@ public class CollectionStorage : IReadOnlyList, IDisposable, ISer public ModCollection CreateFromData(Guid id, string name, int version, Dictionary allSettings, IReadOnlyList inheritances) { - var newCollection = ModCollection.CreateFromData(_saveService, _modStorage, id, name, CurrentCollectionId, version, Count, allSettings, + var newCollection = ModCollection.CreateFromData(_saveService, _modStorage, new ModCollectionIdentity(id, CurrentCollectionId, name, Count), version, allSettings, inheritances); _collectionsByLocal[CurrentCollectionId] = newCollection; CurrentCollectionId += 1; @@ -57,7 +57,7 @@ public class CollectionStorage : IReadOnlyList, IDisposable, ISer } public void Delete(ModCollection collection) - => _collectionsByLocal.Remove(collection.LocalId); + => _collectionsByLocal.Remove(collection.Identity.LocalId); /// The empty collection is always available at Index 0. private readonly List _collections = @@ -92,7 +92,7 @@ public class CollectionStorage : IReadOnlyList, IDisposable, ISer public bool ByName(string name, [NotNullWhen(true)] out ModCollection? collection) { if (name.Length != 0) - return _collections.FindFirst(c => string.Equals(c.Name, name, StringComparison.OrdinalIgnoreCase), out collection); + return _collections.FindFirst(c => string.Equals(c.Identity.Name, name, StringComparison.OrdinalIgnoreCase), out collection); collection = ModCollection.Empty; return true; @@ -102,7 +102,7 @@ public class CollectionStorage : IReadOnlyList, IDisposable, ISer public bool ById(Guid id, [NotNullWhen(true)] out ModCollection? collection) { if (id != Guid.Empty) - return _collections.FindFirst(c => c.Id == id, out collection); + return _collections.FindFirst(c => c.Identity.Id == id, out collection); collection = ModCollection.Empty; return true; @@ -158,7 +158,7 @@ public class CollectionStorage : IReadOnlyList, IDisposable, ISer var newCollection = Create(name, _collections.Count, duplicate); _collections.Add(newCollection); _saveService.ImmediateSave(new ModCollectionSave(_modStorage, newCollection)); - Penumbra.Messager.NotificationMessage($"Created new collection {newCollection.AnonymizedName}.", NotificationType.Success, false); + Penumbra.Messager.NotificationMessage($"Created new collection {newCollection.Identity.AnonymizedName}.", NotificationType.Success, false); _communicator.CollectionChange.Invoke(CollectionType.Inactive, null, newCollection, string.Empty); return true; } @@ -168,13 +168,13 @@ public class CollectionStorage : IReadOnlyList, IDisposable, ISer /// public bool RemoveCollection(ModCollection collection) { - if (collection.Index <= ModCollection.Empty.Index || collection.Index >= _collections.Count) + if (collection.Identity.Index <= ModCollection.Empty.Identity.Index || collection.Identity.Index >= _collections.Count) { Penumbra.Messager.NotificationMessage("Can not remove the empty collection.", NotificationType.Error, false); return false; } - if (collection.Index == DefaultNamed.Index) + if (collection.Identity.Index == DefaultNamed.Identity.Index) { Penumbra.Messager.NotificationMessage("Can not remove the default collection.", NotificationType.Error, false); return false; @@ -182,13 +182,13 @@ public class CollectionStorage : IReadOnlyList, IDisposable, ISer Delete(collection); _saveService.ImmediateDelete(new ModCollectionSave(_modStorage, collection)); - _collections.RemoveAt(collection.Index); + _collections.RemoveAt(collection.Identity.Index); // Update indices. - for (var i = collection.Index; i < Count; ++i) - _collections[i].Index = i; - _collectionsByLocal.Remove(collection.LocalId); + for (var i = collection.Identity.Index; i < Count; ++i) + _collections[i].Identity.Index = i; + _collectionsByLocal.Remove(collection.Identity.LocalId); - Penumbra.Messager.NotificationMessage($"Deleted collection {collection.AnonymizedName}.", NotificationType.Success, false); + Penumbra.Messager.NotificationMessage($"Deleted collection {collection.Identity.AnonymizedName}.", NotificationType.Success, false); _communicator.CollectionChange.Invoke(CollectionType.Inactive, collection, null, string.Empty); return true; } @@ -246,13 +246,13 @@ public class CollectionStorage : IReadOnlyList, IDisposable, ISer { File.Move(file.FullName, correctName, false); Penumbra.Messager.NotificationMessage( - $"Collection {file.Name} does not correspond to {collection.Identifier}, renamed.", + $"Collection {file.Name} does not correspond to {collection.Identity.Identifier}, renamed.", NotificationType.Warning); } catch (Exception ex) { Penumbra.Messager.NotificationMessage( - $"Collection {file.Name} does not correspond to {collection.Identifier}, rename failed:\n{ex}", + $"Collection {file.Name} does not correspond to {collection.Identity.Identifier}, rename failed:\n{ex}", NotificationType.Warning); } } @@ -273,7 +273,7 @@ public class CollectionStorage : IReadOnlyList, IDisposable, ISer catch (Exception e) { Penumbra.Messager.NotificationMessage(e, - $"Collection {file.Name} does not correspond to {collection.Identifier}, but could not rename.", + $"Collection {file.Name} does not correspond to {collection.Identity.Identifier}, but could not rename.", NotificationType.Error); } @@ -291,14 +291,14 @@ public class CollectionStorage : IReadOnlyList, IDisposable, ISer /// private ModCollection SetDefaultNamedCollection() { - if (ByName(ModCollection.DefaultCollectionName, out var collection)) + if (ByName(ModCollectionIdentity.DefaultCollectionName, out var collection)) return collection; - if (AddCollection(ModCollection.DefaultCollectionName, null)) + if (AddCollection(ModCollectionIdentity.DefaultCollectionName, null)) return _collections[^1]; Penumbra.Messager.NotificationMessage( - $"Unknown problem creating a collection with the name {ModCollection.DefaultCollectionName}, which is required to exist.", + $"Unknown problem creating a collection with the name {ModCollectionIdentity.DefaultCollectionName}, which is required to exist.", NotificationType.Error); return Count > 1 ? _collections[1] : _collections[0]; } diff --git a/Penumbra/Collections/Manager/IndividualCollections.Files.cs b/Penumbra/Collections/Manager/IndividualCollections.Files.cs index f7a26384..60e9fc5f 100644 --- a/Penumbra/Collections/Manager/IndividualCollections.Files.cs +++ b/Penumbra/Collections/Manager/IndividualCollections.Files.cs @@ -18,7 +18,7 @@ public partial class IndividualCollections foreach (var (name, identifiers, collection) in Assignments) { var tmp = identifiers[0].ToJson(); - tmp.Add("Collection", collection.Id); + tmp.Add("Collection", collection.Identity.Id); tmp.Add("Display", name); ret.Add(tmp); } @@ -182,7 +182,7 @@ public partial class IndividualCollections Penumbra.Log.Information($"Migrated {name} ({kind.ToName()}) to NPC Identifiers [{ids}]."); else Penumbra.Messager.NotificationMessage( - $"Could not migrate {name} ({collection.AnonymizedName}) which was assumed to be a {kind.ToName()} with IDs [{ids}], please look through your individual collections.", + $"Could not migrate {name} ({collection.Identity.AnonymizedName}) which was assumed to be a {kind.ToName()} with IDs [{ids}], please look through your individual collections.", NotificationType.Error); } // If it is not a valid NPC name, check if it can be a player name. @@ -192,16 +192,16 @@ public partial class IndividualCollections var shortName = string.Join(" ", name.Split().Select(n => $"{n[0]}.")); // Try to migrate the player name without logging full names. if (Add($"{name} ({_actors.Data.ToWorldName(identifier.HomeWorld)})", [identifier], collection)) - Penumbra.Log.Information($"Migrated {shortName} ({collection.AnonymizedName}) to Player Identifier."); + Penumbra.Log.Information($"Migrated {shortName} ({collection.Identity.AnonymizedName}) to Player Identifier."); else Penumbra.Messager.NotificationMessage( - $"Could not migrate {shortName} ({collection.AnonymizedName}), please look through your individual collections.", + $"Could not migrate {shortName} ({collection.Identity.AnonymizedName}), please look through your individual collections.", NotificationType.Error); } else { Penumbra.Messager.NotificationMessage( - $"Could not migrate {name} ({collection.AnonymizedName}), which can not be a player name nor is it a known NPC name, please look through your individual collections.", + $"Could not migrate {name} ({collection.Identity.AnonymizedName}), which can not be a player name nor is it a known NPC name, please look through your individual collections.", NotificationType.Error); } } diff --git a/Penumbra/Collections/Manager/InheritanceManager.cs b/Penumbra/Collections/Manager/InheritanceManager.cs index bc1a362c..e003ad6b 100644 --- a/Penumbra/Collections/Manager/InheritanceManager.cs +++ b/Penumbra/Collections/Manager/InheritanceManager.cs @@ -89,7 +89,7 @@ public class InheritanceManager : IDisposable, IService _saveService.QueueSave(new ModCollectionSave(_modStorage, inheritor)); _communicator.CollectionInheritanceChanged.Invoke(inheritor, false); RecurseInheritanceChanges(inheritor); - Penumbra.Log.Debug($"Removed {parent.AnonymizedName} from {inheritor.AnonymizedName} inheritances."); + Penumbra.Log.Debug($"Removed {parent.Identity.AnonymizedName} from {inheritor.Identity.AnonymizedName} inheritances."); } /// Order in the inheritance list is relevant. @@ -101,7 +101,7 @@ public class InheritanceManager : IDisposable, IService _saveService.QueueSave(new ModCollectionSave(_modStorage, inheritor)); _communicator.CollectionInheritanceChanged.Invoke(inheritor, false); RecurseInheritanceChanges(inheritor); - Penumbra.Log.Debug($"Moved {inheritor.AnonymizedName}s inheritance {from} to {to}."); + Penumbra.Log.Debug($"Moved {inheritor.Identity.AnonymizedName}s inheritance {from} to {to}."); } /// @@ -119,7 +119,7 @@ public class InheritanceManager : IDisposable, IService RecurseInheritanceChanges(inheritor); } - Penumbra.Log.Debug($"Added {parent.AnonymizedName} to {inheritor.AnonymizedName} inheritances."); + Penumbra.Log.Debug($"Added {parent.Identity.AnonymizedName} to {inheritor.Identity.AnonymizedName} inheritances."); return true; } @@ -143,23 +143,23 @@ public class InheritanceManager : IDisposable, IService continue; changes = true; - Penumbra.Messager.NotificationMessage($"{collection.Name} can not inherit from {subCollection.Name}, removed.", + Penumbra.Messager.NotificationMessage($"{collection.Identity.Name} can not inherit from {subCollection.Identity.Name}, removed.", NotificationType.Warning); } else if (_storage.ByName(subCollectionName, out subCollection)) { changes = true; - Penumbra.Log.Information($"Migrating inheritance for {collection.AnonymizedName} from name to GUID."); + Penumbra.Log.Information($"Migrating inheritance for {collection.Identity.AnonymizedName} from name to GUID."); if (AddInheritance(collection, subCollection, false)) continue; - Penumbra.Messager.NotificationMessage($"{collection.Name} can not inherit from {subCollection.Name}, removed.", + Penumbra.Messager.NotificationMessage($"{collection.Identity.Name} can not inherit from {subCollection.Identity.Name}, removed.", NotificationType.Warning); } else { Penumbra.Messager.NotificationMessage( - $"Inherited collection {subCollectionName} for {collection.AnonymizedName} does not exist, it was removed.", + $"Inherited collection {subCollectionName} for {collection.Identity.AnonymizedName} does not exist, it was removed.", NotificationType.Warning); changes = true; } diff --git a/Penumbra/Collections/Manager/TempCollectionManager.cs b/Penumbra/Collections/Manager/TempCollectionManager.cs index e5b844c8..8aab5297 100644 --- a/Penumbra/Collections/Manager/TempCollectionManager.cs +++ b/Penumbra/Collections/Manager/TempCollectionManager.cs @@ -44,7 +44,7 @@ public class TempCollectionManager : IDisposable, IService => _customCollections.Values; public bool CollectionByName(string name, [NotNullWhen(true)] out ModCollection? collection) - => _customCollections.Values.FindFirst(c => string.Equals(name, c.Name, StringComparison.OrdinalIgnoreCase), out collection); + => _customCollections.Values.FindFirst(c => string.Equals(name, c.Identity.Name, StringComparison.OrdinalIgnoreCase), out collection); public bool CollectionById(Guid id, [NotNullWhen(true)] out ModCollection? collection) => _customCollections.TryGetValue(id, out collection); @@ -54,12 +54,12 @@ public class TempCollectionManager : IDisposable, IService if (GlobalChangeCounter == int.MaxValue) GlobalChangeCounter = 0; var collection = _storage.CreateTemporary(name, ~Count, GlobalChangeCounter++); - Penumbra.Log.Debug($"Creating temporary collection {collection.Name} with {collection.Id}."); - if (_customCollections.TryAdd(collection.Id, collection)) + Penumbra.Log.Debug($"Creating temporary collection {collection.Identity.Name} with {collection.Identity.Id}."); + if (_customCollections.TryAdd(collection.Identity.Id, collection)) { // Temporary collection created. _communicator.CollectionChange.Invoke(CollectionType.Temporary, null, collection, string.Empty); - return collection.Id; + return collection.Identity.Id; } return Guid.Empty; @@ -74,7 +74,7 @@ public class TempCollectionManager : IDisposable, IService } _storage.Delete(collection); - Penumbra.Log.Debug($"Deleted temporary collection {collection.Id}."); + Penumbra.Log.Debug($"Deleted temporary collection {collection.Identity.Id}."); GlobalChangeCounter += Math.Max(collection.Counters.Change + 1 - GlobalChangeCounter, 0); for (var i = 0; i < Collections.Count; ++i) { @@ -83,7 +83,7 @@ public class TempCollectionManager : IDisposable, IService // Temporary collection assignment removed. _communicator.CollectionChange.Invoke(CollectionType.Temporary, collection, null, Collections[i].DisplayName); - Penumbra.Log.Verbose($"Unassigned temporary collection {collection.Id} from {Collections[i].DisplayName}."); + Penumbra.Log.Verbose($"Unassigned temporary collection {collection.Identity.Id} from {Collections[i].DisplayName}."); Collections.Delete(i--); } @@ -96,7 +96,7 @@ public class TempCollectionManager : IDisposable, IService return false; // Temporary collection assignment added. - Penumbra.Log.Verbose($"Assigned temporary collection {collection.AnonymizedName} to {Collections.Last().DisplayName}."); + Penumbra.Log.Verbose($"Assigned temporary collection {collection.Identity.AnonymizedName} to {Collections.Last().DisplayName}."); _communicator.CollectionChange.Invoke(CollectionType.Temporary, null, collection, Collections.Last().DisplayName); return true; } @@ -127,6 +127,6 @@ public class TempCollectionManager : IDisposable, IService return false; var identifier = _actors.CreatePlayer(byteString, worldId); - return Collections.TryGetValue(identifier, out var collection) && RemoveTemporaryCollection(collection.Id); + return Collections.TryGetValue(identifier, out var collection) && RemoveTemporaryCollection(collection.Identity.Id); } } diff --git a/Penumbra/Collections/ModCollection.cs b/Penumbra/Collections/ModCollection.cs index 95e78da0..9b33c1f4 100644 --- a/Penumbra/Collections/ModCollection.cs +++ b/Penumbra/Collections/ModCollection.cs @@ -13,42 +13,21 @@ namespace Penumbra.Collections; /// - Index is the collections index in the ModCollection.Manager /// - Settings has the same size as ModManager.Mods. /// - any change in settings or inheritance of the collection causes a Save. -/// - the name can not contain invalid path characters and has to be unique when lower-cased. /// public partial class ModCollection { - public const int CurrentVersion = 2; - public const string DefaultCollectionName = "Default"; - public const string EmptyCollectionName = "None"; + public const int CurrentVersion = 2; /// /// Create the always available Empty Collection that will always sit at index 0, /// can not be deleted and does never create a cache. /// - public static readonly ModCollection Empty = new(Guid.Empty, EmptyCollectionName, LocalCollectionId.Zero, 0, 0, CurrentVersion, [], [], []); + public static readonly ModCollection Empty = new(ModCollectionIdentity.Empty, 0, CurrentVersion, [], [], []); - /// The name of a collection. - public string Name { get; set; } - - public Guid Id { get; } - - public LocalCollectionId LocalId { get; } - - public string Identifier - => Id.ToString(); - - public string ShortIdentifier - => Identifier[..8]; + public ModCollectionIdentity Identity; public override string ToString() - => Name.Length > 0 ? Name : ShortIdentifier; - - /// Get the first two letters of a collection name and its Index (or None if it is the empty collection). - public string AnonymizedName - => this == Empty ? Empty.Name : Name == DefaultCollectionName ? Name : ShortIdentifier; - - /// The index of the collection is set and kept up-to-date by the CollectionManager. - public int Index { get; internal set; } + => Identity.ToString(); public CollectionCounters Counters; @@ -90,7 +69,7 @@ public partial class ModCollection { get { - if (Index <= 0) + if (Identity.Index <= 0) return (ModSettings.Empty, this); foreach (var collection in GetFlattenedInheritance()) @@ -114,17 +93,17 @@ public partial class ModCollection public ModCollection Duplicate(string name, LocalCollectionId localId, int index) { Debug.Assert(index > 0, "Collection duplicated with non-positive index."); - return new ModCollection(Guid.NewGuid(), name, localId, index, 0, CurrentVersion, Settings.Select(s => s?.DeepCopy()).ToList(), - [.. DirectlyInheritsFrom], UnusedSettings.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.DeepCopy())); + return new ModCollection(ModCollectionIdentity.New(name, localId, index), 0, CurrentVersion, + Settings.Select(s => s?.DeepCopy()).ToList(), [.. DirectlyInheritsFrom], + UnusedSettings.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.DeepCopy())); } /// Constructor for reading from files. - public static ModCollection CreateFromData(SaveService saver, ModStorage mods, Guid id, string name, LocalCollectionId localId, int version, - int index, + public static ModCollection CreateFromData(SaveService saver, ModStorage mods, ModCollectionIdentity identity, int version, Dictionary allSettings, IReadOnlyList inheritances) { - Debug.Assert(index > 0, "Collection read with non-positive index."); - var ret = new ModCollection(id, name, localId, index, 0, version, [], [], allSettings) + Debug.Assert(identity.Index > 0, "Collection read with non-positive index."); + var ret = new ModCollection(identity, 0, version, [], [], allSettings) { InheritanceByName = inheritances, }; @@ -137,7 +116,7 @@ public partial class ModCollection public static ModCollection CreateTemporary(string name, LocalCollectionId localId, int index, int changeCounter) { Debug.Assert(index < 0, "Temporary collection created with non-negative index."); - var ret = new ModCollection(Guid.NewGuid(), name, localId, index, changeCounter, CurrentVersion, [], [], []); + var ret = new ModCollection(ModCollectionIdentity.New(name, localId, index), changeCounter, CurrentVersion, [], [], []); return ret; } @@ -145,9 +124,8 @@ public partial class ModCollection public static ModCollection CreateEmpty(string name, LocalCollectionId localId, int index, int modCount) { Debug.Assert(index >= 0, "Empty collection created with negative index."); - return new ModCollection(Guid.NewGuid(), name, localId, index, 0, CurrentVersion, - Enumerable.Repeat((ModSettings?)null, modCount).ToList(), [], - []); + return new ModCollection(ModCollectionIdentity.New(name, localId, index), 0, CurrentVersion, + Enumerable.Repeat((ModSettings?)null, modCount).ToList(), [], []); } /// Add settings for a new appended mod, by checking if the mod had settings from a previous deletion. @@ -195,16 +173,13 @@ public partial class ModCollection saver.ImmediateSave(new ModCollectionSave(mods, this)); } - private ModCollection(Guid id, string name, LocalCollectionId localId, int index, int changeCounter, int version, - List appliedSettings, List inheritsFrom, Dictionary settings) + private ModCollection(ModCollectionIdentity identity, int changeCounter, int version, List appliedSettings, + List inheritsFrom, Dictionary settings) { - Name = name; - Id = id; - LocalId = localId; - Index = index; + Identity = identity; Counters = new CollectionCounters(changeCounter); - Settings = appliedSettings; - UnusedSettings = settings; + Settings = appliedSettings; + UnusedSettings = settings; DirectlyInheritsFrom = inheritsFrom; foreach (var c in DirectlyInheritsFrom) ((List)c.DirectParentOf).Add(this); diff --git a/Penumbra/Collections/ModCollectionIdentity.cs b/Penumbra/Collections/ModCollectionIdentity.cs new file mode 100644 index 00000000..c7f60005 --- /dev/null +++ b/Penumbra/Collections/ModCollectionIdentity.cs @@ -0,0 +1,42 @@ +using OtterGui; +using Penumbra.Collections.Manager; + +namespace Penumbra.Collections; + +public struct ModCollectionIdentity(Guid id, LocalCollectionId localId) +{ + public const string DefaultCollectionName = "Default"; + public const string EmptyCollectionName = "None"; + + public static readonly ModCollectionIdentity Empty = new(Guid.Empty, LocalCollectionId.Zero, EmptyCollectionName, 0); + + public string Name { get; set; } + public Guid Id { get; } = id; + public LocalCollectionId LocalId { get; } = localId; + + /// The index of the collection is set and kept up-to-date by the CollectionManager. + public int Index { get; internal set; } + + public string Identifier + => Id.ToString(); + + public string ShortIdentifier + => Id.ShortGuid(); + + /// Get the short identifier of a collection unless it is a well-known collection name. + public string AnonymizedName + => Id == Guid.Empty ? EmptyCollectionName : Name == DefaultCollectionName ? Name : ShortIdentifier; + + public override string ToString() + => Name.Length > 0 ? Name : ShortIdentifier; + + public ModCollectionIdentity(Guid id, LocalCollectionId localId, string name, int index) + : this(id, localId) + { + Name = name; + Index = index; + } + + public static ModCollectionIdentity New(string name, LocalCollectionId id, int index) + => new(Guid.NewGuid(), id, name, index); +} diff --git a/Penumbra/Collections/ModCollectionSave.cs b/Penumbra/Collections/ModCollectionSave.cs index e6bb069b..6e1b51ac 100644 --- a/Penumbra/Collections/ModCollectionSave.cs +++ b/Penumbra/Collections/ModCollectionSave.cs @@ -15,7 +15,7 @@ internal readonly struct ModCollectionSave(ModStorage modStorage, ModCollection => fileNames.CollectionFile(modCollection); public string LogName(string _) - => modCollection.AnonymizedName; + => modCollection.Identity.AnonymizedName; public string TypeName => "Collection"; @@ -28,10 +28,10 @@ internal readonly struct ModCollectionSave(ModStorage modStorage, ModCollection j.WriteStartObject(); j.WritePropertyName("Version"); j.WriteValue(ModCollection.CurrentVersion); - j.WritePropertyName(nameof(ModCollection.Id)); - j.WriteValue(modCollection.Identifier); - j.WritePropertyName(nameof(ModCollection.Name)); - j.WriteValue(modCollection.Name); + j.WritePropertyName(nameof(ModCollectionIdentity.Id)); + j.WriteValue(modCollection.Identity.Identifier); + j.WritePropertyName(nameof(ModCollectionIdentity.Name)); + j.WriteValue(modCollection.Identity.Name); j.WritePropertyName(nameof(ModCollection.Settings)); // Write all used and unused settings by mod directory name. @@ -57,7 +57,7 @@ internal readonly struct ModCollectionSave(ModStorage modStorage, ModCollection // Inherit by collection name. j.WritePropertyName("Inheritance"); - x.Serialize(j, modCollection.InheritanceByName ?? modCollection.DirectlyInheritsFrom.Select(c => c.Identifier)); + x.Serialize(j, modCollection.InheritanceByName ?? modCollection.DirectlyInheritsFrom.Select(c => c.Identity.Identifier)); j.WriteEndObject(); } @@ -79,8 +79,8 @@ internal readonly struct ModCollectionSave(ModStorage modStorage, ModCollection { var obj = JObject.Parse(File.ReadAllText(file.FullName)); version = obj["Version"]?.ToObject() ?? 0; - name = obj[nameof(ModCollection.Name)]?.ToObject() ?? string.Empty; - id = obj[nameof(ModCollection.Id)]?.ToObject() ?? (version == 1 ? Guid.NewGuid() : Guid.Empty); + name = obj[nameof(ModCollectionIdentity.Name)]?.ToObject() ?? string.Empty; + id = obj[nameof(ModCollectionIdentity.Id)]?.ToObject() ?? (version == 1 ? Guid.NewGuid() : Guid.Empty); // Custom deserialization that is converted with the constructor. settings = obj[nameof(ModCollection.Settings)]?.ToObject>() ?? settings; inheritance = obj["Inheritance"]?.ToObject>() ?? inheritance; diff --git a/Penumbra/Collections/ResolveData.cs b/Penumbra/Collections/ResolveData.cs index 8fe160b3..bda877ff 100644 --- a/Penumbra/Collections/ResolveData.cs +++ b/Penumbra/Collections/ResolveData.cs @@ -23,7 +23,7 @@ public readonly struct ResolveData(ModCollection collection, nint gameObject) { } public override string ToString() - => ModCollection.Name; + => ModCollection.Identity.Name; } public static class ResolveDataExtensions diff --git a/Penumbra/CommandHandler.cs b/Penumbra/CommandHandler.cs index aff7f16f..61946978 100644 --- a/Penumbra/CommandHandler.cs +++ b/Penumbra/CommandHandler.cs @@ -326,7 +326,7 @@ public class CommandHandler : IDisposable, IApiService { _chat.Print(collection == null ? $"The {type.ToName()} Collection{(identifier.IsValid ? $" for {identifier}" : string.Empty)} is already unassigned" - : $"{collection.Name} already is the {type.ToName()} Collection{(identifier.IsValid ? $" for {identifier}." : ".")}"); + : $"{collection.Identity.Name} already is the {type.ToName()} Collection{(identifier.IsValid ? $" for {identifier}." : ".")}"); continue; } @@ -363,13 +363,13 @@ public class CommandHandler : IDisposable, IApiService } Print( - $"Removed {oldCollection.Name} as {type.ToName()} Collection assignment {(identifier.IsValid ? $" for {identifier}." : ".")}"); + $"Removed {oldCollection.Identity.Name} as {type.ToName()} Collection assignment {(identifier.IsValid ? $" for {identifier}." : ".")}"); anySuccess = true; continue; } _collectionManager.Active.SetCollection(collection!, type, individualIndex); - Print($"Assigned {collection!.Name} as {type.ToName()} Collection{(identifier.IsValid ? $" for {identifier}." : ".")}"); + Print($"Assigned {collection!.Identity.Name} as {type.ToName()} Collection{(identifier.IsValid ? $" for {identifier}." : ".")}"); } return anySuccess; @@ -440,7 +440,7 @@ public class CommandHandler : IDisposable, IApiService _chat.Print(new SeStringBuilder().AddText("Mod ").AddPurple(mod.Name, true) .AddText("already had the desired state in collection ") - .AddYellow(collection!.Name, true).AddText(".").BuiltString); + .AddYellow(collection!.Identity.Name, true).AddText(".").BuiltString); return false; } @@ -458,7 +458,7 @@ public class CommandHandler : IDisposable, IApiService _collectionEditor.SetModSetting(collection!, mod, groupIndex, setting); Print(() => new SeStringBuilder().AddText("Changed settings of group ").AddGreen(groupName, true).AddText(" in mod ") .AddPurple(mod.Name, true).AddText(" in collection ") - .AddYellow(collection!.Name, true).AddText(".").BuiltString); + .AddYellow(collection!.Identity.Name, true).AddText(".").BuiltString); return true; } @@ -543,7 +543,7 @@ public class CommandHandler : IDisposable, IApiService changes |= HandleModState(state, collection!, mod); if (!changes) - Print(() => new SeStringBuilder().AddText("No mod states were changed in collection ").AddYellow(collection!.Name, true) + Print(() => new SeStringBuilder().AddText("No mod states were changed in collection ").AddYellow(collection!.Identity.Name, true) .AddText(".").BuiltString); return true; @@ -558,7 +558,7 @@ public class CommandHandler : IDisposable, IApiService return true; } - collection = string.Equals(lowerName, ModCollection.Empty.Name, StringComparison.OrdinalIgnoreCase) + collection = string.Equals(lowerName, ModCollection.Empty.Identity.Name, StringComparison.OrdinalIgnoreCase) ? ModCollection.Empty : _collectionManager.Storage.ByIdentifier(lowerName, out var c) ? c @@ -614,7 +614,7 @@ public class CommandHandler : IDisposable, IApiService return false; Print(() => new SeStringBuilder().AddText("Enabled mod ").AddPurple(mod.Name, true).AddText(" in collection ") - .AddYellow(collection.Name, true) + .AddYellow(collection.Identity.Name, true) .AddText(".").BuiltString); return true; @@ -623,7 +623,7 @@ public class CommandHandler : IDisposable, IApiService return false; Print(() => new SeStringBuilder().AddText("Disabled mod ").AddPurple(mod.Name, true).AddText(" in collection ") - .AddYellow(collection.Name, true) + .AddYellow(collection.Identity.Name, true) .AddText(".").BuiltString); return true; @@ -634,7 +634,7 @@ public class CommandHandler : IDisposable, IApiService Print(() => new SeStringBuilder().AddText(setting ? "Enabled mod " : "Disabled mod ").AddPurple(mod.Name, true) .AddText(" in collection ") - .AddYellow(collection.Name, true) + .AddYellow(collection.Identity.Name, true) .AddText(".").BuiltString); return true; @@ -643,7 +643,7 @@ public class CommandHandler : IDisposable, IApiService return false; Print(() => new SeStringBuilder().AddText("Set mod ").AddPurple(mod.Name, true).AddText(" in collection ") - .AddYellow(collection.Name, true) + .AddYellow(collection.Identity.Name, true) .AddText(" to inherit.").BuiltString); return true; } diff --git a/Penumbra/Interop/Hooks/Meta/AtchCallerHook1.cs b/Penumbra/Interop/Hooks/Meta/AtchCallerHook1.cs index dcbaedc8..c350c157 100644 --- a/Penumbra/Interop/Hooks/Meta/AtchCallerHook1.cs +++ b/Penumbra/Interop/Hooks/Meta/AtchCallerHook1.cs @@ -30,7 +30,7 @@ public unsafe class AtchCallerHook1 : FastHook, IDispo Task.Result.Original(data, slot, unk, playerModel); _metaState.AtchCollection.Pop(); Penumbra.Log.Excessive( - $"[AtchCaller1] Invoked on 0x{(ulong)data:X} with {slot}, {unk:X}, 0x{playerModel.Address:X}, identified to {collection.ModCollection.AnonymizedName}."); + $"[AtchCaller1] Invoked on 0x{(ulong)data:X} with {slot}, {unk:X}, 0x{playerModel.Address:X}, identified to {collection.ModCollection.Identity.AnonymizedName}."); } public void Dispose() diff --git a/Penumbra/Interop/Hooks/Meta/AtchCallerHook2.cs b/Penumbra/Interop/Hooks/Meta/AtchCallerHook2.cs index aa2d3f31..af38ce50 100644 --- a/Penumbra/Interop/Hooks/Meta/AtchCallerHook2.cs +++ b/Penumbra/Interop/Hooks/Meta/AtchCallerHook2.cs @@ -30,7 +30,7 @@ public unsafe class AtchCallerHook2 : FastHook, IDispo Task.Result.Original(data, slot, unk, playerModel, unk2); _metaState.AtchCollection.Pop(); Penumbra.Log.Excessive( - $"[AtchCaller2] Invoked on 0x{(ulong)data:X} with {slot}, {unk:X}, 0x{playerModel.Address:X}, {unk2}, identified to {collection.ModCollection.AnonymizedName}."); + $"[AtchCaller2] Invoked on 0x{(ulong)data:X} with {slot}, {unk:X}, 0x{playerModel.Address:X}, {unk2}, identified to {collection.ModCollection.Identity.AnonymizedName}."); } public void Dispose() diff --git a/Penumbra/Interop/PathResolving/MetaState.cs b/Penumbra/Interop/PathResolving/MetaState.cs index e7fc3176..eeae77cc 100644 --- a/Penumbra/Interop/PathResolving/MetaState.cs +++ b/Penumbra/Interop/PathResolving/MetaState.cs @@ -98,7 +98,7 @@ public sealed unsafe class MetaState : IDisposable, IService _lastCreatedCollection = _collectionResolver.IdentifyLastGameObjectCollection(true); if (_lastCreatedCollection.Valid && _lastCreatedCollection.AssociatedGameObject != nint.Zero) _communicator.CreatingCharacterBase.Invoke(_lastCreatedCollection.AssociatedGameObject, - _lastCreatedCollection.ModCollection.Id, (nint)modelCharaId, (nint)customize, (nint)equipData); + _lastCreatedCollection.ModCollection.Identity.Id, (nint)modelCharaId, (nint)customize, (nint)equipData); var decal = new DecalReverter(Config, _characterUtility, _resources, _lastCreatedCollection, UsesDecal(*(uint*)modelCharaId, (nint)customize)); diff --git a/Penumbra/Interop/PathResolving/PathDataHandler.cs b/Penumbra/Interop/PathResolving/PathDataHandler.cs index 25d4f7ea..e0c235a2 100644 --- a/Penumbra/Interop/PathResolving/PathDataHandler.cs +++ b/Penumbra/Interop/PathResolving/PathDataHandler.cs @@ -32,7 +32,7 @@ public static class PathDataHandler /// Create the encoding path for an IMC file. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static FullPath CreateImc(CiByteString path, ModCollection collection) - => new($"|{collection.LocalId.Id}_{collection.Counters.Imc}_{DiscriminatorString}|{path}"); + => new($"|{collection.Identity.LocalId.Id}_{collection.Counters.Imc}_{DiscriminatorString}|{path}"); /// Create the encoding path for a TMB file. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -47,17 +47,17 @@ public static class PathDataHandler /// Create the encoding path for an ATCH file. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static FullPath CreateAtch(CiByteString path, ModCollection collection) - => new($"|{collection.LocalId.Id}_{collection.Counters.Atch}_{DiscriminatorString}|{path}"); + => new($"|{collection.Identity.LocalId.Id}_{collection.Counters.Atch}_{DiscriminatorString}|{path}"); /// Create the encoding path for a MTRL file. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static FullPath CreateMtrl(CiByteString path, ModCollection collection, Utf8GamePath originalPath) - => new($"|{collection.LocalId.Id}_{collection.Counters.Change}_{originalPath.Path.Crc32:X8}_{DiscriminatorString}|{path}"); + => new($"|{collection.Identity.LocalId.Id}_{collection.Counters.Change}_{originalPath.Path.Crc32:X8}_{DiscriminatorString}|{path}"); /// The base function shared by most file types. [MethodImpl(MethodImplOptions.AggressiveInlining)] private static FullPath CreateBase(CiByteString path, ModCollection collection) - => new($"|{collection.LocalId.Id}_{collection.Counters.Change}_{DiscriminatorString}|{path}"); + => new($"|{collection.Identity.LocalId.Id}_{collection.Counters.Change}_{DiscriminatorString}|{path}"); /// Read an additional data blurb and parse it into usable data for all file types but Materials. [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/Penumbra/Interop/Processing/ImcFilePostProcessor.cs b/Penumbra/Interop/Processing/ImcFilePostProcessor.cs index a3233cfb..513877d4 100644 --- a/Penumbra/Interop/Processing/ImcFilePostProcessor.cs +++ b/Penumbra/Interop/Processing/ImcFilePostProcessor.cs @@ -26,6 +26,6 @@ public sealed class ImcFilePostProcessor(CollectionStorage collections) : IFileP file.Replace(resource); Penumbra.Log.Verbose( - $"[ResourceLoader] Loaded {originalGamePath} from file and replaced with IMC from collection {collection.AnonymizedName}."); + $"[ResourceLoader] Loaded {originalGamePath} from file and replaced with IMC from collection {collection.Identity.AnonymizedName}."); } } diff --git a/Penumbra/Interop/ResourceTree/ResourceTreeFactory.cs b/Penumbra/Interop/ResourceTree/ResourceTreeFactory.cs index 7e378f41..f5659e7c 100644 --- a/Penumbra/Interop/ResourceTree/ResourceTreeFactory.cs +++ b/Penumbra/Interop/ResourceTree/ResourceTreeFactory.cs @@ -81,7 +81,7 @@ public class ResourceTreeFactory( var (name, anonymizedName, related) = GetCharacterName(character); var networked = character.EntityId != 0xE0000000; var tree = new ResourceTree(name, anonymizedName, character.ObjectIndex, (nint)gameObjStruct, (nint)drawObjStruct, localPlayerRelated, related, - networked, collectionResolveData.ModCollection.Name, collectionResolveData.ModCollection.AnonymizedName); + networked, collectionResolveData.ModCollection.Identity.Name, collectionResolveData.ModCollection.Identity.AnonymizedName); var globalContext = new GlobalResolveContext(metaFileManager, objectIdentifier, collectionResolveData.ModCollection, cache, (flags & Flags.WithUiData) != 0); using (var _ = pathState.EnterInternalResolve()) diff --git a/Penumbra/Mods/TemporaryMod.cs b/Penumbra/Mods/TemporaryMod.cs index b5499624..8fdd09c5 100644 --- a/Penumbra/Mods/TemporaryMod.cs +++ b/Penumbra/Mods/TemporaryMod.cs @@ -63,10 +63,10 @@ public class TemporaryMod : IMod DirectoryInfo? dir = null; try { - dir = ModCreator.CreateModFolder(modManager.BasePath, collection.Name, config.ReplaceNonAsciiOnImport, true); + dir = ModCreator.CreateModFolder(modManager.BasePath, collection.Identity.Name, config.ReplaceNonAsciiOnImport, true); var fileDir = Directory.CreateDirectory(Path.Combine(dir.FullName, "files")); - modManager.DataEditor.CreateMeta(dir, collection.Name, character ?? config.DefaultModAuthor, - $"Mod generated from temporary collection {collection.Id} for {character ?? "Unknown Character"} with name {collection.Name}.", + modManager.DataEditor.CreateMeta(dir, collection.Identity.Name, character ?? config.DefaultModAuthor, + $"Mod generated from temporary collection {collection.Identity.Id} for {character ?? "Unknown Character"} with name {collection.Identity.Name}.", null, null); var mod = new Mod(dir); var defaultMod = mod.Default; @@ -99,11 +99,11 @@ public class TemporaryMod : IMod saveService.ImmediateSaveSync(new ModSaveGroup(dir, defaultMod, config.ReplaceNonAsciiOnImport)); modManager.AddMod(dir, false); Penumbra.Log.Information( - $"Successfully generated mod {mod.Name} at {mod.ModPath.FullName} for collection {collection.Identifier}."); + $"Successfully generated mod {mod.Name} at {mod.ModPath.FullName} for collection {collection.Identity.Identifier}."); } catch (Exception e) { - Penumbra.Log.Error($"Could not save temporary collection {collection.Identifier} to permanent Mod:\n{e}"); + Penumbra.Log.Error($"Could not save temporary collection {collection.Identity.Identifier} to permanent Mod:\n{e}"); if (dir != null && Directory.Exists(dir.FullName)) { try diff --git a/Penumbra/Penumbra.cs b/Penumbra/Penumbra.cs index 534911df..a2594145 100644 --- a/Penumbra/Penumbra.cs +++ b/Penumbra/Penumbra.cs @@ -245,24 +245,24 @@ public class Penumbra : IDalamudPlugin void PrintCollection(ModCollection c, CollectionCache _) => sb.Append( - $"> **`Collection {c.AnonymizedName + ':',-18}`** Inheritances: `{c.DirectlyInheritsFrom.Count,3}`, Enabled Mods: `{c.ActualSettings.Count(s => s is { Enabled: true }),4}`, Conflicts: `{c.AllConflicts.SelectMany(x => x).Sum(x => x is { HasPriority: true, Solved: true } ? x.Conflicts.Count : 0),5}/{c.AllConflicts.SelectMany(x => x).Sum(x => x.HasPriority ? x.Conflicts.Count : 0),5}`\n"); + $"> **`Collection {c.Identity.AnonymizedName + ':',-18}`** Inheritances: `{c.DirectlyInheritsFrom.Count,3}`, Enabled Mods: `{c.ActualSettings.Count(s => s is { Enabled: true }),4}`, Conflicts: `{c.AllConflicts.SelectMany(x => x).Sum(x => x is { HasPriority: true, Solved: true } ? x.Conflicts.Count : 0),5}/{c.AllConflicts.SelectMany(x => x).Sum(x => x.HasPriority ? x.Conflicts.Count : 0),5}`\n"); sb.AppendLine("**Collections**"); sb.Append($"> **`#Collections: `** {_collectionManager.Storage.Count - 1}\n"); sb.Append($"> **`#Temp Collections: `** {_tempCollections.Count}\n"); sb.Append($"> **`Active Collections: `** {_collectionManager.Caches.Count}\n"); - sb.Append($"> **`Base Collection: `** {_collectionManager.Active.Default.AnonymizedName}\n"); - sb.Append($"> **`Interface Collection: `** {_collectionManager.Active.Interface.AnonymizedName}\n"); - sb.Append($"> **`Selected Collection: `** {_collectionManager.Active.Current.AnonymizedName}\n"); + sb.Append($"> **`Base Collection: `** {_collectionManager.Active.Default.Identity.AnonymizedName}\n"); + sb.Append($"> **`Interface Collection: `** {_collectionManager.Active.Interface.Identity.AnonymizedName}\n"); + sb.Append($"> **`Selected Collection: `** {_collectionManager.Active.Current.Identity.AnonymizedName}\n"); foreach (var (type, name, _) in CollectionTypeExtensions.Special) { var collection = _collectionManager.Active.ByType(type); if (collection != null) - sb.Append($"> **`{name,-29}`** {collection.AnonymizedName}\n"); + sb.Append($"> **`{name,-29}`** {collection.Identity.AnonymizedName}\n"); } foreach (var (name, id, collection) in _collectionManager.Active.Individuals.Assignments) - sb.Append($"> **`{id[0].Incognito(name) + ':',-29}`** {collection.AnonymizedName}\n"); + sb.Append($"> **`{id[0].Incognito(name) + ':',-29}`** {collection.Identity.AnonymizedName}\n"); foreach (var collection in _collectionManager.Caches.Active) PrintCollection(collection, collection._cache!); diff --git a/Penumbra/Services/ConfigMigrationService.cs b/Penumbra/Services/ConfigMigrationService.cs index 5ba57cf4..f58eb891 100644 --- a/Penumbra/Services/ConfigMigrationService.cs +++ b/Penumbra/Services/ConfigMigrationService.cs @@ -27,8 +27,8 @@ public class ConfigMigrationService(SaveService saveService, BackupService backu private Configuration _config = null!; private JObject _data = null!; - public string CurrentCollection = ModCollection.DefaultCollectionName; - public string DefaultCollection = ModCollection.DefaultCollectionName; + public string CurrentCollection = ModCollectionIdentity.DefaultCollectionName; + public string DefaultCollection = ModCollectionIdentity.DefaultCollectionName; public string ForcedCollection = string.Empty; public Dictionary CharacterCollections = []; public Dictionary ModSortOrder = []; @@ -346,7 +346,7 @@ public class ConfigMigrationService(SaveService saveService, BackupService backu if (!collectionJson.Exists) return; - var defaultCollectionFile = new FileInfo(saveService.FileNames.CollectionFile(ModCollection.DefaultCollectionName)); + var defaultCollectionFile = new FileInfo(saveService.FileNames.CollectionFile(ModCollectionIdentity.DefaultCollectionName)); if (defaultCollectionFile.Exists) return; @@ -380,7 +380,7 @@ public class ConfigMigrationService(SaveService saveService, BackupService backu var emptyStorage = new ModStorage(); // Only used for saving and immediately discarded, so the local collection id here is irrelevant. - var collection = ModCollection.CreateFromData(saveService, emptyStorage, Guid.NewGuid(), ModCollection.DefaultCollectionName, LocalCollectionId.Zero, 0, 1, dict, []); + var collection = ModCollection.CreateFromData(saveService, emptyStorage, ModCollectionIdentity.New(ModCollectionIdentity.DefaultCollectionName, LocalCollectionId.Zero, 1), 0, dict, []); saveService.ImmediateSaveSync(new ModCollectionSave(emptyStorage, collection)); } catch (Exception e) diff --git a/Penumbra/Services/CrashHandlerService.cs b/Penumbra/Services/CrashHandlerService.cs index 9103b29c..4814795c 100644 --- a/Penumbra/Services/CrashHandlerService.cs +++ b/Penumbra/Services/CrashHandlerService.cs @@ -240,7 +240,7 @@ public sealed class CrashHandlerService : IDisposable, IService var name = GetActorName(character); lock (_eventWriter) { - _eventWriter?.AnimationFuncInvoked.WriteLine(character, name.Span, collection.Id, type); + _eventWriter?.AnimationFuncInvoked.WriteLine(character, name.Span, collection.Identity.Id, type); } } catch (Exception ex) @@ -293,7 +293,7 @@ public sealed class CrashHandlerService : IDisposable, IService var name = GetActorName(resolveData.AssociatedGameObject); lock (_eventWriter) { - _eventWriter!.FileLoaded.WriteLine(resolveData.AssociatedGameObject, name.Span, resolveData.ModCollection.Id, + _eventWriter!.FileLoaded.WriteLine(resolveData.AssociatedGameObject, name.Span, resolveData.ModCollection.Identity.Id, manipulatedPath.Value.InternalName.Span, originalPath.Path.Span); } } diff --git a/Penumbra/Services/FilenameService.cs b/Penumbra/Services/FilenameService.cs index 817af0d2..ee096109 100644 --- a/Penumbra/Services/FilenameService.cs +++ b/Penumbra/Services/FilenameService.cs @@ -24,7 +24,7 @@ public class FilenameService(IDalamudPluginInterface pi) : IService /// Obtain the path of a collection file given its name. public string CollectionFile(ModCollection collection) - => CollectionFile(collection.Identifier); + => CollectionFile(collection.Identity.Identifier); /// Obtain the path of a collection file given its name. public string CollectionFile(string collectionName) diff --git a/Penumbra/UI/Classes/CollectionSelectHeader.cs b/Penumbra/UI/Classes/CollectionSelectHeader.cs index 3972e350..0e1408c5 100644 --- a/Penumbra/UI/Classes/CollectionSelectHeader.cs +++ b/Penumbra/UI/Classes/CollectionSelectHeader.cs @@ -25,7 +25,7 @@ public class CollectionSelectHeader : IUiService _selection = selection; _resolver = resolver; _activeCollections = collectionManager.Active; - _collectionCombo = new CollectionCombo(collectionManager, () => collectionManager.Storage.OrderBy(c => c.Name).ToList()); + _collectionCombo = new CollectionCombo(collectionManager, () => collectionManager.Storage.OrderBy(c => c.Identity.Name).ToList()); } /// Draw the header line that can quick switch between collections. @@ -77,10 +77,10 @@ public class CollectionSelectHeader : IUiService return CheckCollection(collection) switch { CollectionState.Empty => (collection, "None", "The base collection is configured to use no mods.", true), - CollectionState.Selected => (collection, collection.Name, + CollectionState.Selected => (collection, collection.Identity.Name, "The configured base collection is already selected as the current collection.", true), - CollectionState.Available => (collection, collection.Name, - $"Select the configured base collection {collection.Name} as the current collection.", false), + CollectionState.Available => (collection, collection.Identity.Name, + $"Select the configured base collection {collection.Identity.Name} as the current collection.", false), _ => throw new Exception("Can not happen."), }; } @@ -91,10 +91,11 @@ public class CollectionSelectHeader : IUiService return CheckCollection(collection) switch { CollectionState.Empty => (collection, "None", "The loaded player character is configured to use no mods.", true), - CollectionState.Selected => (collection, collection.Name, + CollectionState.Selected => (collection, collection.Identity.Name, "The collection configured to apply to the loaded player character is already selected as the current collection.", true), - CollectionState.Available => (collection, collection.Name, - $"Select the collection {collection.Name} that applies to the loaded player character as the current collection.", false), + CollectionState.Available => (collection, collection.Identity.Name, + $"Select the collection {collection.Identity.Name} that applies to the loaded player character as the current collection.", + false), _ => throw new Exception("Can not happen."), }; } @@ -105,10 +106,10 @@ public class CollectionSelectHeader : IUiService return CheckCollection(collection) switch { CollectionState.Empty => (collection, "None", "The interface collection is configured to use no mods.", true), - CollectionState.Selected => (collection, collection.Name, + CollectionState.Selected => (collection, collection.Identity.Name, "The configured interface collection is already selected as the current collection.", true), - CollectionState.Available => (collection, collection.Name, - $"Select the configured interface collection {collection.Name} as the current collection.", false), + CollectionState.Available => (collection, collection.Identity.Name, + $"Select the configured interface collection {collection.Identity.Name} as the current collection.", false), _ => throw new Exception("Can not happen."), }; } @@ -120,8 +121,8 @@ public class CollectionSelectHeader : IUiService { CollectionState.Unavailable => (null, "Not Inherited", "The settings of the selected mod are not inherited from another collection.", true), - CollectionState.Available => (collection, collection!.Name, - $"Select the collection {collection!.Name} from which the selected mod inherits its settings as the current collection.", + CollectionState.Available => (collection, collection!.Identity.Name, + $"Select the collection {collection!.Identity.Name} from which the selected mod inherits its settings as the current collection.", false), _ => throw new Exception("Can not happen."), }; diff --git a/Penumbra/UI/CollectionTab/CollectionCombo.cs b/Penumbra/UI/CollectionTab/CollectionCombo.cs index 1670be5e..0259713f 100644 --- a/Penumbra/UI/CollectionTab/CollectionCombo.cs +++ b/Penumbra/UI/CollectionTab/CollectionCombo.cs @@ -29,13 +29,13 @@ public sealed class CollectionCombo(CollectionManager manager, Func obj.Name; + => obj.Identity.Name; protected override void DrawCombo(string label, string preview, string tooltip, int currentSelected, float previewWidth, float itemHeight, ImGuiComboFlags flags) diff --git a/Penumbra/UI/CollectionTab/CollectionPanel.cs b/Penumbra/UI/CollectionTab/CollectionPanel.cs index 914f10d9..cab34b10 100644 --- a/Penumbra/UI/CollectionTab/CollectionPanel.cs +++ b/Penumbra/UI/CollectionTab/CollectionPanel.cs @@ -221,16 +221,16 @@ public sealed class CollectionPanel( ImGui.SameLine(); ImGui.BeginGroup(); using var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f)); - var name = _newName ?? collection.Name; - var identifier = collection.Identifier; + var name = _newName ?? collection.Identity.Name; + var identifier = collection.Identity.Identifier; var width = ImGui.GetContentRegionAvail().X; var fileName = saveService.FileNames.CollectionFile(collection); ImGui.SetNextItemWidth(width); if (ImGui.InputText("##name", ref name, 128)) _newName = name; - if (ImGui.IsItemDeactivatedAfterEdit() && _newName != null && _newName != collection.Name) + if (ImGui.IsItemDeactivatedAfterEdit() && _newName != null && _newName != collection.Identity.Name) { - collection.Name = _newName; + collection.Identity.Name = _newName; saveService.QueueSave(new ModCollectionSave(mods, collection)); selector.RestoreCollections(); _newName = null; @@ -242,7 +242,7 @@ public sealed class CollectionPanel( using (ImRaii.PushFont(UiBuilder.MonoFont)) { - if (ImGui.Button(collection.Identifier, new Vector2(width, 0))) + if (ImGui.Button(collection.Identity.Identifier, new Vector2(width, 0))) try { Process.Start(new ProcessStartInfo(fileName) { UseShellExecute = true }); @@ -289,9 +289,9 @@ public sealed class CollectionPanel( _active.SetCollection(null, type, _active.Individuals.GetGroup(identifier)); } - foreach (var coll in _collections.OrderBy(c => c.Name)) + foreach (var coll in _collections.OrderBy(c => c.Identity.Name)) { - if (coll != collection && ImGui.MenuItem($"Use {coll.Name}.")) + if (coll != collection && ImGui.MenuItem($"Use {coll.Identity.Name}.")) _active.SetCollection(coll, type, _active.Individuals.GetGroup(identifier)); } } @@ -418,7 +418,7 @@ public sealed class CollectionPanel( private string Name(ModCollection? collection) => collection == null ? "Unassigned" : collection == ModCollection.Empty ? "Use No Mods" : - incognito.IncognitoMode ? collection.AnonymizedName : collection.Name; + incognito.IncognitoMode ? collection.Identity.AnonymizedName : collection.Identity.Name; private void DrawIndividualButton(string intro, Vector2 width, string tooltip, char suffix, params ActorIdentifier[] identifiers) { diff --git a/Penumbra/UI/CollectionTab/CollectionSelector.cs b/Penumbra/UI/CollectionTab/CollectionSelector.cs index 024873bf..57429531 100644 --- a/Penumbra/UI/CollectionTab/CollectionSelector.cs +++ b/Penumbra/UI/CollectionTab/CollectionSelector.cs @@ -69,7 +69,7 @@ public sealed class CollectionSelector : ItemSelector, IDisposabl } protected override bool Filtered(int idx) - => !Items[idx].Name.Contains(Filter, StringComparison.OrdinalIgnoreCase); + => !Items[idx].Identity.Name.Contains(Filter, StringComparison.OrdinalIgnoreCase); private const string PayloadString = "Collection"; @@ -111,12 +111,12 @@ public sealed class CollectionSelector : ItemSelector, IDisposabl } private string Name(ModCollection collection) - => _incognito.IncognitoMode || collection.Name.Length == 0 ? collection.AnonymizedName : collection.Name; + => _incognito.IncognitoMode || collection.Identity.Name.Length == 0 ? collection.Identity.AnonymizedName : collection.Identity.Name; public void RestoreCollections() { Items.Clear(); - foreach (var c in _storage.OrderBy(c => c.Name)) + foreach (var c in _storage.OrderBy(c => c.Identity.Name)) Items.Add(c); SetFilterDirty(); SetCurrent(_active.Current); diff --git a/Penumbra/UI/CollectionTab/InheritanceUi.cs b/Penumbra/UI/CollectionTab/InheritanceUi.cs index 418fe52c..a4d60b13 100644 --- a/Penumbra/UI/CollectionTab/InheritanceUi.cs +++ b/Penumbra/UI/CollectionTab/InheritanceUi.cs @@ -93,7 +93,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService /// private void DrawInheritedChildren(ModCollection collection) { - using var id = ImRaii.PushId(collection.Index); + using var id = ImRaii.PushId(collection.Identity.Index); using var indent = ImRaii.PushIndent(); // Get start point for the lines (top of the selector). @@ -114,7 +114,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService _seenInheritedCollections.Contains(inheritance)); _seenInheritedCollections.Add(inheritance); - ImRaii.TreeNode($"{Name(inheritance)}###{inheritance.Id}", + ImRaii.TreeNode($"{Name(inheritance)}###{inheritance.Identity.Id}", ImGuiTreeNodeFlags.NoTreePushOnOpen | ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet); var (minRect, maxRect) = (ImGui.GetItemRectMin(), ImGui.GetItemRectMax()); DrawInheritanceTreeClicks(inheritance, false); @@ -140,7 +140,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService using var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.HandledConflictMod.Value(), _seenInheritedCollections.Contains(collection)); _seenInheritedCollections.Add(collection); - using var tree = ImRaii.TreeNode($"{Name(collection)}###{collection.Name}", ImGuiTreeNodeFlags.NoTreePushOnOpen); + using var tree = ImRaii.TreeNode($"{Name(collection)}###{collection.Identity.Name}", ImGuiTreeNodeFlags.NoTreePushOnOpen); color.Pop(); DrawInheritanceTreeClicks(collection, true); DrawInheritanceDropSource(collection); @@ -252,7 +252,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService foreach (var collection in _collections .Where(c => InheritanceManager.CheckValidInheritance(_active.Current, c) == InheritanceManager.ValidInheritance.Valid) - .OrderBy(c => c.Name)) + .OrderBy(c => c.Identity.Name)) { if (ImGui.Selectable(Name(collection), _newInheritance == collection)) _newInheritance = collection; @@ -312,5 +312,5 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService } private string Name(ModCollection collection) - => incognito.IncognitoMode ? collection.AnonymizedName : collection.Name; + => incognito.IncognitoMode ? collection.Identity.AnonymizedName : collection.Identity.Name; } diff --git a/Penumbra/UI/ModsTab/ModPanelCollectionsTab.cs b/Penumbra/UI/ModsTab/ModPanelCollectionsTab.cs index b7648428..89a7d765 100644 --- a/Penumbra/UI/ModsTab/ModPanelCollectionsTab.cs +++ b/Penumbra/UI/ModsTab/ModPanelCollectionsTab.cs @@ -56,7 +56,7 @@ public class ModPanelCollectionsTab(CollectionManager manager, ModFileSystemSele foreach (var ((collection, parent, color, state), idx) in _cache.WithIndex()) { using var id = ImUtf8.PushId(idx); - ImUtf8.DrawTableColumn(collection.Name); + ImUtf8.DrawTableColumn(collection.Identity.Name); ImGui.TableNextColumn(); ImUtf8.Text(ToText(state), color); @@ -65,7 +65,7 @@ public class ModPanelCollectionsTab(CollectionManager manager, ModFileSystemSele { if (context) { - ImUtf8.Text(collection.Name); + ImUtf8.Text(collection.Identity.Name); ImGui.Separator(); using (ImRaii.Disabled(state is ModState.Enabled && parent == collection)) { @@ -95,7 +95,7 @@ public class ModPanelCollectionsTab(CollectionManager manager, ModFileSystemSele } } - ImUtf8.DrawTableColumn(parent == collection ? string.Empty : parent.Name); + ImUtf8.DrawTableColumn(parent == collection ? string.Empty : parent.Identity.Name); } } diff --git a/Penumbra/UI/ModsTab/ModPanelSettingsTab.cs b/Penumbra/UI/ModsTab/ModPanelSettingsTab.cs index 8d889c3b..261f6e92 100644 --- a/Penumbra/UI/ModsTab/ModPanelSettingsTab.cs +++ b/Penumbra/UI/ModsTab/ModPanelSettingsTab.cs @@ -67,7 +67,7 @@ public class ModPanelSettingsTab( using var color = ImRaii.PushColor(ImGuiCol.Button, Colors.PressEnterWarningBg); var width = new Vector2(ImGui.GetContentRegionAvail().X, 0); - if (ImGui.Button($"These settings are inherited from {selection.Collection.Name}.", width)) + if (ImGui.Button($"These settings are inherited from {selection.Collection.Identity.Name}.", width)) collectionManager.Editor.SetModInheritance(collectionManager.Active.Current, selection.Mod!, false); ImGuiUtil.HoverTooltip("You can click this button to copy the current settings to the current selection.\n" diff --git a/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs b/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs index d432e97e..0f72efff 100644 --- a/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs +++ b/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs @@ -241,7 +241,7 @@ public sealed class ResourceWatcher : IDisposable, ITab, IUiService { var pathString = manipulatedPath != null ? $"custom file {name2} instead of {name}" : name; Penumbra.Log.Information( - $"[ResourceLoader] [LOAD] [{handle->FileType}] Loaded {pathString} to 0x{(ulong)handle:X} using collection {data.ModCollection.AnonymizedName} for {Name(data, "no associated object.")} (Refcount {handle->RefCount}) "); + $"[ResourceLoader] [LOAD] [{handle->FileType}] Loaded {pathString} to 0x{(ulong)handle:X} using collection {data.ModCollection.Identity.AnonymizedName} for {Name(data, "no associated object.")} (Refcount {handle->RefCount}) "); } } diff --git a/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs b/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs index 88b7120d..7ac3cb99 100644 --- a/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs +++ b/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs @@ -167,7 +167,7 @@ internal sealed class ResourceWatcherTable : Table => 80 * UiHelpers.Scale; public override string ToName(Record item) - => item.Collection?.Name ?? string.Empty; + => (item.Collection != null ? item.Collection.Identity.Name : null) ?? string.Empty; } private sealed class ObjectColumn : ColumnString diff --git a/Penumbra/UI/Tabs/Debug/DebugTab.cs b/Penumbra/UI/Tabs/Debug/DebugTab.cs index 95afb10f..d6a9f05a 100644 --- a/Penumbra/UI/Tabs/Debug/DebugTab.cs +++ b/Penumbra/UI/Tabs/Debug/DebugTab.cs @@ -204,7 +204,7 @@ public class DebugTab : Window, ITab, IUiService if (collection.HasCache) { using var color = PushColor(ImGuiCol.Text, ColorId.FolderExpanded.Value()); - using var node = TreeNode($"{collection.Name} (Change Counter {collection.Counters.Change})###{collection.Name}"); + using var node = TreeNode($"{collection.Identity.Name} (Change Counter {collection.Counters.Change})###{collection.Identity.Name}"); if (!node) continue; @@ -239,7 +239,7 @@ public class DebugTab : Window, ITab, IUiService else { using var color = PushColor(ImGuiCol.Text, ColorId.UndefinedMod.Value()); - TreeNode($"{collection.AnonymizedName} (Change Counter {collection.Counters.Change})", + TreeNode($"{collection.Identity.AnonymizedName} (Change Counter {collection.Counters.Change})", ImGuiTreeNodeFlags.Bullet | ImGuiTreeNodeFlags.Leaf).Dispose(); } } @@ -265,9 +265,9 @@ public class DebugTab : Window, ITab, IUiService { PrintValue("Penumbra Version", $"{_validityChecker.Version} {DebugVersionString}"); PrintValue("Git Commit Hash", _validityChecker.CommitHash); - PrintValue(TutorialService.SelectedCollection, _collectionManager.Active.Current.Name); + PrintValue(TutorialService.SelectedCollection, _collectionManager.Active.Current.Identity.Name); PrintValue(" has Cache", _collectionManager.Active.Current.HasCache.ToString()); - PrintValue(TutorialService.DefaultCollection, _collectionManager.Active.Default.Name); + PrintValue(TutorialService.DefaultCollection, _collectionManager.Active.Default.Identity.Name); PrintValue(" has Cache", _collectionManager.Active.Default.HasCache.ToString()); PrintValue("Mod Manager BasePath", _modManager.BasePath.Name); PrintValue("Mod Manager BasePath-Full", _modManager.BasePath.FullName); @@ -518,7 +518,7 @@ public class DebugTab : Window, ITab, IUiService return; ImGui.TextUnformatted( - $"Last Game Object: 0x{_collectionResolver.IdentifyLastGameObjectCollection(true).AssociatedGameObject:X} ({_collectionResolver.IdentifyLastGameObjectCollection(true).ModCollection.Name})"); + $"Last Game Object: 0x{_collectionResolver.IdentifyLastGameObjectCollection(true).AssociatedGameObject:X} ({_collectionResolver.IdentifyLastGameObjectCollection(true).ModCollection.Identity.Name})"); using (var drawTree = TreeNode("Draw Object to Object")) { if (drawTree) @@ -545,7 +545,7 @@ public class DebugTab : Window, ITab, IUiService ImGui.TextUnformatted(name); ImGui.TableNextColumn(); var collection = _collectionResolver.IdentifyCollection(gameObject, true); - ImGui.TextUnformatted(collection.ModCollection.Name); + ImGui.TextUnformatted(collection.ModCollection.Identity.Name); } } } @@ -561,7 +561,7 @@ public class DebugTab : Window, ITab, IUiService ImGui.TableNextColumn(); ImGui.TextUnformatted($"{data.AssociatedGameObject:X}"); ImGui.TableNextColumn(); - ImGui.TextUnformatted(data.ModCollection.Name); + ImGui.TextUnformatted(data.ModCollection.Identity.Name); } } } @@ -574,12 +574,12 @@ public class DebugTab : Window, ITab, IUiService if (table) { ImGuiUtil.DrawTableColumn("Current Mtrl Data"); - ImGuiUtil.DrawTableColumn(_subfileHelper.MtrlData.ModCollection.Name); + ImGuiUtil.DrawTableColumn(_subfileHelper.MtrlData.ModCollection.Identity.Name); ImGuiUtil.DrawTableColumn($"0x{_subfileHelper.MtrlData.AssociatedGameObject:X}"); ImGui.TableNextColumn(); ImGuiUtil.DrawTableColumn("Current Avfx Data"); - ImGuiUtil.DrawTableColumn(_subfileHelper.AvfxData.ModCollection.Name); + ImGuiUtil.DrawTableColumn(_subfileHelper.AvfxData.ModCollection.Identity.Name); ImGuiUtil.DrawTableColumn($"0x{_subfileHelper.AvfxData.AssociatedGameObject:X}"); ImGui.TableNextColumn(); @@ -591,7 +591,7 @@ public class DebugTab : Window, ITab, IUiService foreach (var (resource, resolve) in _subfileHelper) { ImGuiUtil.DrawTableColumn($"0x{resource:X}"); - ImGuiUtil.DrawTableColumn(resolve.ModCollection.Name); + ImGuiUtil.DrawTableColumn(resolve.ModCollection.Identity.Name); ImGuiUtil.DrawTableColumn($"0x{resolve.AssociatedGameObject:X}"); ImGuiUtil.DrawTableColumn($"{((ResourceHandle*)resource)->FileName()}"); } @@ -611,7 +611,7 @@ public class DebugTab : Window, ITab, IUiService ImGuiUtil.DrawTableColumn($"{((GameObject*)address)->ObjectIndex}"); ImGuiUtil.DrawTableColumn($"0x{address:X}"); ImGuiUtil.DrawTableColumn(identifier.ToString()); - ImGuiUtil.DrawTableColumn(collection.Name); + ImGuiUtil.DrawTableColumn(collection.Identity.Name); } } } diff --git a/Penumbra/UI/Tabs/ModsTab.cs b/Penumbra/UI/Tabs/ModsTab.cs index 87338bdb..c226098d 100644 --- a/Penumbra/UI/Tabs/ModsTab.cs +++ b/Penumbra/UI/Tabs/ModsTab.cs @@ -77,12 +77,12 @@ public class ModsTab( { Penumbra.Log.Error($"Exception thrown during ModPanel Render:\n{e}"); Penumbra.Log.Error($"{modManager.Count} Mods\n" - + $"{_activeCollections.Current.AnonymizedName} Current Collection\n" + + $"{_activeCollections.Current.Identity.AnonymizedName} Current Collection\n" + $"{_activeCollections.Current.Settings.Count} Settings\n" + $"{selector.SortMode.Name} Sort Mode\n" + $"{selector.SelectedLeaf?.Name ?? "NULL"} Selected Leaf\n" + $"{selector.Selected?.Name ?? "NULL"} Selected Mod\n" - + $"{string.Join(", ", _activeCollections.Current.DirectlyInheritsFrom.Select(c => c.AnonymizedName))} Inheritances\n"); + + $"{string.Join(", ", _activeCollections.Current.DirectlyInheritsFrom.Select(c => c.Identity.AnonymizedName))} Inheritances\n"); } } diff --git a/Penumbra/UI/TutorialService.cs b/Penumbra/UI/TutorialService.cs index 7d2a0d2a..69f2b616 100644 --- a/Penumbra/UI/TutorialService.cs +++ b/Penumbra/UI/TutorialService.cs @@ -83,14 +83,14 @@ public class TutorialService : IUiService + "Go here after setting up your root folder to continue the tutorial!") .Register("Initial Setup, Step 4: Managing Collections", "On the left, we have the collection selector. Here, we can create new collections - either empty ones or by duplicating existing ones - and delete any collections not needed anymore.\n" - + $"There will always be one collection called {ModCollection.DefaultCollectionName} that can not be deleted.") + + $"There will always be one collection called {ModCollectionIdentity.DefaultCollectionName} that can not be deleted.") .Register($"Initial Setup, Step 5: {SelectedCollection}", $"The {SelectedCollection} is the one we highlighted in the selector. It is the collection we are currently looking at and editing.\nAny changes we make in our mod settings later in the next tab will edit this collection.\n" - + $"We should already have the collection named {ModCollection.DefaultCollectionName} selected, and for our simple setup, we do not need to do anything here.\n\n") + + $"We should already have the collection named {ModCollectionIdentity.DefaultCollectionName} selected, and for our simple setup, we do not need to do anything here.\n\n") .Register("Initial Setup, Step 6: Simple Assignments", "Aside from being a collection of settings, we can also assign collections to different functions. This is used to make different mods apply to different characters.\n" + "The Simple Assignments panel shows you the possible assignments that are enough for most people along with descriptions.\n" - + $"If you are just starting, you can see that the {ModCollection.DefaultCollectionName} is currently assigned to {CollectionType.Default.ToName()} and {CollectionType.Interface.ToName()}.\n" + + $"If you are just starting, you can see that the {ModCollectionIdentity.DefaultCollectionName} is currently assigned to {CollectionType.Default.ToName()} and {CollectionType.Interface.ToName()}.\n" + "You can also assign 'Use No Mods' instead of a collection by clicking on the function buttons.") .Register("Individual Assignments", "In the Individual Assignments panel, you can manually create assignments for very specific characters or monsters, not just yourself or ones you can currently target.")