Penumbra/Penumbra/Collections/ModSettingProvider.cs
2024-12-31 15:40:25 +01:00

98 lines
3.4 KiB
C#

using Penumbra.Mods;
using Penumbra.Mods.Manager;
using Penumbra.Mods.Settings;
using Penumbra.Services;
namespace Penumbra.Collections;
public readonly struct ModSettingProvider
{
private ModSettingProvider(IEnumerable<FullModSettings> settings, Dictionary<string, ModSettings.SavedSettings> unusedSettings)
{
_settings = settings.Select(s => s.DeepCopy()).ToList();
_unused = unusedSettings.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.DeepCopy());
}
public ModSettingProvider()
{ }
public static ModSettingProvider Empty(int count)
=> new(Enumerable.Repeat(FullModSettings.Empty, count), []);
public ModSettingProvider(Dictionary<string, ModSettings.SavedSettings> allSettings)
=> _unused = allSettings;
private readonly List<FullModSettings> _settings = [];
/// <summary> Settings for deleted mods will be kept via the mods identifier (directory name). </summary>
private readonly Dictionary<string, ModSettings.SavedSettings> _unused = [];
public int Count
=> _settings.Count;
public bool RemoveUnused(string key)
=> _unused.Remove(key);
internal void Set(Index index, ModSettings? settings)
=> _settings[index] = _settings[index] with { Settings = settings };
internal void SetTemporary(Index index, TemporaryModSettings? settings)
=> _settings[index] = _settings[index] with { TempSettings = settings };
internal void SetAll(Index index, FullModSettings settings)
=> _settings[index] = settings;
public IReadOnlyList<FullModSettings> Settings
=> _settings;
public IReadOnlyDictionary<string, ModSettings.SavedSettings> Unused
=> _unused;
public ModSettingProvider Clone()
=> new(_settings, _unused);
/// <summary> Add settings for a new appended mod, by checking if the mod had settings from a previous deletion. </summary>
internal bool AddMod(Mod mod)
{
if (_unused.Remove(mod.ModPath.Name, out var save))
{
var ret = save.ToSettings(mod, out var settings);
_settings.Add(new FullModSettings(settings));
return ret;
}
_settings.Add(FullModSettings.Empty);
return false;
}
/// <summary> Move settings from the current mod list to the unused mod settings. </summary>
internal void RemoveMod(Mod mod)
{
var settings = _settings[mod.Index];
if (settings.Settings != null)
_unused[mod.ModPath.Name] = new ModSettings.SavedSettings(settings.Settings, mod);
_settings.RemoveAt(mod.Index);
}
/// <summary> Move all settings to unused settings for rediscovery. </summary>
internal void PrepareModDiscovery(ModStorage mods)
{
foreach (var (mod, setting) in mods.Zip(_settings).Where(s => s.Second.Settings != null))
_unused[mod.ModPath.Name] = new ModSettings.SavedSettings(setting.Settings!, mod);
_settings.Clear();
}
/// <summary>
/// Apply all mod settings from unused settings to the current set of mods.
/// Also fixes invalid settings.
/// </summary>
internal void ApplyModSettings(ModCollection parent, SaveService saver, ModStorage mods)
{
_settings.Capacity = Math.Max(_settings.Capacity, mods.Count);
var settings = this;
if (mods.Aggregate(false, (current, mod) => current | settings.AddMod(mod)))
saver.ImmediateSave(new ModCollectionSave(mods, parent));
}
}