mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-16 05:34:25 +01:00
Improve meta manipulation handling a bit.
This commit is contained in:
parent
250c4034e0
commit
d7b60206d7
14 changed files with 242 additions and 66 deletions
|
|
@ -160,7 +160,7 @@ public class TemporaryApi(
|
||||||
/// Only returns true if all conversions are successful and distinct.
|
/// Only returns true if all conversions are successful and distinct.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static bool ConvertManips(string manipString,
|
private static bool ConvertManips(string manipString,
|
||||||
[NotNullWhen(true)] out HashSet<MetaManipulation>? manips)
|
[NotNullWhen(true)] out MetaDictionary? manips)
|
||||||
{
|
{
|
||||||
if (manipString.Length == 0)
|
if (manipString.Length == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -174,7 +174,7 @@ public class TemporaryApi(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
manips = new HashSet<MetaManipulation>(manipArray!.Length);
|
manips = new MetaDictionary(manipArray!.Length);
|
||||||
foreach (var manip in manipArray.Where(m => m.Validate()))
|
foreach (var manip in manipArray.Where(m => m.Validate()))
|
||||||
{
|
{
|
||||||
if (manips.Add(manip))
|
if (manips.Add(manip))
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ public class TempModManager : IDisposable
|
||||||
=> _modsForAllCollections;
|
=> _modsForAllCollections;
|
||||||
|
|
||||||
public RedirectResult Register(string tag, ModCollection? collection, Dictionary<Utf8GamePath, FullPath> dict,
|
public RedirectResult Register(string tag, ModCollection? collection, Dictionary<Utf8GamePath, FullPath> dict,
|
||||||
HashSet<MetaManipulation> manips, ModPriority priority)
|
MetaDictionary manips, ModPriority priority)
|
||||||
{
|
{
|
||||||
var mod = GetOrCreateMod(tag, collection, priority, out var created);
|
var mod = GetOrCreateMod(tag, collection, priority, out var created);
|
||||||
Penumbra.Log.Verbose($"{(created ? "Created" : "Changed")} temporary Mod {mod.Name}.");
|
Penumbra.Log.Verbose($"{(created ? "Created" : "Changed")} temporary Mod {mod.Name}.");
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,12 @@ using Penumbra.Meta.Files;
|
||||||
namespace Penumbra.Meta.Manipulations;
|
namespace Penumbra.Meta.Manipulations;
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
public readonly struct EqdpManipulation : IMetaManipulation<EqdpManipulation>
|
public readonly struct EqdpManipulation(EqdpIdentifier identifier, EqdpEntry entry) : IMetaManipulation<EqdpManipulation>
|
||||||
{
|
{
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public EqdpIdentifier Identifier { get; private init; }
|
public EqdpIdentifier Identifier { get; } = identifier;
|
||||||
public EqdpEntry Entry { get; private init; }
|
|
||||||
|
public EqdpEntry Entry { get; } = entry;
|
||||||
|
|
||||||
[JsonConverter(typeof(StringEnumConverter))]
|
[JsonConverter(typeof(StringEnumConverter))]
|
||||||
public Gender Gender
|
public Gender Gender
|
||||||
|
|
@ -31,20 +32,18 @@ public readonly struct EqdpManipulation : IMetaManipulation<EqdpManipulation>
|
||||||
|
|
||||||
[JsonConstructor]
|
[JsonConstructor]
|
||||||
public EqdpManipulation(EqdpEntry entry, EquipSlot slot, Gender gender, ModelRace race, PrimaryId setId)
|
public EqdpManipulation(EqdpEntry entry, EquipSlot slot, Gender gender, ModelRace race, PrimaryId setId)
|
||||||
{
|
: this(new EqdpIdentifier(setId, slot, Names.CombinedRace(gender, race)), Eqdp.Mask(slot) & entry)
|
||||||
Identifier = new EqdpIdentifier(setId, slot, Names.CombinedRace(gender, race));
|
{ }
|
||||||
Entry = Eqdp.Mask(Slot) & entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EqdpManipulation Copy(EqdpManipulation entry)
|
public EqdpManipulation Copy(EqdpManipulation entry)
|
||||||
{
|
{
|
||||||
if (entry.Slot != Slot)
|
if (entry.Slot != Slot)
|
||||||
{
|
{
|
||||||
var (bit1, bit2) = entry.Entry.ToBits(entry.Slot);
|
var (bit1, bit2) = entry.Entry.ToBits(entry.Slot);
|
||||||
return new EqdpManipulation(Eqdp.FromSlotAndBits(Slot, bit1, bit2), Slot, Gender, Race, SetId);
|
return new EqdpManipulation(Identifier, Eqdp.FromSlotAndBits(Slot, bit1, bit2));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new EqdpManipulation(entry.Entry, Slot, Gender, Race, SetId);
|
return new EqdpManipulation(Identifier, entry.Entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
public EqdpManipulation Copy(EqdpEntry entry)
|
public EqdpManipulation Copy(EqdpEntry entry)
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,13 @@ using Penumbra.Util;
|
||||||
namespace Penumbra.Meta.Manipulations;
|
namespace Penumbra.Meta.Manipulations;
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
public readonly struct EqpManipulation : IMetaManipulation<EqpManipulation>
|
public readonly struct EqpManipulation(EqpIdentifier identifier, EqpEntry entry) : IMetaManipulation<EqpManipulation>
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(ForceNumericFlagEnumConverter))]
|
[JsonIgnore]
|
||||||
public EqpEntry Entry { get; private init; }
|
public EqpIdentifier Identifier { get; } = identifier;
|
||||||
|
|
||||||
public EqpIdentifier Identifier { get; private init; }
|
[JsonConverter(typeof(ForceNumericFlagEnumConverter))]
|
||||||
|
public EqpEntry Entry { get; } = entry;
|
||||||
|
|
||||||
public PrimaryId SetId
|
public PrimaryId SetId
|
||||||
=> Identifier.SetId;
|
=> Identifier.SetId;
|
||||||
|
|
@ -25,13 +26,11 @@ public readonly struct EqpManipulation : IMetaManipulation<EqpManipulation>
|
||||||
|
|
||||||
[JsonConstructor]
|
[JsonConstructor]
|
||||||
public EqpManipulation(EqpEntry entry, EquipSlot slot, PrimaryId setId)
|
public EqpManipulation(EqpEntry entry, EquipSlot slot, PrimaryId setId)
|
||||||
{
|
: this(new EqpIdentifier(setId, slot), Eqp.Mask(slot) & entry)
|
||||||
Identifier = new EqpIdentifier(setId, slot);
|
{ }
|
||||||
Entry = Eqp.Mask(slot) & entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EqpManipulation Copy(EqpEntry entry)
|
public EqpManipulation Copy(EqpEntry entry)
|
||||||
=> new(entry, Slot, SetId);
|
=> new(Identifier, entry);
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
=> $"Eqp - {SetId} - {Slot}";
|
=> $"Eqp - {SetId} - {Slot}";
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ using Penumbra.Meta.Files;
|
||||||
namespace Penumbra.Meta.Manipulations;
|
namespace Penumbra.Meta.Manipulations;
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
public readonly struct EstManipulation : IMetaManipulation<EstManipulation>
|
public readonly struct EstManipulation(EstIdentifier identifier, EstEntry entry) : IMetaManipulation<EstManipulation>
|
||||||
{
|
{
|
||||||
public static string ToName(EstType type)
|
public static string ToName(EstType type)
|
||||||
=> type switch
|
=> type switch
|
||||||
|
|
@ -20,8 +20,9 @@ public readonly struct EstManipulation : IMetaManipulation<EstManipulation>
|
||||||
_ => "unk",
|
_ => "unk",
|
||||||
};
|
};
|
||||||
|
|
||||||
public EstIdentifier Identifier { get; private init; }
|
[JsonIgnore]
|
||||||
public EstEntry Entry { get; private init; }
|
public EstIdentifier Identifier { get; } = identifier;
|
||||||
|
public EstEntry Entry { get; } = entry;
|
||||||
|
|
||||||
[JsonConverter(typeof(StringEnumConverter))]
|
[JsonConverter(typeof(StringEnumConverter))]
|
||||||
public Gender Gender
|
public Gender Gender
|
||||||
|
|
@ -41,13 +42,11 @@ public readonly struct EstManipulation : IMetaManipulation<EstManipulation>
|
||||||
|
|
||||||
[JsonConstructor]
|
[JsonConstructor]
|
||||||
public EstManipulation(Gender gender, ModelRace race, EstType slot, PrimaryId setId, EstEntry entry)
|
public EstManipulation(Gender gender, ModelRace race, EstType slot, PrimaryId setId, EstEntry entry)
|
||||||
{
|
: this(new EstIdentifier(setId, slot, Names.CombinedRace(gender, race)), entry)
|
||||||
Entry = entry;
|
{ }
|
||||||
Identifier = new EstIdentifier(setId, slot, Names.CombinedRace(gender, race));
|
|
||||||
}
|
|
||||||
|
|
||||||
public EstManipulation Copy(EstEntry entry)
|
public EstManipulation Copy(EstEntry entry)
|
||||||
=> new(Gender, Race, Slot, SetId, entry);
|
=> new(Identifier, entry);
|
||||||
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Penumbra.GameData.Data;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
using Penumbra.Interop.Structs;
|
using Penumbra.Interop.Structs;
|
||||||
|
|
||||||
namespace Penumbra.Meta.Manipulations;
|
namespace Penumbra.Meta.Manipulations;
|
||||||
|
|
||||||
public readonly struct GlobalEqpManipulation : IMetaManipulation<GlobalEqpManipulation>
|
public readonly struct GlobalEqpManipulation : IMetaManipulation<GlobalEqpManipulation>, IMetaIdentifier
|
||||||
{
|
{
|
||||||
public GlobalEqpType Type { get; init; }
|
public GlobalEqpType Type { get; init; }
|
||||||
public PrimaryId Condition { get; init; }
|
public PrimaryId Condition { get; init; }
|
||||||
|
|
@ -19,6 +21,28 @@ public readonly struct GlobalEqpManipulation : IMetaManipulation<GlobalEqpManipu
|
||||||
return Condition != 0;
|
return Condition != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JObject AddToJson(JObject jObj)
|
||||||
|
{
|
||||||
|
jObj[nameof(Type)] = Type.ToString();
|
||||||
|
jObj[nameof(Condition)] = Condition.Id;
|
||||||
|
return jObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GlobalEqpManipulation? FromJson(JObject? jObj)
|
||||||
|
{
|
||||||
|
if (jObj == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var type = jObj[nameof(Type)]?.ToObject<GlobalEqpType>() ?? (GlobalEqpType)100;
|
||||||
|
var condition = jObj[nameof(Condition)]?.ToObject<PrimaryId>() ?? 0;
|
||||||
|
var ret = new GlobalEqpManipulation
|
||||||
|
{
|
||||||
|
Type = type,
|
||||||
|
Condition = condition,
|
||||||
|
};
|
||||||
|
return ret.Validate() ? ret : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public bool Equals(GlobalEqpManipulation other)
|
public bool Equals(GlobalEqpManipulation other)
|
||||||
=> Type == other.Type
|
=> Type == other.Type
|
||||||
|
|
@ -45,6 +69,9 @@ public readonly struct GlobalEqpManipulation : IMetaManipulation<GlobalEqpManipu
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
=> $"Global EQP - {Type}{(Condition != 0 ? $" - {Condition.Id}" : string.Empty)}";
|
=> $"Global EQP - {Type}{(Condition != 0 ? $" - {Condition.Id}" : string.Empty)}";
|
||||||
|
|
||||||
|
public void AddChangedItems(ObjectIdentification identifier, IDictionary<string, object?> changedItems)
|
||||||
|
{ }
|
||||||
|
|
||||||
public MetaIndex FileIndex()
|
public MetaIndex FileIndex()
|
||||||
=> (MetaIndex)(-1);
|
=> MetaIndex.Eqp;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,24 +6,23 @@ using Penumbra.Meta.Files;
|
||||||
namespace Penumbra.Meta.Manipulations;
|
namespace Penumbra.Meta.Manipulations;
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
public readonly struct GmpManipulation : IMetaManipulation<GmpManipulation>
|
public readonly struct GmpManipulation(GmpIdentifier identifier, GmpEntry entry) : IMetaManipulation<GmpManipulation>
|
||||||
{
|
{
|
||||||
public GmpIdentifier Identifier { get; private init; }
|
[JsonIgnore]
|
||||||
|
public GmpIdentifier Identifier { get; } = identifier;
|
||||||
|
|
||||||
public GmpEntry Entry { get; private init; }
|
public GmpEntry Entry { get; } = entry;
|
||||||
|
|
||||||
public PrimaryId SetId
|
public PrimaryId SetId
|
||||||
=> Identifier.SetId;
|
=> Identifier.SetId;
|
||||||
|
|
||||||
[JsonConstructor]
|
[JsonConstructor]
|
||||||
public GmpManipulation(GmpEntry entry, PrimaryId setId)
|
public GmpManipulation(GmpEntry entry, PrimaryId setId)
|
||||||
{
|
: this(new GmpIdentifier(setId), entry)
|
||||||
Entry = entry;
|
{ }
|
||||||
Identifier = new GmpIdentifier(setId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public GmpManipulation Copy(GmpEntry entry)
|
public GmpManipulation Copy(GmpEntry entry)
|
||||||
=> new(entry, SetId);
|
=> new(Identifier, entry);
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
=> $"Gmp - {SetId}";
|
=> $"Gmp - {SetId}";
|
||||||
|
|
|
||||||
140
Penumbra/Meta/Manipulations/MetaDictionary.cs
Normal file
140
Penumbra/Meta/Manipulations/MetaDictionary.cs
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Penumbra.GameData.Structs;
|
||||||
|
using ImcEntry = Penumbra.GameData.Structs.ImcEntry;
|
||||||
|
|
||||||
|
namespace Penumbra.Meta.Manipulations;
|
||||||
|
|
||||||
|
[JsonConverter(typeof(Converter))]
|
||||||
|
public sealed class MetaDictionary : HashSet<MetaManipulation>
|
||||||
|
{
|
||||||
|
public MetaDictionary()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public MetaDictionary(int capacity)
|
||||||
|
: base(capacity)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
private class Converter : JsonConverter<MetaDictionary>
|
||||||
|
{
|
||||||
|
public override void WriteJson(JsonWriter writer, MetaDictionary? value, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (value is null)
|
||||||
|
{
|
||||||
|
writer.WriteNull();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WriteStartArray();
|
||||||
|
foreach (var item in value)
|
||||||
|
{
|
||||||
|
writer.WriteStartObject();
|
||||||
|
writer.WritePropertyName("Type");
|
||||||
|
writer.WriteValue(item.ManipulationType.ToString());
|
||||||
|
writer.WritePropertyName("Manipulation");
|
||||||
|
serializer.Serialize(writer, item.Manipulation);
|
||||||
|
writer.WriteEndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WriteEndArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override MetaDictionary ReadJson(JsonReader reader, Type objectType, MetaDictionary? existingValue, bool hasExistingValue,
|
||||||
|
JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
var dict = existingValue ?? [];
|
||||||
|
dict.Clear();
|
||||||
|
var jObj = JArray.Load(reader);
|
||||||
|
foreach (var item in jObj)
|
||||||
|
{
|
||||||
|
var type = item["Type"]?.ToObject<MetaManipulation.Type>() ?? MetaManipulation.Type.Unknown;
|
||||||
|
if (type is MetaManipulation.Type.Unknown)
|
||||||
|
{
|
||||||
|
Penumbra.Log.Warning($"Invalid Meta Manipulation Type {type} encountered.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item["Manipulation"] is not JObject manip)
|
||||||
|
{
|
||||||
|
Penumbra.Log.Warning($"Manipulation of type {type} does not contain manipulation data.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case MetaManipulation.Type.Imc:
|
||||||
|
{
|
||||||
|
var identifier = ImcIdentifier.FromJson(manip);
|
||||||
|
var entry = manip["Entry"]?.ToObject<ImcEntry>();
|
||||||
|
if (identifier.HasValue && entry.HasValue)
|
||||||
|
dict.Add(new MetaManipulation(new ImcManipulation(identifier.Value, entry.Value)));
|
||||||
|
else
|
||||||
|
Penumbra.Log.Warning("Invalid IMC Manipulation encountered.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MetaManipulation.Type.Eqdp:
|
||||||
|
{
|
||||||
|
var identifier = EqdpIdentifier.FromJson(manip);
|
||||||
|
var entry = (EqdpEntry?)manip["Entry"]?.ToObject<ushort>();
|
||||||
|
if (identifier.HasValue && entry.HasValue)
|
||||||
|
dict.Add(new MetaManipulation(new EqdpManipulation(identifier.Value, entry.Value)));
|
||||||
|
else
|
||||||
|
Penumbra.Log.Warning("Invalid EQDP Manipulation encountered.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MetaManipulation.Type.Eqp:
|
||||||
|
{
|
||||||
|
var identifier = EqpIdentifier.FromJson(manip);
|
||||||
|
var entry = (EqpEntry?)manip["Entry"]?.ToObject<ulong>();
|
||||||
|
if (identifier.HasValue && entry.HasValue)
|
||||||
|
dict.Add(new MetaManipulation(new EqpManipulation(identifier.Value, entry.Value)));
|
||||||
|
else
|
||||||
|
Penumbra.Log.Warning("Invalid EQP Manipulation encountered.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MetaManipulation.Type.Est:
|
||||||
|
{
|
||||||
|
var identifier = EstIdentifier.FromJson(manip);
|
||||||
|
var entry = manip["Entry"]?.ToObject<EstEntry>();
|
||||||
|
if (identifier.HasValue && entry.HasValue)
|
||||||
|
dict.Add(new MetaManipulation(new EstManipulation(identifier.Value, entry.Value)));
|
||||||
|
else
|
||||||
|
Penumbra.Log.Warning("Invalid EST Manipulation encountered.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MetaManipulation.Type.Gmp:
|
||||||
|
{
|
||||||
|
var identifier = GmpIdentifier.FromJson(manip);
|
||||||
|
var entry = manip["Entry"]?.ToObject<GmpEntry>();
|
||||||
|
if (identifier.HasValue && entry.HasValue)
|
||||||
|
dict.Add(new MetaManipulation(new GmpManipulation(identifier.Value, entry.Value)));
|
||||||
|
else
|
||||||
|
Penumbra.Log.Warning("Invalid GMP Manipulation encountered.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MetaManipulation.Type.Rsp:
|
||||||
|
{
|
||||||
|
var identifier = RspIdentifier.FromJson(manip);
|
||||||
|
var entry = manip["Entry"]?.ToObject<RspEntry>();
|
||||||
|
if (identifier.HasValue && entry.HasValue)
|
||||||
|
dict.Add(new MetaManipulation(new RspManipulation(identifier.Value, entry.Value)));
|
||||||
|
else
|
||||||
|
Penumbra.Log.Warning("Invalid RSP Manipulation encountered.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MetaManipulation.Type.GlobalEqp:
|
||||||
|
{
|
||||||
|
var identifier = GlobalEqpManipulation.FromJson(manip);
|
||||||
|
if (identifier.HasValue)
|
||||||
|
dict.Add(new MetaManipulation(identifier.Value));
|
||||||
|
else
|
||||||
|
Penumbra.Log.Warning("Invalid Global EQP Manipulation encountered.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
using Lumina.Excel.GeneratedSheets;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Penumbra.GameData.Data;
|
using Penumbra.GameData.Data;
|
||||||
|
|
@ -12,13 +13,31 @@ public readonly record struct RspIdentifier(SubRace SubRace, RspAttribute Attrib
|
||||||
=> changedItems.TryAdd($"{SubRace.ToName()} {Attribute.ToFullString()}", null);
|
=> changedItems.TryAdd($"{SubRace.ToName()} {Attribute.ToFullString()}", null);
|
||||||
|
|
||||||
public MetaIndex FileIndex()
|
public MetaIndex FileIndex()
|
||||||
=> throw new NotImplementedException();
|
=> MetaIndex.HumanCmp;
|
||||||
|
|
||||||
public bool Validate()
|
public bool Validate()
|
||||||
=> throw new NotImplementedException();
|
=> SubRace is not SubRace.Unknown
|
||||||
|
&& Enum.IsDefined(SubRace)
|
||||||
|
&& Attribute is not RspAttribute.NumAttributes
|
||||||
|
&& Enum.IsDefined(Attribute);
|
||||||
|
|
||||||
public JObject AddToJson(JObject jObj)
|
public JObject AddToJson(JObject jObj)
|
||||||
=> throw new NotImplementedException();
|
{
|
||||||
|
jObj["SubRace"] = SubRace.ToString();
|
||||||
|
jObj["Attribute"] = Attribute.ToString();
|
||||||
|
return jObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RspIdentifier? FromJson(JObject? jObj)
|
||||||
|
{
|
||||||
|
if (jObj == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var subRace = jObj["SubRace"]?.ToObject<SubRace>() ?? SubRace.Unknown;
|
||||||
|
var attribute = jObj["Attribute"]?.ToObject<RspAttribute>() ?? RspAttribute.NumAttributes;
|
||||||
|
var ret = new RspIdentifier(subRace, attribute);
|
||||||
|
return ret.Validate() ? ret : null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonConverter(typeof(Converter))]
|
[JsonConverter(typeof(Converter))]
|
||||||
|
|
@ -28,6 +47,9 @@ public readonly record struct RspEntry(float Value) : IComparisonOperators<RspEn
|
||||||
public const float MaxValue = 512f;
|
public const float MaxValue = 512f;
|
||||||
public static readonly RspEntry One = new(1f);
|
public static readonly RspEntry One = new(1f);
|
||||||
|
|
||||||
|
public bool Validate()
|
||||||
|
=> Value is >= MinValue and <= MaxValue;
|
||||||
|
|
||||||
private class Converter : JsonConverter<RspEntry>
|
private class Converter : JsonConverter<RspEntry>
|
||||||
{
|
{
|
||||||
public override void WriteJson(JsonWriter writer, RspEntry value, JsonSerializer serializer)
|
public override void WriteJson(JsonWriter writer, RspEntry value, JsonSerializer serializer)
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,12 @@ using Penumbra.Meta.Files;
|
||||||
namespace Penumbra.Meta.Manipulations;
|
namespace Penumbra.Meta.Manipulations;
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
public readonly struct RspManipulation : IMetaManipulation<RspManipulation>
|
public readonly struct RspManipulation(RspIdentifier identifier, RspEntry entry) : IMetaManipulation<RspManipulation>
|
||||||
{
|
{
|
||||||
public RspIdentifier Identifier { get; private init; }
|
[JsonIgnore]
|
||||||
public RspEntry Entry { get; private init; }
|
public RspIdentifier Identifier { get; } = identifier;
|
||||||
|
|
||||||
|
public RspEntry Entry { get; } = entry;
|
||||||
|
|
||||||
[JsonConverter(typeof(StringEnumConverter))]
|
[JsonConverter(typeof(StringEnumConverter))]
|
||||||
public SubRace SubRace
|
public SubRace SubRace
|
||||||
|
|
@ -22,13 +24,11 @@ public readonly struct RspManipulation : IMetaManipulation<RspManipulation>
|
||||||
|
|
||||||
[JsonConstructor]
|
[JsonConstructor]
|
||||||
public RspManipulation(SubRace subRace, RspAttribute attribute, RspEntry entry)
|
public RspManipulation(SubRace subRace, RspAttribute attribute, RspEntry entry)
|
||||||
{
|
: this(new RspIdentifier(subRace, attribute), entry)
|
||||||
Entry = entry;
|
{ }
|
||||||
Identifier = new RspIdentifier(subRace, attribute);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RspManipulation Copy(RspEntry entry)
|
public RspManipulation Copy(RspEntry entry)
|
||||||
=> new(SubRace, Attribute, entry);
|
=> new(Identifier, entry);
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
=> $"Rsp - {SubRace.ToName()} - {Attribute.ToFullString()}";
|
=> $"Rsp - {SubRace.ToName()} - {Attribute.ToFullString()}";
|
||||||
|
|
@ -63,14 +63,5 @@ public readonly struct RspManipulation : IMetaManipulation<RspManipulation>
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Validate()
|
public bool Validate()
|
||||||
{
|
=> Identifier.Validate() && Entry.Validate();
|
||||||
if (SubRace is SubRace.Unknown || !Enum.IsDefined(SubRace))
|
|
||||||
return false;
|
|
||||||
if (!Enum.IsDefined(Attribute))
|
|
||||||
return false;
|
|
||||||
if (Entry.Value is < RspEntry.MinValue or > RspEntry.MaxValue)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ public class DefaultSubMod(IMod mod) : IModDataContainer
|
||||||
|
|
||||||
public Dictionary<Utf8GamePath, FullPath> Files { get; set; } = [];
|
public Dictionary<Utf8GamePath, FullPath> Files { get; set; } = [];
|
||||||
public Dictionary<Utf8GamePath, FullPath> FileSwaps { get; set; } = [];
|
public Dictionary<Utf8GamePath, FullPath> FileSwaps { get; set; } = [];
|
||||||
public HashSet<MetaManipulation> Manipulations { get; set; } = [];
|
public MetaDictionary Manipulations { get; set; } = [];
|
||||||
|
|
||||||
IMod IModDataContainer.Mod
|
IMod IModDataContainer.Mod
|
||||||
=> Mod;
|
=> Mod;
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,9 @@ public interface IModDataContainer
|
||||||
public IMod Mod { get; }
|
public IMod Mod { get; }
|
||||||
public IModGroup? Group { get; }
|
public IModGroup? Group { get; }
|
||||||
|
|
||||||
public Dictionary<Utf8GamePath, FullPath> Files { get; set; }
|
public Dictionary<Utf8GamePath, FullPath> Files { get; set; }
|
||||||
public Dictionary<Utf8GamePath, FullPath> FileSwaps { get; set; }
|
public Dictionary<Utf8GamePath, FullPath> FileSwaps { get; set; }
|
||||||
public HashSet<MetaManipulation> Manipulations { get; set; }
|
public MetaDictionary Manipulations { get; set; }
|
||||||
|
|
||||||
public string GetName();
|
public string GetName();
|
||||||
public string GetFullName();
|
public string GetFullName();
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ public abstract class OptionSubMod(IModGroup group) : IModOption, IModDataContai
|
||||||
|
|
||||||
public Dictionary<Utf8GamePath, FullPath> Files { get; set; } = [];
|
public Dictionary<Utf8GamePath, FullPath> Files { get; set; } = [];
|
||||||
public Dictionary<Utf8GamePath, FullPath> FileSwaps { get; set; } = [];
|
public Dictionary<Utf8GamePath, FullPath> FileSwaps { get; set; } = [];
|
||||||
public HashSet<MetaManipulation> Manipulations { get; set; } = [];
|
public MetaDictionary Manipulations { get; set; } = [];
|
||||||
|
|
||||||
public void AddDataTo(Dictionary<Utf8GamePath, FullPath> redirections, HashSet<MetaManipulation> manipulations)
|
public void AddDataTo(Dictionary<Utf8GamePath, FullPath> redirections, HashSet<MetaManipulation> manipulations)
|
||||||
=> SubMod.AddContainerTo(this, redirections, manipulations);
|
=> SubMod.AddContainerTo(this, redirections, manipulations);
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ public class TemporaryMod : IMod
|
||||||
public bool SetManipulation(MetaManipulation manip)
|
public bool SetManipulation(MetaManipulation manip)
|
||||||
=> Default.Manipulations.Remove(manip) | Default.Manipulations.Add(manip);
|
=> Default.Manipulations.Remove(manip) | Default.Manipulations.Add(manip);
|
||||||
|
|
||||||
public void SetAll(Dictionary<Utf8GamePath, FullPath> dict, HashSet<MetaManipulation> manips)
|
public void SetAll(Dictionary<Utf8GamePath, FullPath> dict, MetaDictionary manips)
|
||||||
{
|
{
|
||||||
Default.Files = dict;
|
Default.Files = dict;
|
||||||
Default.Manipulations = manips;
|
Default.Manipulations = manips;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue