Remove meta-default-value checking from TT imports, move it entirely to mod loads, and keep default-valued entries if other options actually edit the same entry.

This commit is contained in:
Ottermandias 2025-04-08 16:56:23 +02:00
parent 0afcae4504
commit 33ada1d994
8 changed files with 194 additions and 75 deletions

View file

@ -1,11 +1,15 @@
using System.Collections.Frozen;
using OtterGui.Classes;
using OtterGui.Services;
using Penumbra.Collections.Cache;
using Penumbra.Meta;
using Penumbra.Meta.Files;
using Penumbra.Meta.Manipulations;
using Penumbra.Mods.Groups;
using Penumbra.Mods.Manager.OptionEditor;
using Penumbra.Mods.SubMods;
using Penumbra.Services;
using static Penumbra.GameData.Files.ShpkFile;
namespace Penumbra.Mods.Editor;
@ -68,13 +72,157 @@ public class ModMetaEditor(
Changes = false;
}
public static bool DeleteDefaultValues(MetaFileManager metaFileManager, MetaDictionary dict)
public static bool DeleteDefaultValues(Mod mod, MetaFileManager metaFileManager, SaveService? saveService, bool deleteAll = false)
{
if (deleteAll)
{
var changes = false;
foreach (var container in mod.AllDataContainers)
{
if (!DeleteDefaultValues(metaFileManager, container.Manipulations))
continue;
saveService?.ImmediateSaveSync(new ModSaveGroup(container, metaFileManager.Config.ReplaceNonAsciiOnImport));
changes = true;
}
return changes;
}
var defaultEntries = new MultiDictionary<IMetaIdentifier, IModDataContainer>();
var actualEntries = new HashSet<IMetaIdentifier>();
if (!FilterDefaultValues(mod.AllDataContainers, metaFileManager, defaultEntries, actualEntries))
return false;
var groups = new HashSet<IModGroup>();
DefaultSubMod? defaultMod = null;
foreach (var (defaultIdentifier, containers) in defaultEntries.Grouped)
{
if (!deleteAll && actualEntries.Contains(defaultIdentifier))
continue;
foreach (var container in containers)
{
if (!container.Manipulations.Remove(defaultIdentifier))
continue;
Penumbra.Log.Verbose($"Deleted default-valued meta-entry {defaultIdentifier}.");
if (container.Group is { } group)
groups.Add(group);
else if (container is DefaultSubMod d)
defaultMod = d;
}
}
if (saveService is not null)
{
if (defaultMod is not null)
saveService.ImmediateSaveSync(new ModSaveGroup(defaultMod, metaFileManager.Config.ReplaceNonAsciiOnImport));
foreach (var group in groups)
saveService.ImmediateSaveSync(new ModSaveGroup(group, metaFileManager.Config.ReplaceNonAsciiOnImport));
}
return defaultMod is not null || groups.Count > 0;
}
public void DeleteDefaultValues()
=> Changes = DeleteDefaultValues(metaFileManager, this);
public void Apply(IModDataContainer container)
{
if (!Changes)
return;
groupEditor.SetManipulations(container, this);
Changes = false;
}
private static bool FilterDefaultValues(IEnumerable<IModDataContainer> containers, MetaFileManager metaFileManager,
MultiDictionary<IMetaIdentifier, IModDataContainer> defaultEntries, HashSet<IMetaIdentifier> actualEntries)
{
if (!metaFileManager.CharacterUtility.Ready)
{
Penumbra.Log.Warning("Trying to filter default meta values before CharacterUtility was ready, skipped.");
return false;
}
foreach (var container in containers)
{
foreach (var (key, value) in container.Manipulations.Imc)
{
var defaultEntry = ImcChecker.GetDefaultEntry(key, false);
if (defaultEntry.Entry.Equals(value))
defaultEntries.TryAdd(key, container);
else
actualEntries.Add(key);
}
foreach (var (key, value) in container.Manipulations.Eqp)
{
var defaultEntry = new EqpEntryInternal(ExpandedEqpFile.GetDefault(metaFileManager, key.SetId), key.Slot);
if (defaultEntry.Equals(value))
defaultEntries.TryAdd(key, container);
else
actualEntries.Add(key);
}
foreach (var (key, value) in container.Manipulations.Eqdp)
{
var defaultEntry = new EqdpEntryInternal(ExpandedEqdpFile.GetDefault(metaFileManager, key), key.Slot);
if (defaultEntry.Equals(value))
defaultEntries.TryAdd(key, container);
else
actualEntries.Add(key);
}
foreach (var (key, value) in container.Manipulations.Est)
{
var defaultEntry = EstFile.GetDefault(metaFileManager, key);
if (defaultEntry.Equals(value))
defaultEntries.TryAdd(key, container);
else
actualEntries.Add(key);
}
foreach (var (key, value) in container.Manipulations.Gmp)
{
var defaultEntry = ExpandedGmpFile.GetDefault(metaFileManager, key);
if (defaultEntry.Equals(value))
defaultEntries.TryAdd(key, container);
else
actualEntries.Add(key);
}
foreach (var (key, value) in container.Manipulations.Rsp)
{
var defaultEntry = CmpFile.GetDefault(metaFileManager, key.SubRace, key.Attribute);
if (defaultEntry.Equals(value))
defaultEntries.TryAdd(key, container);
else
actualEntries.Add(key);
}
foreach (var (key, value) in container.Manipulations.Atch)
{
var defaultEntry = AtchCache.GetDefault(metaFileManager, key);
if (defaultEntry.Equals(value))
defaultEntries.TryAdd(key, container);
else
actualEntries.Add(key);
}
}
return true;
}
private static bool DeleteDefaultValues(MetaFileManager metaFileManager, MetaDictionary dict)
{
if (!metaFileManager.CharacterUtility.Ready)
{
Penumbra.Log.Warning("Trying to delete default meta values before CharacterUtility was ready, skipped.");
return false;
}
var clone = dict.Clone();
dict.ClearForDefault();
@ -189,16 +337,4 @@ public class ModMetaEditor(
Penumbra.Log.Debug($"Deleted {count} default-valued meta-entries from a mod option.");
return true;
}
public void DeleteDefaultValues()
=> Changes = DeleteDefaultValues(metaFileManager, this);
public void Apply(IModDataContainer container)
{
if (!Changes)
return;
groupEditor.SetManipulations(container, this);
Changes = false;
}
}