mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Remove ISubMod.
This commit is contained in:
parent
8fc7de64d9
commit
9f4c6767f8
23 changed files with 123 additions and 184 deletions
|
|
@ -152,7 +152,7 @@ public partial class TexToolsImporter
|
|||
}
|
||||
|
||||
// Iterate through all pages
|
||||
var options = new List<ISubMod>();
|
||||
var options = new List<SubMod>();
|
||||
var groupPriority = ModPriority.Default;
|
||||
var groupNames = new HashSet<string>();
|
||||
foreach (var page in modList.ModPackPages)
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public class DuplicateManager(ModManager modManager, SaveService saveService, Co
|
|||
Worker = Task.Run(() => CheckDuplicates(filesTmp, _cancellationTokenSource.Token), _cancellationTokenSource.Token);
|
||||
}
|
||||
|
||||
public void DeleteDuplicates(ModFileCollection files, Mod mod, ISubMod option, bool useModManager)
|
||||
public void DeleteDuplicates(ModFileCollection files, Mod mod, SubMod option, bool useModManager)
|
||||
{
|
||||
if (!Worker.IsCompleted || _duplicates.Count == 0)
|
||||
return;
|
||||
|
|
@ -72,7 +72,7 @@ public class DuplicateManager(ModManager modManager, SaveService saveService, Co
|
|||
|
||||
return;
|
||||
|
||||
void HandleSubMod(ISubMod subMod, int groupIdx, int optionIdx)
|
||||
void HandleSubMod(SubMod subMod, int groupIdx, int optionIdx)
|
||||
{
|
||||
var changes = false;
|
||||
var dict = subMod.Files.ToDictionary(kvp => kvp.Key,
|
||||
|
|
@ -86,8 +86,7 @@ public class DuplicateManager(ModManager modManager, SaveService saveService, Co
|
|||
}
|
||||
else
|
||||
{
|
||||
var sub = (SubMod)subMod;
|
||||
sub.FileData = dict;
|
||||
subMod.FileData = dict;
|
||||
saveService.ImmediateSaveSync(new ModSaveGroup(mod, groupIdx, config.ReplaceNonAsciiOnImport));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace Penumbra.Mods.Editor;
|
|||
|
||||
public class FileRegistry : IEquatable<FileRegistry>
|
||||
{
|
||||
public readonly List<(ISubMod, Utf8GamePath)> SubModUsage = [];
|
||||
public readonly List<(SubMod, Utf8GamePath)> SubModUsage = [];
|
||||
public FullPath File { get; private init; }
|
||||
public Utf8RelPath RelPath { get; private init; }
|
||||
public long FileSize { get; private init; }
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ using Penumbra.String.Classes;
|
|||
namespace Penumbra.Mods.Editor;
|
||||
|
||||
public record struct AppliedModData(
|
||||
IReadOnlyCollection<KeyValuePair<Utf8GamePath, FullPath>> FileRedirections,
|
||||
IReadOnlyCollection<MetaManipulation> Manipulations)
|
||||
Dictionary<Utf8GamePath, FullPath> FileRedirections,
|
||||
HashSet<MetaManipulation> Manipulations)
|
||||
{
|
||||
public static readonly AppliedModData Empty = new([], []);
|
||||
}
|
||||
|
|
@ -19,13 +19,9 @@ public interface IMod
|
|||
public int Index { get; }
|
||||
public ModPriority Priority { get; }
|
||||
|
||||
public AppliedModData GetData(ModSettings? settings = null);
|
||||
|
||||
|
||||
public ISubMod Default { get; }
|
||||
public IReadOnlyList<IModGroup> Groups { get; }
|
||||
|
||||
public IEnumerable<SubMod> AllSubMods { get; }
|
||||
public AppliedModData GetData(ModSettings? settings = null);
|
||||
|
||||
// Cache
|
||||
public int TotalManipulations { get; }
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public class ModEditor(
|
|||
public int OptionIdx { get; private set; }
|
||||
|
||||
public IModGroup? Group { get; private set; }
|
||||
public ISubMod? Option { get; private set; }
|
||||
public SubMod? Option { get; private set; }
|
||||
|
||||
public void LoadMod(Mod mod)
|
||||
=> LoadMod(mod, -1, 0);
|
||||
|
|
@ -104,7 +104,7 @@ public class ModEditor(
|
|||
=> Clear();
|
||||
|
||||
/// <summary> Apply a option action to all available option in a mod, including the default option. </summary>
|
||||
public static void ApplyToAllOptions(Mod mod, Action<ISubMod, int, int> action)
|
||||
public static void ApplyToAllOptions(Mod mod, Action<SubMod, int, int> action)
|
||||
{
|
||||
action(mod.Default, -1, 0);
|
||||
foreach (var (group, groupIdx) in mod.Groups.WithIndex())
|
||||
|
|
|
|||
|
|
@ -38,13 +38,13 @@ public class ModFileCollection : IDisposable
|
|||
|
||||
public bool Ready { get; private set; } = true;
|
||||
|
||||
public void UpdateAll(Mod mod, ISubMod option)
|
||||
public void UpdateAll(Mod mod, SubMod option)
|
||||
{
|
||||
UpdateFiles(mod, new CancellationToken());
|
||||
UpdatePaths(mod, option, false, new CancellationToken());
|
||||
}
|
||||
|
||||
public void UpdatePaths(Mod mod, ISubMod option)
|
||||
public void UpdatePaths(Mod mod, SubMod option)
|
||||
=> UpdatePaths(mod, option, true, new CancellationToken());
|
||||
|
||||
public void Clear()
|
||||
|
|
@ -59,7 +59,7 @@ public class ModFileCollection : IDisposable
|
|||
public void ClearMissingFiles()
|
||||
=> _missing.Clear();
|
||||
|
||||
public void RemoveUsedPath(ISubMod option, FileRegistry? file, Utf8GamePath gamePath)
|
||||
public void RemoveUsedPath(SubMod option, FileRegistry? file, Utf8GamePath gamePath)
|
||||
{
|
||||
_usedPaths.Remove(gamePath);
|
||||
if (file != null)
|
||||
|
|
@ -69,10 +69,10 @@ public class ModFileCollection : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
public void RemoveUsedPath(ISubMod option, FullPath file, Utf8GamePath gamePath)
|
||||
public void RemoveUsedPath(SubMod option, FullPath file, Utf8GamePath gamePath)
|
||||
=> RemoveUsedPath(option, _available.FirstOrDefault(f => f.File.Equals(file)), gamePath);
|
||||
|
||||
public void AddUsedPath(ISubMod option, FileRegistry? file, Utf8GamePath gamePath)
|
||||
public void AddUsedPath(SubMod option, FileRegistry? file, Utf8GamePath gamePath)
|
||||
{
|
||||
_usedPaths.Add(gamePath);
|
||||
if (file == null)
|
||||
|
|
@ -82,7 +82,7 @@ public class ModFileCollection : IDisposable
|
|||
file.SubModUsage.Add((option, gamePath));
|
||||
}
|
||||
|
||||
public void AddUsedPath(ISubMod option, FullPath file, Utf8GamePath gamePath)
|
||||
public void AddUsedPath(SubMod option, FullPath file, Utf8GamePath gamePath)
|
||||
=> AddUsedPath(option, _available.FirstOrDefault(f => f.File.Equals(file)), gamePath);
|
||||
|
||||
public void ChangeUsedPath(FileRegistry file, int pathIdx, Utf8GamePath gamePath)
|
||||
|
|
@ -154,7 +154,7 @@ public class ModFileCollection : IDisposable
|
|||
_usedPaths.Clear();
|
||||
}
|
||||
|
||||
private void UpdatePaths(Mod mod, ISubMod option, bool clearRegistries, CancellationToken tok)
|
||||
private void UpdatePaths(Mod mod, SubMod option, bool clearRegistries, CancellationToken tok)
|
||||
{
|
||||
tok.ThrowIfCancellationRequested();
|
||||
ClearPaths(clearRegistries, tok);
|
||||
|
|
|
|||
|
|
@ -30,16 +30,16 @@ public class ModFileEditor(ModFileCollection files, ModManager modManager, Commu
|
|||
return num;
|
||||
}
|
||||
|
||||
public void Revert(Mod mod, ISubMod option)
|
||||
public void Revert(Mod mod, SubMod option)
|
||||
{
|
||||
files.UpdateAll(mod, option);
|
||||
Changes = false;
|
||||
}
|
||||
|
||||
/// <summary> Remove all path redirections where the pointed-to file does not exist. </summary>
|
||||
public void RemoveMissingPaths(Mod mod, ISubMod option)
|
||||
public void RemoveMissingPaths(Mod mod, SubMod option)
|
||||
{
|
||||
void HandleSubMod(ISubMod subMod, int groupIdx, int optionIdx)
|
||||
void HandleSubMod(SubMod subMod, int groupIdx, int optionIdx)
|
||||
{
|
||||
var newDict = subMod.Files.Where(kvp => CheckAgainstMissing(mod, subMod, kvp.Value, kvp.Key, subMod == option))
|
||||
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
||||
|
|
@ -61,7 +61,7 @@ public class ModFileEditor(ModFileCollection files, ModManager modManager, Commu
|
|||
/// If path is empty, it will be deleted instead.
|
||||
/// If pathIdx is equal to the total number of paths, path will be added, otherwise replaced.
|
||||
/// </summary>
|
||||
public bool SetGamePath(ISubMod option, int fileIdx, int pathIdx, Utf8GamePath path)
|
||||
public bool SetGamePath(SubMod option, int fileIdx, int pathIdx, Utf8GamePath path)
|
||||
{
|
||||
if (!CanAddGamePath(path) || fileIdx < 0 || fileIdx > files.Available.Count)
|
||||
return false;
|
||||
|
|
@ -84,7 +84,7 @@ public class ModFileEditor(ModFileCollection files, ModManager modManager, Commu
|
|||
/// Transform a set of files to the appropriate game paths with the given number of folders skipped,
|
||||
/// and add them to the given option.
|
||||
/// </summary>
|
||||
public int AddPathsToSelected(ISubMod option, IEnumerable<FileRegistry> files1, int skipFolders = 0)
|
||||
public int AddPathsToSelected(SubMod option, IEnumerable<FileRegistry> files1, int skipFolders = 0)
|
||||
{
|
||||
var failed = 0;
|
||||
foreach (var file in files1)
|
||||
|
|
@ -111,7 +111,7 @@ public class ModFileEditor(ModFileCollection files, ModManager modManager, Commu
|
|||
}
|
||||
|
||||
/// <summary> Remove all paths in the current option from the given files. </summary>
|
||||
public void RemovePathsFromSelected(ISubMod option, IEnumerable<FileRegistry> files1)
|
||||
public void RemovePathsFromSelected(SubMod option, IEnumerable<FileRegistry> files1)
|
||||
{
|
||||
foreach (var file in files1)
|
||||
{
|
||||
|
|
@ -129,7 +129,7 @@ public class ModFileEditor(ModFileCollection files, ModManager modManager, Commu
|
|||
}
|
||||
|
||||
/// <summary> Delete all given files from your filesystem </summary>
|
||||
public void DeleteFiles(Mod mod, ISubMod option, IEnumerable<FileRegistry> files1)
|
||||
public void DeleteFiles(Mod mod, SubMod option, IEnumerable<FileRegistry> files1)
|
||||
{
|
||||
var deletions = 0;
|
||||
foreach (var file in files1)
|
||||
|
|
@ -155,7 +155,7 @@ public class ModFileEditor(ModFileCollection files, ModManager modManager, Commu
|
|||
}
|
||||
|
||||
|
||||
private bool CheckAgainstMissing(Mod mod, ISubMod option, FullPath file, Utf8GamePath key, bool removeUsed)
|
||||
private bool CheckAgainstMissing(Mod mod, SubMod option, FullPath file, Utf8GamePath key, bool removeUsed)
|
||||
{
|
||||
if (!files.Missing.Contains(file))
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ public class ModMerger : IDisposable
|
|||
MergeIntoOption(MergeFromMod!.AllSubMods.Reverse(), option, true);
|
||||
}
|
||||
|
||||
private void MergeIntoOption(IEnumerable<ISubMod> mergeOptions, SubMod option, bool fromFileToFile)
|
||||
private void MergeIntoOption(IEnumerable<SubMod> mergeOptions, SubMod option, bool fromFileToFile)
|
||||
{
|
||||
var redirections = option.FileData.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
||||
var swaps = option.FileSwapData.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ public class ModMetaEditor(ModManager modManager)
|
|||
Changes = true;
|
||||
}
|
||||
|
||||
public void Load(Mod mod, ISubMod currentOption)
|
||||
public void Load(Mod mod, SubMod currentOption)
|
||||
{
|
||||
OtherImcCount = 0;
|
||||
OtherEqpCount = 0;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ public class ModSwapEditor(ModManager modManager)
|
|||
public IReadOnlyDictionary<Utf8GamePath, FullPath> Swaps
|
||||
=> _swaps;
|
||||
|
||||
public void Revert(ISubMod option)
|
||||
public void Revert(SubMod option)
|
||||
{
|
||||
_swaps.SetTo(option.FileSwaps);
|
||||
Changes = false;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using Penumbra.GameData.Structs;
|
|||
using Penumbra.Meta.Manipulations;
|
||||
using Penumbra.String.Classes;
|
||||
using Penumbra.Meta;
|
||||
using Penumbra.Mods.Editor;
|
||||
using Penumbra.Mods.Manager;
|
||||
using Penumbra.Mods.Subclasses;
|
||||
|
||||
|
|
@ -15,14 +16,13 @@ public class ItemSwapContainer
|
|||
private readonly MetaFileManager _manager;
|
||||
private readonly ObjectIdentification _identifier;
|
||||
|
||||
private Dictionary<Utf8GamePath, FullPath> _modRedirections = [];
|
||||
private HashSet<MetaManipulation> _modManipulations = [];
|
||||
private AppliedModData _appliedModData = AppliedModData.Empty;
|
||||
|
||||
public IReadOnlyDictionary<Utf8GamePath, FullPath> ModRedirections
|
||||
=> _modRedirections;
|
||||
=> _appliedModData.FileRedirections;
|
||||
|
||||
public IReadOnlySet<MetaManipulation> ModManipulations
|
||||
=> _modManipulations;
|
||||
=> _appliedModData.Manipulations;
|
||||
|
||||
public readonly List<Swap> Swaps = [];
|
||||
|
||||
|
|
@ -97,12 +97,11 @@ public class ItemSwapContainer
|
|||
Clear();
|
||||
if (mod == null || mod.Index < 0)
|
||||
{
|
||||
_modRedirections = [];
|
||||
_modManipulations = [];
|
||||
_appliedModData = AppliedModData.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
(_modRedirections, _modManipulations) = ModSettings.GetResolveData(mod, settings);
|
||||
_appliedModData = ModSettings.GetResolveData(mod, settings);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -120,7 +119,7 @@ public class ItemSwapContainer
|
|||
|
||||
private Func<MetaManipulation, MetaManipulation> MetaResolver(ModCollection? collection)
|
||||
{
|
||||
var set = collection?.MetaCache?.Manipulations.ToHashSet() ?? _modManipulations;
|
||||
var set = collection?.MetaCache?.Manipulations.ToHashSet() ?? _appliedModData.Manipulations;
|
||||
return m => set.TryGetValue(m, out var a) ? a : m;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -262,15 +262,12 @@ public class ModOptionEditor(CommunicatorService communicator, SaveService saveS
|
|||
}
|
||||
|
||||
/// <summary> Add an existing option to a given group with default priority. </summary>
|
||||
public void AddOption(Mod mod, int groupIdx, ISubMod option)
|
||||
public void AddOption(Mod mod, int groupIdx, SubMod option)
|
||||
=> AddOption(mod, groupIdx, option, ModPriority.Default);
|
||||
|
||||
/// <summary> Add an existing option to a given group with a given priority. </summary>
|
||||
public void AddOption(Mod mod, int groupIdx, ISubMod option, ModPriority priority)
|
||||
public void AddOption(Mod mod, int groupIdx, SubMod option, ModPriority priority)
|
||||
{
|
||||
if (option is not SubMod o)
|
||||
return;
|
||||
|
||||
var group = mod.Groups[groupIdx];
|
||||
switch (group)
|
||||
{
|
||||
|
|
@ -280,12 +277,12 @@ public class ModOptionEditor(CommunicatorService communicator, SaveService saveS
|
|||
+ $"since only up to {IModGroup.MaxMultiOptions} options are supported in one group.");
|
||||
return;
|
||||
case SingleModGroup s:
|
||||
o.SetPosition(groupIdx, s.Count);
|
||||
s.OptionData.Add(o);
|
||||
option.SetPosition(groupIdx, s.Count);
|
||||
s.OptionData.Add(option);
|
||||
break;
|
||||
case MultiModGroup m:
|
||||
o.SetPosition(groupIdx, m.Count);
|
||||
m.PrioritizedOptions.Add((o, priority));
|
||||
option.SetPosition(groupIdx, m.Count);
|
||||
m.PrioritizedOptions.Add((option, priority));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@ public sealed class Mod : IMod
|
|||
public ModPriority Priority
|
||||
=> ModPriority.Default;
|
||||
|
||||
IReadOnlyList<IModGroup> IMod.Groups
|
||||
=> Groups;
|
||||
|
||||
internal Mod(DirectoryInfo modPath)
|
||||
{
|
||||
ModPath = modPath;
|
||||
|
|
@ -74,18 +77,12 @@ public sealed class Mod : IMod
|
|||
group.AddData(config, dictRedirections, setManips);
|
||||
}
|
||||
|
||||
((ISubMod)Default).AddData(dictRedirections, setManips);
|
||||
Default.AddData(dictRedirections, setManips);
|
||||
return new AppliedModData(dictRedirections, setManips);
|
||||
}
|
||||
|
||||
ISubMod IMod.Default
|
||||
=> Default;
|
||||
|
||||
IReadOnlyList<IModGroup> IMod.Groups
|
||||
=> Groups;
|
||||
|
||||
public IEnumerable<SubMod> AllSubMods
|
||||
=> Groups.SelectMany(o => o).OfType<SubMod>().Prepend(Default);
|
||||
=> Groups.SelectMany(o => o).Prepend(Default);
|
||||
|
||||
public List<FullPath> FindUnusedFiles()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ public partial class ModCreator(SaveService _saveService, Configuration config,
|
|||
|
||||
/// <summary> Create a file for an option group from given data. </summary>
|
||||
public void CreateOptionGroup(DirectoryInfo baseFolder, GroupType type, string name,
|
||||
ModPriority priority, int index, Setting defaultSettings, string desc, IEnumerable<ISubMod> subMods)
|
||||
ModPriority priority, int index, Setting defaultSettings, string desc, IEnumerable<SubMod> subMods)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
|
|
@ -248,7 +248,7 @@ public partial class ModCreator(SaveService _saveService, Configuration config,
|
|||
Priority = priority,
|
||||
DefaultSettings = defaultSettings,
|
||||
};
|
||||
group.PrioritizedOptions.AddRange(subMods.OfType<SubMod>().Select((s, idx) => (s, new ModPriority(idx))));
|
||||
group.PrioritizedOptions.AddRange(subMods.Select((s, idx) => (s, new ModPriority(idx))));
|
||||
_saveService.ImmediateSaveSync(new ModSaveGroup(baseFolder, group, index, Config.ReplaceNonAsciiOnImport));
|
||||
break;
|
||||
}
|
||||
|
|
@ -269,7 +269,7 @@ public partial class ModCreator(SaveService _saveService, Configuration config,
|
|||
}
|
||||
|
||||
/// <summary> Create the data for a given sub mod from its data and the folder it is based on. </summary>
|
||||
public ISubMod CreateSubMod(DirectoryInfo baseFolder, DirectoryInfo optionFolder, OptionList option)
|
||||
public SubMod CreateSubMod(DirectoryInfo baseFolder, DirectoryInfo optionFolder, OptionList option)
|
||||
{
|
||||
var list = optionFolder.EnumerateNonHiddenFiles()
|
||||
.Select(f => (Utf8GamePath.FromFile(f, optionFolder, out var gamePath, true), gamePath, new FullPath(f)))
|
||||
|
|
@ -288,7 +288,7 @@ public partial class ModCreator(SaveService _saveService, Configuration config,
|
|||
}
|
||||
|
||||
/// <summary> Create an empty sub mod for single groups with None options. </summary>
|
||||
internal static ISubMod CreateEmptySubMod(string name)
|
||||
internal static SubMod CreateEmptySubMod(string name)
|
||||
=> new SubMod(null!) // Mod is irrelevant here, only used for saving.
|
||||
{
|
||||
Name = name,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ using Penumbra.String.Classes;
|
|||
|
||||
namespace Penumbra.Mods.Subclasses;
|
||||
|
||||
public interface IModGroup : IReadOnlyCollection<ISubMod>
|
||||
public interface IModGroup : IReadOnlyCollection<SubMod>
|
||||
{
|
||||
public const int MaxMultiOptions = 63;
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ public interface IModGroup : IReadOnlyCollection<ISubMod>
|
|||
|
||||
public ModPriority OptionPriority(Index optionIdx);
|
||||
|
||||
public ISubMod this[Index idx] { get; }
|
||||
public SubMod this[Index idx] { get; }
|
||||
|
||||
public bool IsOption { get; }
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ public readonly struct ModSaveGroup : ISavable
|
|||
private readonly DirectoryInfo _basePath;
|
||||
private readonly IModGroup? _group;
|
||||
private readonly int _groupIdx;
|
||||
private readonly ISubMod? _defaultMod;
|
||||
private readonly SubMod? _defaultMod;
|
||||
private readonly bool _onlyAscii;
|
||||
|
||||
public ModSaveGroup(Mod mod, int groupIdx, bool onlyAscii)
|
||||
|
|
@ -59,7 +59,7 @@ public readonly struct ModSaveGroup : ISavable
|
|||
_onlyAscii = onlyAscii;
|
||||
}
|
||||
|
||||
public ModSaveGroup(DirectoryInfo basePath, ISubMod @default, bool onlyAscii)
|
||||
public ModSaveGroup(DirectoryInfo basePath, SubMod @default, bool onlyAscii)
|
||||
{
|
||||
_basePath = basePath;
|
||||
_groupIdx = -1;
|
||||
|
|
@ -91,7 +91,7 @@ public readonly struct ModSaveGroup : ISavable
|
|||
j.WriteStartArray();
|
||||
for (var idx = 0; idx < _group.Count; ++idx)
|
||||
{
|
||||
ISubMod.WriteSubMod(j, serializer, _group[idx], _basePath, _group.Type switch
|
||||
SubMod.WriteSubMod(j, serializer, _group[idx], _basePath, _group.Type switch
|
||||
{
|
||||
GroupType.Multi => _group.OptionPriority(idx),
|
||||
_ => null,
|
||||
|
|
@ -103,7 +103,7 @@ public readonly struct ModSaveGroup : ISavable
|
|||
}
|
||||
else
|
||||
{
|
||||
ISubMod.WriteSubMod(j, serializer, _defaultMod!, _basePath, null);
|
||||
SubMod.WriteSubMod(j, serializer, _defaultMod!, _basePath, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,67 +0,0 @@
|
|||
using Newtonsoft.Json;
|
||||
using Penumbra.Meta.Manipulations;
|
||||
using Penumbra.String.Classes;
|
||||
|
||||
namespace Penumbra.Mods.Subclasses;
|
||||
|
||||
public interface ISubMod
|
||||
{
|
||||
public string Name { get; }
|
||||
public string FullName { get; }
|
||||
public string Description { get; }
|
||||
|
||||
public IReadOnlyDictionary<Utf8GamePath, FullPath> Files { get; }
|
||||
public IReadOnlyDictionary<Utf8GamePath, FullPath> FileSwaps { get; }
|
||||
public IReadOnlySet<MetaManipulation> Manipulations { get; }
|
||||
|
||||
public void AddData(Dictionary<Utf8GamePath, FullPath> redirections, HashSet<MetaManipulation> manipulations)
|
||||
{
|
||||
foreach (var (path, file) in Files)
|
||||
redirections.TryAdd(path, file);
|
||||
|
||||
foreach (var (path, file) in FileSwaps)
|
||||
redirections.TryAdd(path, file);
|
||||
manipulations.UnionWith(Manipulations);
|
||||
}
|
||||
|
||||
public bool IsDefault { get; }
|
||||
|
||||
public static void WriteSubMod(JsonWriter j, JsonSerializer serializer, ISubMod mod, DirectoryInfo basePath, ModPriority? priority)
|
||||
{
|
||||
j.WriteStartObject();
|
||||
j.WritePropertyName(nameof(Name));
|
||||
j.WriteValue(mod.Name);
|
||||
j.WritePropertyName(nameof(Description));
|
||||
j.WriteValue(mod.Description);
|
||||
if (priority != null)
|
||||
{
|
||||
j.WritePropertyName(nameof(IModGroup.Priority));
|
||||
j.WriteValue(priority.Value.Value);
|
||||
}
|
||||
|
||||
j.WritePropertyName(nameof(mod.Files));
|
||||
j.WriteStartObject();
|
||||
foreach (var (gamePath, file) in mod.Files)
|
||||
{
|
||||
if (file.ToRelPath(basePath, out var relPath))
|
||||
{
|
||||
j.WritePropertyName(gamePath.ToString());
|
||||
j.WriteValue(relPath.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
j.WriteEndObject();
|
||||
j.WritePropertyName(nameof(mod.FileSwaps));
|
||||
j.WriteStartObject();
|
||||
foreach (var (gamePath, file) in mod.FileSwaps)
|
||||
{
|
||||
j.WritePropertyName(gamePath.ToString());
|
||||
j.WriteValue(file.ToString());
|
||||
}
|
||||
|
||||
j.WriteEndObject();
|
||||
j.WritePropertyName(nameof(mod.Manipulations));
|
||||
serializer.Serialize(j, mod.Manipulations);
|
||||
j.WriteEndObject();
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ using OtterGui;
|
|||
using OtterGui.Filesystem;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Meta.Manipulations;
|
||||
using Penumbra.Mods.Editor;
|
||||
using Penumbra.Mods.Manager;
|
||||
using Penumbra.String.Classes;
|
||||
|
||||
|
|
@ -34,44 +35,14 @@ public class ModSettings
|
|||
};
|
||||
|
||||
// Return everything required to resolve things for a single mod with given settings (which can be null, in which case the default is used.
|
||||
public static (Dictionary<Utf8GamePath, FullPath>, HashSet<MetaManipulation>) GetResolveData(Mod mod, ModSettings? settings)
|
||||
public static AppliedModData GetResolveData(Mod mod, ModSettings? settings)
|
||||
{
|
||||
if (settings == null)
|
||||
settings = DefaultSettings(mod);
|
||||
else
|
||||
settings.Settings.FixSize(mod);
|
||||
|
||||
var dict = new Dictionary<Utf8GamePath, FullPath>();
|
||||
var set = new HashSet<MetaManipulation>();
|
||||
|
||||
foreach (var (group, index) in mod.Groups.WithIndex().OrderByDescending(g => g.Value.Priority))
|
||||
{
|
||||
if (group.Type is GroupType.Single)
|
||||
{
|
||||
if (group.Count > 0)
|
||||
AddOption(group[settings.Settings[index].AsIndex]);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var (option, optionIdx) in group.WithIndex().OrderByDescending(o => group.OptionPriority(o.Index)))
|
||||
{
|
||||
if (settings.Settings[index].HasFlag(optionIdx))
|
||||
AddOption(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AddOption(mod.Default);
|
||||
return (dict, set);
|
||||
|
||||
void AddOption(ISubMod option)
|
||||
{
|
||||
foreach (var (path, file) in option.Files.Concat(option.FileSwaps))
|
||||
dict.TryAdd(path, file);
|
||||
|
||||
foreach (var manip in option.Manipulations)
|
||||
set.Add(manip);
|
||||
}
|
||||
return mod.GetData(settings);
|
||||
}
|
||||
|
||||
// Automatically react to changes in a mods available options.
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ public sealed class MultiModGroup : IModGroup
|
|||
public ModPriority OptionPriority(Index idx)
|
||||
=> PrioritizedOptions[idx].Priority;
|
||||
|
||||
public ISubMod this[Index idx]
|
||||
public SubMod this[Index idx]
|
||||
=> PrioritizedOptions[idx].Mod;
|
||||
|
||||
public bool IsOption
|
||||
|
|
@ -36,7 +36,7 @@ public sealed class MultiModGroup : IModGroup
|
|||
|
||||
public readonly List<(SubMod Mod, ModPriority Priority)> PrioritizedOptions = [];
|
||||
|
||||
public IEnumerator<ISubMod> GetEnumerator()
|
||||
public IEnumerator<SubMod> GetEnumerator()
|
||||
=> PrioritizedOptions.Select(o => o.Mod).GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
|
|
@ -117,7 +117,7 @@ public sealed class MultiModGroup : IModGroup
|
|||
foreach (var (option, index) in PrioritizedOptions.WithIndex().OrderByDescending(o => o.Value.Priority))
|
||||
{
|
||||
if (setting.HasFlag(index))
|
||||
((ISubMod)option.Mod).AddData(redirections, manipulations);
|
||||
option.Mod.AddData(redirections, manipulations);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ public sealed class SingleModGroup : IModGroup
|
|||
public ModPriority OptionPriority(Index _)
|
||||
=> Priority;
|
||||
|
||||
public ISubMod this[Index idx]
|
||||
public SubMod this[Index idx]
|
||||
=> OptionData[idx];
|
||||
|
||||
public bool IsOption
|
||||
|
|
@ -34,7 +34,7 @@ public sealed class SingleModGroup : IModGroup
|
|||
public int Count
|
||||
=> OptionData.Count;
|
||||
|
||||
public IEnumerator<ISubMod> GetEnumerator()
|
||||
public IEnumerator<SubMod> GetEnumerator()
|
||||
=> OptionData.GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Penumbra.Meta.Manipulations;
|
||||
using Penumbra.Mods.Editor;
|
||||
|
|
@ -15,7 +16,7 @@ namespace Penumbra.Mods.Subclasses;
|
|||
/// Nothing is checked for existence or validity when loading.
|
||||
/// Objects are also not checked for uniqueness, the first appearance of a game path or meta path decides.
|
||||
/// </summary>
|
||||
public sealed class SubMod : ISubMod
|
||||
public sealed class SubMod
|
||||
{
|
||||
public string Name { get; set; } = "Default";
|
||||
|
||||
|
|
@ -31,6 +32,16 @@ public sealed class SubMod : ISubMod
|
|||
public bool IsDefault
|
||||
=> GroupIdx < 0;
|
||||
|
||||
public void AddData(Dictionary<Utf8GamePath, FullPath> redirections, HashSet<MetaManipulation> manipulations)
|
||||
{
|
||||
foreach (var (path, file) in Files)
|
||||
redirections.TryAdd(path, file);
|
||||
|
||||
foreach (var (path, file) in FileSwaps)
|
||||
redirections.TryAdd(path, file);
|
||||
manipulations.UnionWith(Manipulations);
|
||||
}
|
||||
|
||||
public Dictionary<Utf8GamePath, FullPath> FileData = [];
|
||||
public Dictionary<Utf8GamePath, FullPath> FileSwapData = [];
|
||||
public HashSet<MetaManipulation> ManipulationData = [];
|
||||
|
|
@ -60,8 +71,8 @@ public sealed class SubMod : ISubMod
|
|||
ManipulationData.Clear();
|
||||
|
||||
// Every option has a name, but priorities are only relevant for multi group options.
|
||||
Name = json[nameof(ISubMod.Name)]?.ToObject<string>() ?? string.Empty;
|
||||
Description = json[nameof(ISubMod.Description)]?.ToObject<string>() ?? string.Empty;
|
||||
Name = json[nameof(Name)]?.ToObject<string>() ?? string.Empty;
|
||||
Description = json[nameof(Description)]?.ToObject<string>() ?? string.Empty;
|
||||
priority = json[nameof(IModGroup.Priority)]?.ToObject<ModPriority>() ?? ModPriority.Default;
|
||||
|
||||
var files = (JObject?)json[nameof(Files)];
|
||||
|
|
@ -104,4 +115,43 @@ public sealed class SubMod : ISubMod
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteSubMod(JsonWriter j, JsonSerializer serializer, SubMod mod, DirectoryInfo basePath, ModPriority? priority)
|
||||
{
|
||||
j.WriteStartObject();
|
||||
j.WritePropertyName(nameof(Name));
|
||||
j.WriteValue(mod.Name);
|
||||
j.WritePropertyName(nameof(Description));
|
||||
j.WriteValue(mod.Description);
|
||||
if (priority != null)
|
||||
{
|
||||
j.WritePropertyName(nameof(IModGroup.Priority));
|
||||
j.WriteValue(priority.Value.Value);
|
||||
}
|
||||
|
||||
j.WritePropertyName(nameof(mod.Files));
|
||||
j.WriteStartObject();
|
||||
foreach (var (gamePath, file) in mod.Files)
|
||||
{
|
||||
if (file.ToRelPath(basePath, out var relPath))
|
||||
{
|
||||
j.WritePropertyName(gamePath.ToString());
|
||||
j.WriteValue(relPath.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
j.WriteEndObject();
|
||||
j.WritePropertyName(nameof(mod.FileSwaps));
|
||||
j.WriteStartObject();
|
||||
foreach (var (gamePath, file) in mod.FileSwaps)
|
||||
{
|
||||
j.WritePropertyName(gamePath.ToString());
|
||||
j.WriteValue(file.ToString());
|
||||
}
|
||||
|
||||
j.WriteEndObject();
|
||||
j.WritePropertyName(nameof(mod.Manipulations));
|
||||
serializer.Serialize(j, mod.Manipulations);
|
||||
j.WriteEndObject();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,12 +39,9 @@ public class TemporaryMod : IMod
|
|||
dict.TryAdd(gamePath, file);
|
||||
}
|
||||
|
||||
return new AppliedModData(dict, Default.Manipulations);
|
||||
return new AppliedModData(dict, Default.ManipulationData);
|
||||
}
|
||||
|
||||
ISubMod IMod.Default
|
||||
=> Default;
|
||||
|
||||
public IReadOnlyList<IModGroup> Groups
|
||||
=> Array.Empty<IModGroup>();
|
||||
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ public partial class ModEditWindow
|
|||
ImGuiUtil.RightAlign(rightText);
|
||||
}
|
||||
|
||||
private void PrintGamePath(int i, int j, FileRegistry registry, ISubMod subMod, Utf8GamePath gamePath)
|
||||
private void PrintGamePath(int i, int j, FileRegistry registry, SubMod subMod, Utf8GamePath gamePath)
|
||||
{
|
||||
using var id = ImRaii.PushId(j);
|
||||
ImGui.TableNextColumn();
|
||||
|
|
@ -228,7 +228,7 @@ public partial class ModEditWindow
|
|||
}
|
||||
}
|
||||
|
||||
private void PrintNewGamePath(int i, FileRegistry registry, ISubMod subMod)
|
||||
private void PrintNewGamePath(int i, FileRegistry registry, SubMod subMod)
|
||||
{
|
||||
var tmp = _fileIdx == i && _pathIdx == -1 ? _gamePathEdit : string.Empty;
|
||||
var pos = ImGui.GetCursorPosX() - ImGui.GetFrameHeight();
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ public partial class ModEditWindow
|
|||
return fileRegistry;
|
||||
}
|
||||
|
||||
private static (DirectoryInfo, int) GetPreferredPath(Mod mod, ISubMod subMod, bool replaceNonAscii)
|
||||
private static (DirectoryInfo, int) GetPreferredPath(Mod mod, SubMod subMod, bool replaceNonAscii)
|
||||
{
|
||||
var path = mod.ModPath;
|
||||
var subDirs = 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue