mirror of
https://github.com/xivdev/Penumbra.git
synced 2026-02-23 08:17:59 +01:00
Extract ModCollectionIdentity.
This commit is contained in:
parent
fbbfe5e00d
commit
67305d507a
43 changed files with 270 additions and 252 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue