mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
Fix inheritance save issues and sort mod settings on collection save.
This commit is contained in:
parent
4298b46130
commit
5567134a56
5 changed files with 43 additions and 63 deletions
|
|
@ -11,7 +11,6 @@ using Penumbra.Communication;
|
|||
using Penumbra.Mods;
|
||||
using Penumbra.Mods.Manager;
|
||||
using Penumbra.Services;
|
||||
using Penumbra.Util;
|
||||
|
||||
namespace Penumbra.Collections.Manager;
|
||||
|
||||
|
|
@ -153,41 +152,6 @@ public class CollectionStorage : IReadOnlyList<ModCollection>, IDisposable
|
|||
return true;
|
||||
}
|
||||
|
||||
/// <summary> Stored after loading to be consumed and passed to the inheritance manager later. </summary>
|
||||
private List<IReadOnlyList<string>>? _inheritancesByName = new();
|
||||
|
||||
/// <summary> Return an enumerable of collections and the collections they should inherit. </summary>
|
||||
public IEnumerable<(ModCollection Collection, IReadOnlyList<ModCollection> Inheritance, bool LoadChanges)> ConsumeInheritanceNames()
|
||||
{
|
||||
if (_inheritancesByName == null)
|
||||
throw new Exception("Inheritances were already consumed. This method can not be called twice.");
|
||||
|
||||
var inheritances = _inheritancesByName;
|
||||
_inheritancesByName = null;
|
||||
var list = new List<ModCollection>();
|
||||
foreach (var (collection, inheritance) in _collections.Zip(inheritances))
|
||||
{
|
||||
list.Clear();
|
||||
var changes = false;
|
||||
foreach (var subCollectionName in inheritance)
|
||||
{
|
||||
if (ByName(subCollectionName, out var subCollection))
|
||||
{
|
||||
list.Add(subCollection);
|
||||
}
|
||||
else
|
||||
{
|
||||
Penumbra.ChatService.NotificationMessage(
|
||||
$"Inherited collection {subCollectionName} for {collection.AnonymizedName} does not exist, it was removed.", "Warning",
|
||||
NotificationType.Warning);
|
||||
changes = true;
|
||||
}
|
||||
}
|
||||
|
||||
yield return (collection, list, changes);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Remove all settings for not currently-installed mods from the given collection. </summary>
|
||||
public void CleanUnavailableSettings(ModCollection collection)
|
||||
{
|
||||
|
|
@ -218,9 +182,6 @@ public class CollectionStorage : IReadOnlyList<ModCollection>, IDisposable
|
|||
/// </summary>
|
||||
private void ReadCollections(out ModCollection defaultNamedCollection)
|
||||
{
|
||||
_inheritancesByName?.Clear();
|
||||
_inheritancesByName?.Add(Array.Empty<string>()); // None.
|
||||
|
||||
foreach (var file in _saveService.FileNames.CollectionFiles)
|
||||
{
|
||||
if (!ModCollectionSave.LoadFromFile(file, out var name, out var version, out var settings, out var inheritance))
|
||||
|
|
@ -241,13 +202,11 @@ public class CollectionStorage : IReadOnlyList<ModCollection>, IDisposable
|
|||
continue;
|
||||
}
|
||||
|
||||
var collection = ModCollection.CreateFromData(_saveService, _modStorage, name, version, Count, settings);
|
||||
var collection = ModCollection.CreateFromData(_saveService, _modStorage, name, version, Count, settings, inheritance);
|
||||
var correctName = _saveService.FileNames.CollectionFile(collection);
|
||||
if (file.FullName != correctName)
|
||||
Penumbra.ChatService.NotificationMessage($"Collection {file.Name} does not correspond to {collection.Name}.", "Warning",
|
||||
NotificationType.Warning);
|
||||
|
||||
_inheritancesByName?.Add(inheritance);
|
||||
_collections.Add(collection);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using OtterGui.Filesystem;
|
|||
using Penumbra.Communication;
|
||||
using Penumbra.Mods.Manager;
|
||||
using Penumbra.Services;
|
||||
using Penumbra.UI.CollectionTab;
|
||||
using Penumbra.Util;
|
||||
|
||||
namespace Penumbra.Collections.Manager;
|
||||
|
|
@ -131,20 +132,34 @@ public class InheritanceManager : IDisposable
|
|||
/// </summary>
|
||||
private void ApplyInheritances()
|
||||
{
|
||||
foreach (var (collection, directParents, changes) in _storage.ConsumeInheritanceNames())
|
||||
foreach (var collection in _storage)
|
||||
{
|
||||
var localChanges = changes;
|
||||
foreach (var parent in directParents)
|
||||
{
|
||||
if (AddInheritance(collection, parent, false))
|
||||
continue;
|
||||
if (collection.InheritanceByName == null)
|
||||
continue;
|
||||
|
||||
localChanges = true;
|
||||
Penumbra.ChatService.NotificationMessage($"{collection.Name} can not inherit from {parent.Name}, removed.", "Warning",
|
||||
NotificationType.Warning);
|
||||
var changes = false;
|
||||
foreach (var subCollectionName in collection.InheritanceByName)
|
||||
{
|
||||
if (_storage.ByName(subCollectionName, out var subCollection))
|
||||
{
|
||||
if (AddInheritance(collection, subCollection, false))
|
||||
continue;
|
||||
|
||||
changes = true;
|
||||
Penumbra.ChatService.NotificationMessage($"{collection.Name} can not inherit from {subCollection.Name}, removed.", "Warning",
|
||||
NotificationType.Warning);
|
||||
}
|
||||
else
|
||||
{
|
||||
Penumbra.ChatService.NotificationMessage(
|
||||
$"Inherited collection {subCollectionName} for {collection.AnonymizedName} does not exist, it was removed.", "Warning",
|
||||
NotificationType.Warning);
|
||||
changes = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (localChanges)
|
||||
collection.InheritanceByName = null;
|
||||
if (changes)
|
||||
_saveService.ImmediateSave(new ModCollectionSave(_modStorage, collection));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ using System.Collections.Generic;
|
|||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Penumbra.Mods.Manager;
|
||||
using Penumbra.Util;
|
||||
using Penumbra.Collections.Manager;
|
||||
using Penumbra.Services;
|
||||
|
||||
|
|
@ -58,6 +57,9 @@ public partial class ModCollection
|
|||
|
||||
/// <summary> Settings for deleted mods will be kept via the mods identifier (directory name). </summary>
|
||||
public readonly IReadOnlyDictionary<string, ModSettings.SavedSettings> UnusedSettings;
|
||||
|
||||
/// <summary> Inheritances stored before they can be applied. </summary>
|
||||
public IReadOnlyList<string>? InheritanceByName;
|
||||
|
||||
/// <summary> Contains all direct parent collections this collection inherits settings from. </summary>
|
||||
public readonly IReadOnlyList<ModCollection> DirectlyInheritsFrom;
|
||||
|
|
@ -115,10 +117,13 @@ public partial class ModCollection
|
|||
|
||||
/// <summary> Constructor for reading from files. </summary>
|
||||
public static ModCollection CreateFromData(SaveService saver, ModStorage mods, string name, int version, int index,
|
||||
Dictionary<string, ModSettings.SavedSettings> allSettings)
|
||||
Dictionary<string, ModSettings.SavedSettings> allSettings, IReadOnlyList<string> inheritances)
|
||||
{
|
||||
Debug.Assert(index > 0, "Collection read with non-positive index.");
|
||||
var ret = new ModCollection(name, index, 0, version, new List<ModSettings?>(), new List<ModCollection>(), allSettings);
|
||||
var ret = new ModCollection(name, index, 0, version, new List<ModSettings?>(), new List<ModCollection>(), allSettings)
|
||||
{
|
||||
InheritanceByName = inheritances,
|
||||
};
|
||||
ret.ApplyModSettings(saver, mods);
|
||||
ModCollectionMigration.Migrate(saver, mods, version, ret);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -48,17 +48,18 @@ internal readonly struct ModCollectionSave : ISavable
|
|||
|
||||
// Write all used and unused settings by mod directory name.
|
||||
j.WriteStartObject();
|
||||
var list = new List<(string, ModSettings.SavedSettings)>(_modCollection.Settings.Count + _modCollection.UnusedSettings.Count);
|
||||
for (var i = 0; i < _modCollection.Settings.Count; ++i)
|
||||
{
|
||||
var settings = _modCollection.Settings[i];
|
||||
if (settings != null)
|
||||
{
|
||||
j.WritePropertyName(_modStorage[i].ModPath.Name);
|
||||
x.Serialize(j, new ModSettings.SavedSettings(settings, _modStorage[i]));
|
||||
}
|
||||
list.Add((_modStorage[i].ModPath.Name, new ModSettings.SavedSettings(settings, _modStorage[i])));
|
||||
}
|
||||
|
||||
foreach (var (modDir, settings) in _modCollection.UnusedSettings)
|
||||
list.AddRange(_modCollection.UnusedSettings.Select(kvp => (kvp.Key, kvp.Value)));
|
||||
list.Sort((a, b) => string.Compare(a.Item1, b.Item1, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
foreach (var (modDir, settings) in list)
|
||||
{
|
||||
j.WritePropertyName(modDir);
|
||||
x.Serialize(j, settings);
|
||||
|
|
@ -67,8 +68,8 @@ internal readonly struct ModCollectionSave : ISavable
|
|||
j.WriteEndObject();
|
||||
|
||||
// Inherit by collection name.
|
||||
j.WritePropertyName("Inheritance");
|
||||
x.Serialize(j, _modCollection.DirectlyInheritsFrom.Select(c => c.Name));
|
||||
j.WritePropertyName("Inheritance");
|
||||
x.Serialize(j, _modCollection.InheritanceByName ?? _modCollection.DirectlyInheritsFrom.Select(c => c.Name));
|
||||
j.WriteEndObject();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -333,7 +333,7 @@ public class ConfigMigrationService
|
|||
dict = dict.ToDictionary(kvp => kvp.Key, kvp => kvp.Value with { Priority = maxPriority - kvp.Value.Priority });
|
||||
|
||||
var emptyStorage = new ModStorage();
|
||||
var collection = ModCollection.CreateFromData(_saveService, emptyStorage, ModCollection.DefaultCollectionName, 0, 1, dict);
|
||||
var collection = ModCollection.CreateFromData(_saveService, emptyStorage, ModCollection.DefaultCollectionName, 0, 1, dict, Array.Empty<string>());
|
||||
_saveService.ImmediateSave(new ModCollectionSave(emptyStorage, collection));
|
||||
}
|
||||
catch (Exception e)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue