mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-30 20:33:43 +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)
|
||||
_group!.WriteJson(j, serializer);
|
||||
else
|
||||
IModDataContainer.WriteModData(j, serializer, _defaultMod!, _basePath);
|
||||
SubModHelpers.WriteModContainer(j, serializer, _defaultMod!, _basePath);
|
||||
j.WriteEndObject();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ public sealed class MultiModGroup(Mod mod) : IModGroup, ITexToolsGroup
|
|||
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)
|
||||
{
|
||||
|
|
@ -140,10 +140,10 @@ public sealed class MultiModGroup(Mod mod) : IModGroup, ITexToolsGroup
|
|||
jWriter.WriteStartArray();
|
||||
foreach (var option in OptionData)
|
||||
{
|
||||
IModOption.WriteModOption(jWriter, option);
|
||||
SubModHelpers.WriteModOption(jWriter, option);
|
||||
jWriter.WritePropertyName(nameof(option.Priority));
|
||||
jWriter.WriteValue(option.Priority.Value);
|
||||
IModDataContainer.WriteModData(jWriter, serializer, option, basePath ?? Mod.ModPath);
|
||||
SubModHelpers.WriteModContainer(jWriter, serializer, option, basePath ?? Mod.ModPath);
|
||||
}
|
||||
|
||||
jWriter.WriteEndArray();
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ public sealed class SingleModGroup(Mod mod) : IModGroup, ITexToolsGroup
|
|||
public bool IsOption
|
||||
=> 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 ret = new SingleModGroup(mod)
|
||||
|
|
@ -144,8 +144,8 @@ public sealed class SingleModGroup(Mod mod) : IModGroup, ITexToolsGroup
|
|||
jWriter.WriteStartArray();
|
||||
foreach (var option in OptionData)
|
||||
{
|
||||
IModOption.WriteModOption(jWriter, option);
|
||||
IModDataContainer.WriteModData(jWriter, serializer, option, basePath ?? Mod.ModPath);
|
||||
SubModHelpers.WriteModOption(jWriter, option);
|
||||
SubModHelpers.WriteModContainer(jWriter, serializer, option, basePath ?? Mod.ModPath);
|
||||
}
|
||||
|
||||
jWriter.WriteEndArray();
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ public class ModOptionEditor(CommunicatorService communicator, SaveService saveS
|
|||
Description = option.Description,
|
||||
};
|
||||
if (option is IModDataContainer data)
|
||||
IModDataContainer.Clone(data, newOption);
|
||||
SubModHelpers.Clone(data, newOption);
|
||||
s.OptionData.Add(newOption);
|
||||
break;
|
||||
}
|
||||
|
|
@ -265,7 +265,7 @@ public class ModOptionEditor(CommunicatorService communicator, SaveService saveS
|
|||
Priority = option is MultiSubMod s ? s.Priority : ModPriority.Default,
|
||||
};
|
||||
if (option is IModDataContainer data)
|
||||
IModDataContainer.Clone(data, newOption);
|
||||
SubModHelpers.Clone(data, newOption);
|
||||
m.OptionData.Add(newOption);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ public sealed class Mod : IMod
|
|||
group.AddData(config, dictRedirections, setManips);
|
||||
}
|
||||
|
||||
Default.AddDataTo(dictRedirections, setManips);
|
||||
Default.AddTo(dictRedirections, setManips);
|
||||
return new AppliedModData(dictRedirections, setManips);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ public partial class ModCreator(
|
|||
try
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
|
@ -162,7 +162,7 @@ public partial class ModCreator(
|
|||
deleteList.AddRange(localDeleteList);
|
||||
}
|
||||
|
||||
IModDataContainer.DeleteDeleteList(deleteList, delete);
|
||||
DeleteDeleteList(deleteList, delete);
|
||||
|
||||
if (!changes)
|
||||
return;
|
||||
|
|
@ -221,7 +221,7 @@ public partial class ModCreator(
|
|||
}
|
||||
}
|
||||
|
||||
IModDataContainer.DeleteDeleteList(deleteList, delete);
|
||||
DeleteDeleteList(deleteList, delete);
|
||||
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.");
|
||||
using (var oldFile = File.CreateText(oldPath))
|
||||
{
|
||||
using var j = new JsonTextWriter(oldFile)
|
||||
{
|
||||
Formatting = Formatting.Indented,
|
||||
};
|
||||
using var j = new JsonTextWriter(oldFile);
|
||||
j.Formatting = Formatting.Indented;
|
||||
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.");
|
||||
using (var newFile = File.CreateText(newPath))
|
||||
{
|
||||
using var j = new JsonTextWriter(newFile)
|
||||
{
|
||||
Formatting = Formatting.Indented,
|
||||
};
|
||||
using var j = new JsonTextWriter(newFile);
|
||||
j.Formatting = Formatting.Indented;
|
||||
clone.WriteTo(j);
|
||||
}
|
||||
|
||||
|
|
@ -436,8 +432,8 @@ public partial class ModCreator(
|
|||
var json = JObject.Parse(File.ReadAllText(file.FullName));
|
||||
switch (json[nameof(Type)]?.ToObject<GroupType>() ?? GroupType.Single)
|
||||
{
|
||||
case GroupType.Multi: return MultiModGroup.Load(mod, json, groupIdx);
|
||||
case GroupType.Single: return SingleModGroup.Load(mod, json, groupIdx);
|
||||
case GroupType.Multi: return MultiModGroup.Load(mod, json);
|
||||
case GroupType.Single: return SingleModGroup.Load(mod, json);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
|
@ -446,5 +442,23 @@ public partial class ModCreator(
|
|||
}
|
||||
|
||||
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,9 +22,9 @@ public class DefaultSubMod(IMod mod) : IModDataContainer
|
|||
IModGroup? IModDataContainer.Group
|
||||
=> null;
|
||||
|
||||
public void AddDataTo(Dictionary<Utf8GamePath, FullPath> redirections, HashSet<MetaManipulation> manipulations)
|
||||
=> IModDataContainer.AddDataTo(this, redirections, manipulations);
|
||||
public void AddTo(Dictionary<Utf8GamePath, FullPath> redirections, HashSet<MetaManipulation> manipulations)
|
||||
=> SubModHelpers.AddContainerTo(this, redirections, manipulations);
|
||||
|
||||
public (int GroupIndex, int DataIndex) GetDataIndices()
|
||||
=> (-1, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Penumbra.Meta.Manipulations;
|
||||
using Penumbra.Mods.Editor;
|
||||
using Penumbra.Mods.Groups;
|
||||
|
|
@ -7,6 +5,7 @@ using Penumbra.String.Classes;
|
|||
|
||||
namespace Penumbra.Mods.SubMods;
|
||||
|
||||
|
||||
public interface IModDataContainer
|
||||
{
|
||||
public IMod Mod { get; }
|
||||
|
|
@ -16,116 +15,24 @@ public interface IModDataContainer
|
|||
public Dictionary<Utf8GamePath, FullPath> FileSwaps { 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()
|
||||
=> this switch
|
||||
{
|
||||
IModOption o => o.FullName,
|
||||
IModOption o => o.FullName,
|
||||
DefaultSubMod => DefaultSubMod.FullName,
|
||||
_ => $"Container {GetDataIndices().DataIndex + 1}",
|
||||
_ => $"Container {GetDataIndices().DataIndex + 1}",
|
||||
};
|
||||
|
||||
public string GetFullName()
|
||||
=> this switch
|
||||
{
|
||||
IModOption o => o.FullName,
|
||||
DefaultSubMod => DefaultSubMod.FullName,
|
||||
IModOption o => o.FullName,
|
||||
DefaultSubMod => DefaultSubMod.FullName,
|
||||
_ 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 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;
|
||||
|
|
|
|||
|
|
@ -1,27 +1,10 @@
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Penumbra.Mods.SubMods;
|
||||
|
||||
public interface IModOption
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string FullName { get; }
|
||||
public string Name { get; set; }
|
||||
public string FullName { get; }
|
||||
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 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)
|
||||
: this(mod, group)
|
||||
{
|
||||
IModOption.Load(json, this);
|
||||
IModDataContainer.Load(json, this, mod.ModPath);
|
||||
SubModHelpers.LoadOptionData(json, this);
|
||||
SubModHelpers.LoadDataContainer(json, this, mod.ModPath);
|
||||
Priority = json[nameof(IModGroup.Priority)]?.ToObject<ModPriority>() ?? ModPriority.Default;
|
||||
}
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ public class MultiSubMod(Mod mod, MultiModGroup group) : IModDataOption
|
|||
Description = Description,
|
||||
Priority = Priority,
|
||||
};
|
||||
IModDataContainer.Clone(this, ret);
|
||||
SubModHelpers.Clone(this, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -60,12 +60,12 @@ public class MultiSubMod(Mod mod, MultiModGroup group) : IModDataOption
|
|||
Name = Name,
|
||||
Description = Description,
|
||||
};
|
||||
IModDataContainer.Clone(this, ret);
|
||||
SubModHelpers.Clone(this, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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)
|
||||
=> new(null!, null!)
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ public class SingleSubMod(Mod mod, SingleModGroup group) : IModDataOption
|
|||
public SingleSubMod(Mod mod, SingleModGroup group, JToken json)
|
||||
: this(mod, group)
|
||||
{
|
||||
IModOption.Load(json, this);
|
||||
IModDataContainer.Load(json, this, mod.ModPath);
|
||||
SubModHelpers.LoadOptionData(json, this);
|
||||
SubModHelpers.LoadDataContainer(json, this, mod.ModPath);
|
||||
}
|
||||
|
||||
public SingleSubMod Clone(Mod mod, SingleModGroup group)
|
||||
|
|
@ -44,7 +44,7 @@ public class SingleSubMod(Mod mod, SingleModGroup group) : IModDataOption
|
|||
Name = Name,
|
||||
Description = Description,
|
||||
};
|
||||
IModDataContainer.Clone(this, ret);
|
||||
SubModHelpers.Clone(this, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -57,13 +57,13 @@ public class SingleSubMod(Mod mod, SingleModGroup group) : IModDataOption
|
|||
Description = Description,
|
||||
Priority = priority,
|
||||
};
|
||||
IModDataContainer.Clone(this, ret);
|
||||
SubModHelpers.Clone(this, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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()
|
||||
=> (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