mirror of
https://github.com/xivdev/Penumbra.git
synced 2026-02-21 07:17:53 +01:00
Some cleanup.
This commit is contained in:
parent
cd76c31d8c
commit
72db023804
12 changed files with 163 additions and 154 deletions
|
|
@ -51,7 +51,7 @@ public readonly struct ModSaveGroup : ISavable
|
||||||
if (_groupIdx >= 0)
|
if (_groupIdx >= 0)
|
||||||
_group!.WriteJson(j, serializer);
|
_group!.WriteJson(j, serializer);
|
||||||
else
|
else
|
||||||
IModDataContainer.WriteModData(j, serializer, _defaultMod!, _basePath);
|
SubModHelpers.WriteModContainer(j, serializer, _defaultMod!, _basePath);
|
||||||
j.WriteEndObject();
|
j.WriteEndObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ public sealed class MultiModGroup(Mod mod) : IModGroup, ITexToolsGroup
|
||||||
return OptionData.Count - 1;
|
return OptionData.Count - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MultiModGroup? Load(Mod mod, JObject json, int groupIdx)
|
public static MultiModGroup? Load(Mod mod, JObject json)
|
||||||
{
|
{
|
||||||
var ret = new MultiModGroup(mod)
|
var ret = new MultiModGroup(mod)
|
||||||
{
|
{
|
||||||
|
|
@ -140,10 +140,10 @@ public sealed class MultiModGroup(Mod mod) : IModGroup, ITexToolsGroup
|
||||||
jWriter.WriteStartArray();
|
jWriter.WriteStartArray();
|
||||||
foreach (var option in OptionData)
|
foreach (var option in OptionData)
|
||||||
{
|
{
|
||||||
IModOption.WriteModOption(jWriter, option);
|
SubModHelpers.WriteModOption(jWriter, option);
|
||||||
jWriter.WritePropertyName(nameof(option.Priority));
|
jWriter.WritePropertyName(nameof(option.Priority));
|
||||||
jWriter.WriteValue(option.Priority.Value);
|
jWriter.WriteValue(option.Priority.Value);
|
||||||
IModDataContainer.WriteModData(jWriter, serializer, option, basePath ?? Mod.ModPath);
|
SubModHelpers.WriteModContainer(jWriter, serializer, option, basePath ?? Mod.ModPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
jWriter.WriteEndArray();
|
jWriter.WriteEndArray();
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ public sealed class SingleModGroup(Mod mod) : IModGroup, ITexToolsGroup
|
||||||
public bool IsOption
|
public bool IsOption
|
||||||
=> OptionData.Count > 1;
|
=> OptionData.Count > 1;
|
||||||
|
|
||||||
public static SingleModGroup? Load(Mod mod, JObject json, int groupIdx)
|
public static SingleModGroup? Load(Mod mod, JObject json)
|
||||||
{
|
{
|
||||||
var options = json["Options"];
|
var options = json["Options"];
|
||||||
var ret = new SingleModGroup(mod)
|
var ret = new SingleModGroup(mod)
|
||||||
|
|
@ -144,8 +144,8 @@ public sealed class SingleModGroup(Mod mod) : IModGroup, ITexToolsGroup
|
||||||
jWriter.WriteStartArray();
|
jWriter.WriteStartArray();
|
||||||
foreach (var option in OptionData)
|
foreach (var option in OptionData)
|
||||||
{
|
{
|
||||||
IModOption.WriteModOption(jWriter, option);
|
SubModHelpers.WriteModOption(jWriter, option);
|
||||||
IModDataContainer.WriteModData(jWriter, serializer, option, basePath ?? Mod.ModPath);
|
SubModHelpers.WriteModContainer(jWriter, serializer, option, basePath ?? Mod.ModPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
jWriter.WriteEndArray();
|
jWriter.WriteEndArray();
|
||||||
|
|
|
||||||
|
|
@ -251,7 +251,7 @@ public class ModOptionEditor(CommunicatorService communicator, SaveService saveS
|
||||||
Description = option.Description,
|
Description = option.Description,
|
||||||
};
|
};
|
||||||
if (option is IModDataContainer data)
|
if (option is IModDataContainer data)
|
||||||
IModDataContainer.Clone(data, newOption);
|
SubModHelpers.Clone(data, newOption);
|
||||||
s.OptionData.Add(newOption);
|
s.OptionData.Add(newOption);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -265,7 +265,7 @@ public class ModOptionEditor(CommunicatorService communicator, SaveService saveS
|
||||||
Priority = option is MultiSubMod s ? s.Priority : ModPriority.Default,
|
Priority = option is MultiSubMod s ? s.Priority : ModPriority.Default,
|
||||||
};
|
};
|
||||||
if (option is IModDataContainer data)
|
if (option is IModDataContainer data)
|
||||||
IModDataContainer.Clone(data, newOption);
|
SubModHelpers.Clone(data, newOption);
|
||||||
m.OptionData.Add(newOption);
|
m.OptionData.Add(newOption);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ public sealed class Mod : IMod
|
||||||
group.AddData(config, dictRedirections, setManips);
|
group.AddData(config, dictRedirections, setManips);
|
||||||
}
|
}
|
||||||
|
|
||||||
Default.AddDataTo(dictRedirections, setManips);
|
Default.AddTo(dictRedirections, setManips);
|
||||||
return new AppliedModData(dictRedirections, setManips);
|
return new AppliedModData(dictRedirections, setManips);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ public partial class ModCreator(
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var jObject = File.Exists(defaultFile) ? JObject.Parse(File.ReadAllText(defaultFile)) : new JObject();
|
var jObject = File.Exists(defaultFile) ? JObject.Parse(File.ReadAllText(defaultFile)) : new JObject();
|
||||||
IModDataContainer.Load(jObject, mod.Default, mod.ModPath);
|
SubModHelpers.LoadDataContainer(jObject, mod.Default, mod.ModPath);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
@ -162,7 +162,7 @@ public partial class ModCreator(
|
||||||
deleteList.AddRange(localDeleteList);
|
deleteList.AddRange(localDeleteList);
|
||||||
}
|
}
|
||||||
|
|
||||||
IModDataContainer.DeleteDeleteList(deleteList, delete);
|
DeleteDeleteList(deleteList, delete);
|
||||||
|
|
||||||
if (!changes)
|
if (!changes)
|
||||||
return;
|
return;
|
||||||
|
|
@ -221,7 +221,7 @@ public partial class ModCreator(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IModDataContainer.DeleteDeleteList(deleteList, delete);
|
DeleteDeleteList(deleteList, delete);
|
||||||
return (oldSize < option.Manipulations.Count, deleteList);
|
return (oldSize < option.Manipulations.Count, deleteList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -392,10 +392,8 @@ public partial class ModCreator(
|
||||||
Penumbra.Log.Debug($"Writing the first {IModGroup.MaxMultiOptions} options to {Path.GetFileName(oldPath)} after split.");
|
Penumbra.Log.Debug($"Writing the first {IModGroup.MaxMultiOptions} options to {Path.GetFileName(oldPath)} after split.");
|
||||||
using (var oldFile = File.CreateText(oldPath))
|
using (var oldFile = File.CreateText(oldPath))
|
||||||
{
|
{
|
||||||
using var j = new JsonTextWriter(oldFile)
|
using var j = new JsonTextWriter(oldFile);
|
||||||
{
|
j.Formatting = Formatting.Indented;
|
||||||
Formatting = Formatting.Indented,
|
|
||||||
};
|
|
||||||
json.WriteTo(j);
|
json.WriteTo(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -403,10 +401,8 @@ public partial class ModCreator(
|
||||||
$"Writing the remaining {options.Count - IModGroup.MaxMultiOptions} options to {Path.GetFileName(newPath)} after split.");
|
$"Writing the remaining {options.Count - IModGroup.MaxMultiOptions} options to {Path.GetFileName(newPath)} after split.");
|
||||||
using (var newFile = File.CreateText(newPath))
|
using (var newFile = File.CreateText(newPath))
|
||||||
{
|
{
|
||||||
using var j = new JsonTextWriter(newFile)
|
using var j = new JsonTextWriter(newFile);
|
||||||
{
|
j.Formatting = Formatting.Indented;
|
||||||
Formatting = Formatting.Indented,
|
|
||||||
};
|
|
||||||
clone.WriteTo(j);
|
clone.WriteTo(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -436,8 +432,8 @@ public partial class ModCreator(
|
||||||
var json = JObject.Parse(File.ReadAllText(file.FullName));
|
var json = JObject.Parse(File.ReadAllText(file.FullName));
|
||||||
switch (json[nameof(Type)]?.ToObject<GroupType>() ?? GroupType.Single)
|
switch (json[nameof(Type)]?.ToObject<GroupType>() ?? GroupType.Single)
|
||||||
{
|
{
|
||||||
case GroupType.Multi: return MultiModGroup.Load(mod, json, groupIdx);
|
case GroupType.Multi: return MultiModGroup.Load(mod, json);
|
||||||
case GroupType.Single: return SingleModGroup.Load(mod, json, groupIdx);
|
case GroupType.Single: return SingleModGroup.Load(mod, json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|
@ -447,4 +443,22 @@ public partial class ModCreator(
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void DeleteDeleteList(IEnumerable<string> deleteList, bool delete)
|
||||||
|
{
|
||||||
|
if (!delete)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var file in deleteList)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Delete(file);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Penumbra.Log.Error($"Could not delete incorporated meta file {file}:\n{e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@ public class DefaultSubMod(IMod mod) : IModDataContainer
|
||||||
IModGroup? IModDataContainer.Group
|
IModGroup? IModDataContainer.Group
|
||||||
=> null;
|
=> null;
|
||||||
|
|
||||||
public void AddDataTo(Dictionary<Utf8GamePath, FullPath> redirections, HashSet<MetaManipulation> manipulations)
|
public void AddTo(Dictionary<Utf8GamePath, FullPath> redirections, HashSet<MetaManipulation> manipulations)
|
||||||
=> IModDataContainer.AddDataTo(this, redirections, manipulations);
|
=> SubModHelpers.AddContainerTo(this, redirections, manipulations);
|
||||||
|
|
||||||
public (int GroupIndex, int DataIndex) GetDataIndices()
|
public (int GroupIndex, int DataIndex) GetDataIndices()
|
||||||
=> (-1, 0);
|
=> (-1, 0);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using Penumbra.Meta.Manipulations;
|
using Penumbra.Meta.Manipulations;
|
||||||
using Penumbra.Mods.Editor;
|
using Penumbra.Mods.Editor;
|
||||||
using Penumbra.Mods.Groups;
|
using Penumbra.Mods.Groups;
|
||||||
|
|
@ -7,6 +5,7 @@ using Penumbra.String.Classes;
|
||||||
|
|
||||||
namespace Penumbra.Mods.SubMods;
|
namespace Penumbra.Mods.SubMods;
|
||||||
|
|
||||||
|
|
||||||
public interface IModDataContainer
|
public interface IModDataContainer
|
||||||
{
|
{
|
||||||
public IMod Mod { get; }
|
public IMod Mod { get; }
|
||||||
|
|
@ -16,116 +15,24 @@ public interface IModDataContainer
|
||||||
public Dictionary<Utf8GamePath, FullPath> FileSwaps { get; set; }
|
public Dictionary<Utf8GamePath, FullPath> FileSwaps { get; set; }
|
||||||
public HashSet<MetaManipulation> Manipulations { get; set; }
|
public HashSet<MetaManipulation> Manipulations { get; set; }
|
||||||
|
|
||||||
public static void AddDataTo(IModDataContainer container, Dictionary<Utf8GamePath, FullPath> redirections, HashSet<MetaManipulation> manipulations)
|
|
||||||
{
|
|
||||||
foreach (var (path, file) in container.Files)
|
|
||||||
redirections.TryAdd(path, file);
|
|
||||||
|
|
||||||
foreach (var (path, file) in container.FileSwaps)
|
|
||||||
redirections.TryAdd(path, file);
|
|
||||||
manipulations.UnionWith(container.Manipulations);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetName()
|
public string GetName()
|
||||||
=> this switch
|
=> this switch
|
||||||
{
|
{
|
||||||
IModOption o => o.FullName,
|
IModOption o => o.FullName,
|
||||||
DefaultSubMod => DefaultSubMod.FullName,
|
DefaultSubMod => DefaultSubMod.FullName,
|
||||||
_ => $"Container {GetDataIndices().DataIndex + 1}",
|
_ => $"Container {GetDataIndices().DataIndex + 1}",
|
||||||
};
|
};
|
||||||
|
|
||||||
public string GetFullName()
|
public string GetFullName()
|
||||||
=> this switch
|
=> this switch
|
||||||
{
|
{
|
||||||
IModOption o => o.FullName,
|
IModOption o => o.FullName,
|
||||||
DefaultSubMod => DefaultSubMod.FullName,
|
DefaultSubMod => DefaultSubMod.FullName,
|
||||||
_ when Group != null => $"{Group.Name}: Container {GetDataIndices().DataIndex + 1}",
|
_ when Group != null => $"{Group.Name}: Container {GetDataIndices().DataIndex + 1}",
|
||||||
_ => $"Container {GetDataIndices().DataIndex + 1}",
|
_ => $"Container {GetDataIndices().DataIndex + 1}",
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void Clone(IModDataContainer from, IModDataContainer to)
|
|
||||||
{
|
|
||||||
to.Files = new Dictionary<Utf8GamePath, FullPath>(from.Files);
|
|
||||||
to.FileSwaps = new Dictionary<Utf8GamePath, FullPath>(from.FileSwaps);
|
|
||||||
to.Manipulations = [.. from.Manipulations];
|
|
||||||
}
|
|
||||||
|
|
||||||
public (int GroupIndex, int DataIndex) GetDataIndices();
|
public (int GroupIndex, int DataIndex) GetDataIndices();
|
||||||
|
|
||||||
public static void Load(JToken json, IModDataContainer data, DirectoryInfo basePath)
|
|
||||||
{
|
|
||||||
data.Files.Clear();
|
|
||||||
data.FileSwaps.Clear();
|
|
||||||
data.Manipulations.Clear();
|
|
||||||
|
|
||||||
var files = (JObject?)json[nameof(Files)];
|
|
||||||
if (files != null)
|
|
||||||
foreach (var property in files.Properties())
|
|
||||||
{
|
|
||||||
if (Utf8GamePath.FromString(property.Name, out var p, true))
|
|
||||||
data.Files.TryAdd(p, new FullPath(basePath, property.Value.ToObject<Utf8RelPath>()));
|
|
||||||
}
|
|
||||||
|
|
||||||
var swaps = (JObject?)json[nameof(FileSwaps)];
|
|
||||||
if (swaps != null)
|
|
||||||
foreach (var property in swaps.Properties())
|
|
||||||
{
|
|
||||||
if (Utf8GamePath.FromString(property.Name, out var p, true))
|
|
||||||
data.FileSwaps.TryAdd(p, new FullPath(property.Value.ToObject<string>()!));
|
|
||||||
}
|
|
||||||
|
|
||||||
var manips = json[nameof(Manipulations)];
|
|
||||||
if (manips != null)
|
|
||||||
foreach (var s in manips.Children().Select(c => c.ToObject<MetaManipulation>())
|
|
||||||
.Where(m => m.Validate()))
|
|
||||||
data.Manipulations.Add(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void WriteModData(JsonWriter j, JsonSerializer serializer, IModDataContainer data, DirectoryInfo basePath)
|
|
||||||
{
|
|
||||||
j.WritePropertyName(nameof(data.Files));
|
|
||||||
j.WriteStartObject();
|
|
||||||
foreach (var (gamePath, file) in data.Files)
|
|
||||||
{
|
|
||||||
if (file.ToRelPath(basePath, out var relPath))
|
|
||||||
{
|
|
||||||
j.WritePropertyName(gamePath.ToString());
|
|
||||||
j.WriteValue(relPath.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
j.WriteEndObject();
|
|
||||||
j.WritePropertyName(nameof(data.FileSwaps));
|
|
||||||
j.WriteStartObject();
|
|
||||||
foreach (var (gamePath, file) in data.FileSwaps)
|
|
||||||
{
|
|
||||||
j.WritePropertyName(gamePath.ToString());
|
|
||||||
j.WriteValue(file.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
j.WriteEndObject();
|
|
||||||
j.WritePropertyName(nameof(data.Manipulations));
|
|
||||||
serializer.Serialize(j, data.Manipulations);
|
|
||||||
j.WriteEndObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void DeleteDeleteList(IEnumerable<string> deleteList, bool delete)
|
|
||||||
{
|
|
||||||
if (!delete)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var file in deleteList)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
File.Delete(file);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Penumbra.Log.Error($"Could not delete incorporated meta file {file}:\n{e}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IModDataOption : IModOption, IModDataContainer;
|
public interface IModDataOption : IModOption, IModDataContainer;
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,10 @@
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
|
|
||||||
namespace Penumbra.Mods.SubMods;
|
namespace Penumbra.Mods.SubMods;
|
||||||
|
|
||||||
public interface IModOption
|
public interface IModOption
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string FullName { get; }
|
public string FullName { get; }
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
|
|
||||||
public static void Load(JToken json, IModOption option)
|
|
||||||
{
|
|
||||||
option.Name = json[nameof(Name)]?.ToObject<string>() ?? string.Empty;
|
|
||||||
option.Description = json[nameof(Description)]?.ToObject<string>() ?? string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public (int GroupIndex, int OptionIndex) GetOptionIndices();
|
public (int GroupIndex, int OptionIndex) GetOptionIndices();
|
||||||
|
|
||||||
public static void WriteModOption(JsonWriter j, IModOption option)
|
|
||||||
{
|
|
||||||
j.WritePropertyName(nameof(Name));
|
|
||||||
j.WriteValue(option.Name);
|
|
||||||
j.WritePropertyName(nameof(Description));
|
|
||||||
j.WriteValue(option.Description);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,8 @@ public class MultiSubMod(Mod mod, MultiModGroup group) : IModDataOption
|
||||||
public MultiSubMod(Mod mod, MultiModGroup group, JToken json)
|
public MultiSubMod(Mod mod, MultiModGroup group, JToken json)
|
||||||
: this(mod, group)
|
: this(mod, group)
|
||||||
{
|
{
|
||||||
IModOption.Load(json, this);
|
SubModHelpers.LoadOptionData(json, this);
|
||||||
IModDataContainer.Load(json, this, mod.ModPath);
|
SubModHelpers.LoadDataContainer(json, this, mod.ModPath);
|
||||||
Priority = json[nameof(IModGroup.Priority)]?.ToObject<ModPriority>() ?? ModPriority.Default;
|
Priority = json[nameof(IModGroup.Priority)]?.ToObject<ModPriority>() ?? ModPriority.Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,7 +48,7 @@ public class MultiSubMod(Mod mod, MultiModGroup group) : IModDataOption
|
||||||
Description = Description,
|
Description = Description,
|
||||||
Priority = Priority,
|
Priority = Priority,
|
||||||
};
|
};
|
||||||
IModDataContainer.Clone(this, ret);
|
SubModHelpers.Clone(this, ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -60,12 +60,12 @@ public class MultiSubMod(Mod mod, MultiModGroup group) : IModDataOption
|
||||||
Name = Name,
|
Name = Name,
|
||||||
Description = Description,
|
Description = Description,
|
||||||
};
|
};
|
||||||
IModDataContainer.Clone(this, ret);
|
SubModHelpers.Clone(this, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddDataTo(Dictionary<Utf8GamePath, FullPath> redirections, HashSet<MetaManipulation> manipulations)
|
public void AddDataTo(Dictionary<Utf8GamePath, FullPath> redirections, HashSet<MetaManipulation> manipulations)
|
||||||
=> IModDataContainer.AddDataTo(this, redirections, manipulations);
|
=> SubModHelpers.AddContainerTo(this, redirections, manipulations);
|
||||||
|
|
||||||
public static MultiSubMod CreateForSaving(string name, string description, ModPriority priority)
|
public static MultiSubMod CreateForSaving(string name, string description, ModPriority priority)
|
||||||
=> new(null!, null!)
|
=> new(null!, null!)
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,8 @@ public class SingleSubMod(Mod mod, SingleModGroup group) : IModDataOption
|
||||||
public SingleSubMod(Mod mod, SingleModGroup group, JToken json)
|
public SingleSubMod(Mod mod, SingleModGroup group, JToken json)
|
||||||
: this(mod, group)
|
: this(mod, group)
|
||||||
{
|
{
|
||||||
IModOption.Load(json, this);
|
SubModHelpers.LoadOptionData(json, this);
|
||||||
IModDataContainer.Load(json, this, mod.ModPath);
|
SubModHelpers.LoadDataContainer(json, this, mod.ModPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SingleSubMod Clone(Mod mod, SingleModGroup group)
|
public SingleSubMod Clone(Mod mod, SingleModGroup group)
|
||||||
|
|
@ -44,7 +44,7 @@ public class SingleSubMod(Mod mod, SingleModGroup group) : IModDataOption
|
||||||
Name = Name,
|
Name = Name,
|
||||||
Description = Description,
|
Description = Description,
|
||||||
};
|
};
|
||||||
IModDataContainer.Clone(this, ret);
|
SubModHelpers.Clone(this, ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -57,13 +57,13 @@ public class SingleSubMod(Mod mod, SingleModGroup group) : IModDataOption
|
||||||
Description = Description,
|
Description = Description,
|
||||||
Priority = priority,
|
Priority = priority,
|
||||||
};
|
};
|
||||||
IModDataContainer.Clone(this, ret);
|
SubModHelpers.Clone(this, ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddDataTo(Dictionary<Utf8GamePath, FullPath> redirections, HashSet<MetaManipulation> manipulations)
|
public void AddDataTo(Dictionary<Utf8GamePath, FullPath> redirections, HashSet<MetaManipulation> manipulations)
|
||||||
=> IModDataContainer.AddDataTo(this, redirections, manipulations);
|
=> SubModHelpers.AddContainerTo(this, redirections, manipulations);
|
||||||
|
|
||||||
public (int GroupIndex, int DataIndex) GetDataIndices()
|
public (int GroupIndex, int DataIndex) GetDataIndices()
|
||||||
=> (Group.GetIndex(), GetDataIndex());
|
=> (Group.GetIndex(), GetDataIndex());
|
||||||
|
|
|
||||||
105
Penumbra/Mods/SubMods/SubModHelpers.cs
Normal file
105
Penumbra/Mods/SubMods/SubModHelpers.cs
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Penumbra.Meta.Manipulations;
|
||||||
|
using Penumbra.Mods.ItemSwap;
|
||||||
|
using Penumbra.String.Classes;
|
||||||
|
|
||||||
|
namespace Penumbra.Mods.SubMods;
|
||||||
|
|
||||||
|
public static class SubModHelpers
|
||||||
|
{
|
||||||
|
/// <summary> Add all unique meta manipulations, file redirections and then file swaps from a ModDataContainer to the given sets. Skip any keys that are already contained. </summary>
|
||||||
|
public static void AddContainerTo(IModDataContainer container, Dictionary<Utf8GamePath, FullPath> redirections,
|
||||||
|
HashSet<MetaManipulation> manipulations)
|
||||||
|
{
|
||||||
|
foreach (var (path, file) in container.Files)
|
||||||
|
redirections.TryAdd(path, file);
|
||||||
|
|
||||||
|
foreach (var (path, file) in container.FileSwaps)
|
||||||
|
redirections.TryAdd(path, file);
|
||||||
|
manipulations.UnionWith(container.Manipulations);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Replace all data of <paramref name="to"/> with the data of <paramref name="from"/>. </summary>
|
||||||
|
public static void Clone(IModDataContainer from, IModDataContainer to)
|
||||||
|
{
|
||||||
|
to.Files = new Dictionary<Utf8GamePath, FullPath>(from.Files);
|
||||||
|
to.FileSwaps = new Dictionary<Utf8GamePath, FullPath>(from.FileSwaps);
|
||||||
|
to.Manipulations = [.. from.Manipulations];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Load all file redirections, file swaps and meta manipulations from a JToken of that option into a data container. </summary>
|
||||||
|
public static void LoadDataContainer(JToken json, IModDataContainer data, DirectoryInfo basePath)
|
||||||
|
{
|
||||||
|
data.Files.Clear();
|
||||||
|
data.FileSwaps.Clear();
|
||||||
|
data.Manipulations.Clear();
|
||||||
|
|
||||||
|
var files = (JObject?)json[nameof(data.Files)];
|
||||||
|
if (files != null)
|
||||||
|
foreach (var property in files.Properties())
|
||||||
|
{
|
||||||
|
if (Utf8GamePath.FromString(property.Name, out var p, true))
|
||||||
|
data.Files.TryAdd(p, new FullPath(basePath, property.Value.ToObject<Utf8RelPath>()));
|
||||||
|
}
|
||||||
|
|
||||||
|
var swaps = (JObject?)json[nameof(data.FileSwaps)];
|
||||||
|
if (swaps != null)
|
||||||
|
foreach (var property in swaps.Properties())
|
||||||
|
{
|
||||||
|
if (Utf8GamePath.FromString(property.Name, out var p, true))
|
||||||
|
data.FileSwaps.TryAdd(p, new FullPath(property.Value.ToObject<string>()!));
|
||||||
|
}
|
||||||
|
|
||||||
|
var manips = json[nameof(data.Manipulations)];
|
||||||
|
if (manips != null)
|
||||||
|
foreach (var s in manips.Children().Select(c => c.ToObject<MetaManipulation>())
|
||||||
|
.Where(m => m.Validate()))
|
||||||
|
data.Manipulations.Add(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Load the relevant data for a selectable option from a JToken of that option. </summary>
|
||||||
|
public static void LoadOptionData(JToken json, IModOption option)
|
||||||
|
{
|
||||||
|
option.Name = json[nameof(option.Name)]?.ToObject<string>() ?? string.Empty;
|
||||||
|
option.Description = json[nameof(option.Description)]?.ToObject<string>() ?? string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Write file redirections, file swaps and meta manipulations from a data container on a JsonWriter. </summary>
|
||||||
|
public static void WriteModContainer(JsonWriter j, JsonSerializer serializer, IModDataContainer data, DirectoryInfo basePath)
|
||||||
|
{
|
||||||
|
j.WritePropertyName(nameof(data.Files));
|
||||||
|
j.WriteStartObject();
|
||||||
|
foreach (var (gamePath, file) in data.Files)
|
||||||
|
{
|
||||||
|
if (file.ToRelPath(basePath, out var relPath))
|
||||||
|
{
|
||||||
|
j.WritePropertyName(gamePath.ToString());
|
||||||
|
j.WriteValue(relPath.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
j.WriteEndObject();
|
||||||
|
j.WritePropertyName(nameof(data.FileSwaps));
|
||||||
|
j.WriteStartObject();
|
||||||
|
foreach (var (gamePath, file) in data.FileSwaps)
|
||||||
|
{
|
||||||
|
j.WritePropertyName(gamePath.ToString());
|
||||||
|
j.WriteValue(file.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
j.WriteEndObject();
|
||||||
|
j.WritePropertyName(nameof(data.Manipulations));
|
||||||
|
serializer.Serialize(j, data.Manipulations);
|
||||||
|
j.WriteEndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Write the data for a selectable mod option on a JsonWriter. </summary>
|
||||||
|
public static void WriteModOption(JsonWriter j, IModOption option)
|
||||||
|
{
|
||||||
|
j.WritePropertyName(nameof(option.Name));
|
||||||
|
j.WriteValue(option.Name);
|
||||||
|
j.WritePropertyName(nameof(option.Description));
|
||||||
|
j.WriteValue(option.Description);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue