mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Extract ModCollectionIdentity.
This commit is contained in:
parent
fbbfe5e00d
commit
67305d507a
43 changed files with 270 additions and 252 deletions
2
OtterGui
2
OtterGui
|
|
@ -1 +1 @@
|
|||
Subproject commit d9caded5efb7c9db0a273a43bb5f6d53cf4ace7f
|
||||
Subproject commit fcc96daa02633f673325c14aeea6b6b568924f1e
|
||||
|
|
@ -8,7 +8,7 @@ namespace Penumbra.Api.Api;
|
|||
public class CollectionApi(CollectionManager collections, ApiHelpers helpers) : IPenumbraApiCollection, IApiService
|
||||
{
|
||||
public Dictionary<Guid, string> 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<Guid, string>?();
|
||||
var old = oldCollection != null ? (oldCollection.Identity.Id, oldCollection.Identity.Name) : new ValueTuple<Guid, string>?();
|
||||
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<Guid, string>?();
|
||||
var old = oldCollection != null ? (oldCollection.Identity.Id, oldCollection.Identity.Name) : new ValueTuple<Guid, string>?();
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ public sealed class CollectionCache : IDisposable
|
|||
public int Calculating = -1;
|
||||
|
||||
public string AnonymizedName
|
||||
=> _collection.AnonymizedName;
|
||||
=> _collection.Identity.AnonymizedName;
|
||||
|
||||
public IEnumerable<SingleArray<ModConflicts>> AllConflicts
|
||||
=> ConflictDict.Values;
|
||||
|
|
|
|||
|
|
@ -114,16 +114,16 @@ public class CollectionCacheManager : IDisposable, IService
|
|||
/// <summary> Only creates a new cache, does not update an existing one. </summary>
|
||||
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.
|
||||
/// </summary>
|
||||
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}.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<string>() ?? ModCollection.Empty.Name;
|
||||
var defaultName = jObject[nameof(Default)]?.ToObject<string>() ?? 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<string>() ?? Default.Name;
|
||||
var interfaceName = jObject[nameof(Interface)]?.ToObject<string>() ?? 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<string>() ?? Default.Name;
|
||||
var currentName = jObject[nameof(Current)]?.ToObject<string>() ?? 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<Guid>() ?? Default.Id;
|
||||
var interfaceId = jObject[nameof(Interface)]?.ToObject<Guid>() ?? 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<Guid>() ?? _storage.DefaultNamed.Id;
|
||||
var currentId = jObject[nameof(Current)]?.ToObject<Guid>() ?? _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.";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ public class CollectionStorage : IReadOnlyList<ModCollection>, IDisposable, ISer
|
|||
public ModCollection CreateFromData(Guid id, string name, int version, Dictionary<string, ModSettings.SavedSettings> allSettings,
|
||||
IReadOnlyList<string> 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<ModCollection>, IDisposable, ISer
|
|||
}
|
||||
|
||||
public void Delete(ModCollection collection)
|
||||
=> _collectionsByLocal.Remove(collection.LocalId);
|
||||
=> _collectionsByLocal.Remove(collection.Identity.LocalId);
|
||||
|
||||
/// <remarks> The empty collection is always available at Index 0. </remarks>
|
||||
private readonly List<ModCollection> _collections =
|
||||
|
|
@ -92,7 +92,7 @@ public class CollectionStorage : IReadOnlyList<ModCollection>, 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<ModCollection>, 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<ModCollection>, 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<ModCollection>, IDisposable, ISer
|
|||
/// </summary>
|
||||
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<ModCollection>, 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<ModCollection>, 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<ModCollection>, 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<ModCollection>, IDisposable, ISer
|
|||
/// </summary>
|
||||
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];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
}
|
||||
|
||||
/// <summary> Order in the inheritance list is relevant. </summary>
|
||||
|
|
@ -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}.");
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="AddInheritance(ModCollection, ModCollection)"/>
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/// </summary>
|
||||
public partial class ModCollection
|
||||
{
|
||||
public const int CurrentVersion = 2;
|
||||
public const string DefaultCollectionName = "Default";
|
||||
public const string EmptyCollectionName = "None";
|
||||
public const int CurrentVersion = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Create the always available Empty Collection that will always sit at index 0,
|
||||
/// can not be deleted and does never create a cache.
|
||||
/// </summary>
|
||||
public static readonly ModCollection Empty = new(Guid.Empty, EmptyCollectionName, LocalCollectionId.Zero, 0, 0, CurrentVersion, [], [], []);
|
||||
public static readonly ModCollection Empty = new(ModCollectionIdentity.Empty, 0, CurrentVersion, [], [], []);
|
||||
|
||||
/// <summary> The name of a collection. </summary>
|
||||
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;
|
||||
|
||||
/// <summary> Get the first two letters of a collection name and its Index (or None if it is the empty collection). </summary>
|
||||
public string AnonymizedName
|
||||
=> this == Empty ? Empty.Name : Name == DefaultCollectionName ? Name : ShortIdentifier;
|
||||
|
||||
/// <summary> The index of the collection is set and kept up-to-date by the CollectionManager. </summary>
|
||||
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()));
|
||||
}
|
||||
|
||||
/// <summary> Constructor for reading from files. </summary>
|
||||
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<string, ModSettings.SavedSettings> allSettings, IReadOnlyList<string> 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(), [], []);
|
||||
}
|
||||
|
||||
/// <summary> Add settings for a new appended mod, by checking if the mod had settings from a previous deletion. </summary>
|
||||
|
|
@ -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<ModSettings?> appliedSettings, List<ModCollection> inheritsFrom, Dictionary<string, ModSettings.SavedSettings> settings)
|
||||
private ModCollection(ModCollectionIdentity identity, int changeCounter, int version, List<ModSettings?> appliedSettings,
|
||||
List<ModCollection> inheritsFrom, Dictionary<string, ModSettings.SavedSettings> 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<ModCollection>)c.DirectParentOf).Add(this);
|
||||
|
|
|
|||
42
Penumbra/Collections/ModCollectionIdentity.cs
Normal file
42
Penumbra/Collections/ModCollectionIdentity.cs
Normal file
|
|
@ -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;
|
||||
|
||||
/// <summary> The index of the collection is set and kept up-to-date by the CollectionManager. </summary>
|
||||
public int Index { get; internal set; }
|
||||
|
||||
public string Identifier
|
||||
=> Id.ToString();
|
||||
|
||||
public string ShortIdentifier
|
||||
=> Id.ShortGuid();
|
||||
|
||||
/// <summary> Get the short identifier of a collection unless it is a well-known collection name. </summary>
|
||||
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);
|
||||
}
|
||||
|
|
@ -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<int>() ?? 0;
|
||||
name = obj[nameof(ModCollection.Name)]?.ToObject<string>() ?? string.Empty;
|
||||
id = obj[nameof(ModCollection.Id)]?.ToObject<Guid>() ?? (version == 1 ? Guid.NewGuid() : Guid.Empty);
|
||||
name = obj[nameof(ModCollectionIdentity.Name)]?.ToObject<string>() ?? string.Empty;
|
||||
id = obj[nameof(ModCollectionIdentity.Id)]?.ToObject<Guid>() ?? (version == 1 ? Guid.NewGuid() : Guid.Empty);
|
||||
// Custom deserialization that is converted with the constructor.
|
||||
settings = obj[nameof(ModCollection.Settings)]?.ToObject<Dictionary<string, ModSettings.SavedSettings>>() ?? settings;
|
||||
inheritance = obj["Inheritance"]?.ToObject<List<string>>() ?? inheritance;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ public unsafe class AtchCallerHook1 : FastHook<AtchCallerHook1.Delegate>, 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()
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ public unsafe class AtchCallerHook2 : FastHook<AtchCallerHook2.Delegate>, 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()
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public static class PathDataHandler
|
|||
/// <summary> Create the encoding path for an IMC file. </summary>
|
||||
[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}");
|
||||
|
||||
/// <summary> Create the encoding path for a TMB file. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
|
@ -47,17 +47,17 @@ public static class PathDataHandler
|
|||
/// <summary> Create the encoding path for an ATCH file. </summary>
|
||||
[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}");
|
||||
|
||||
/// <summary> Create the encoding path for a MTRL file. </summary>
|
||||
[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}");
|
||||
|
||||
/// <summary> The base function shared by most file types. </summary>
|
||||
[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}");
|
||||
|
||||
/// <summary> Read an additional data blurb and parse it into usable data for all file types but Materials. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
|
|
|||
|
|
@ -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}.");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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!);
|
||||
|
|
|
|||
|
|
@ -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<string, string> CharacterCollections = [];
|
||||
public Dictionary<string, string> 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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ public class FilenameService(IDalamudPluginInterface pi) : IService
|
|||
|
||||
/// <summary> Obtain the path of a collection file given its name.</summary>
|
||||
public string CollectionFile(ModCollection collection)
|
||||
=> CollectionFile(collection.Identifier);
|
||||
=> CollectionFile(collection.Identity.Identifier);
|
||||
|
||||
/// <summary> Obtain the path of a collection file given its name. </summary>
|
||||
public string CollectionFile(string collectionName)
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
||||
/// <summary> Draw the header line that can quick switch between collections. </summary>
|
||||
|
|
@ -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."),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -29,13 +29,13 @@ public sealed class CollectionCombo(CollectionManager manager, Func<IReadOnlyLis
|
|||
}
|
||||
|
||||
_color.Push(ImGuiCol.FrameBg, color).Push(ImGuiCol.FrameBgHovered, color);
|
||||
if (Draw(label, current.Name, string.Empty, width, ImGui.GetTextLineHeightWithSpacing()) && CurrentSelection != null)
|
||||
if (Draw(label, current.Identity.Name, string.Empty, width, ImGui.GetTextLineHeightWithSpacing()) && CurrentSelection != null)
|
||||
manager.Active.SetCollection(CurrentSelection, CollectionType.Current);
|
||||
_color.Dispose();
|
||||
}
|
||||
|
||||
protected override string ToString(ModCollection obj)
|
||||
=> obj.Name;
|
||||
=> obj.Identity.Name;
|
||||
|
||||
protected override void DrawCombo(string label, string preview, string tooltip, int currentSelected, float previewWidth, float itemHeight,
|
||||
ImGuiComboFlags flags)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ public sealed class CollectionSelector : ItemSelector<ModCollection>, 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<ModCollection>, 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);
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService
|
|||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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}) ");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ internal sealed class ResourceWatcherTable : Table<Record>
|
|||
=> 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<Record>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue