mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
129 lines
4.1 KiB
C#
129 lines
4.1 KiB
C#
using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Linq;
|
|
using Penumbra.GameData.Data;
|
|
using Penumbra.GameData.Enums;
|
|
using Penumbra.GameData.Structs;
|
|
using Penumbra.Interop.Structs;
|
|
|
|
namespace Penumbra.Meta.Manipulations;
|
|
|
|
public enum EstType : byte
|
|
{
|
|
Hair = MetaIndex.HairEst,
|
|
Face = MetaIndex.FaceEst,
|
|
Body = MetaIndex.BodyEst,
|
|
Head = MetaIndex.HeadEst,
|
|
}
|
|
|
|
public readonly record struct EstIdentifier(PrimaryId SetId, EstType Slot, GenderRace GenderRace)
|
|
: IMetaIdentifier, IComparable<EstIdentifier>
|
|
{
|
|
public ModelRace Race
|
|
=> GenderRace.Split().Item2;
|
|
|
|
public Gender Gender
|
|
=> GenderRace.Split().Item1;
|
|
|
|
public void AddChangedItems(ObjectIdentification identifier, IDictionary<string, IIdentifiedObjectData?> changedItems)
|
|
{
|
|
switch (Slot)
|
|
{
|
|
case EstType.Hair:
|
|
changedItems.TryAdd(
|
|
$"Customization: {GenderRace.Split().Item2.ToName()} {GenderRace.Split().Item1.ToName()} Hair (Hair) {SetId}", null);
|
|
break;
|
|
case EstType.Face:
|
|
changedItems.TryAdd(
|
|
$"Customization: {GenderRace.Split().Item2.ToName()} {GenderRace.Split().Item1.ToName()} Face (Face) {SetId}", null);
|
|
break;
|
|
case EstType.Body:
|
|
identifier.Identify(changedItems, GamePaths.Equipment.Mdl.Path(SetId, GenderRace, EquipSlot.Body));
|
|
break;
|
|
case EstType.Head:
|
|
identifier.Identify(changedItems, GamePaths.Equipment.Mdl.Path(SetId, GenderRace, EquipSlot.Head));
|
|
break;
|
|
}
|
|
}
|
|
|
|
public MetaIndex FileIndex()
|
|
=> (MetaIndex)Slot;
|
|
|
|
public override string ToString()
|
|
=> $"Est - {SetId} - {Slot} - {GenderRace.ToName()}";
|
|
|
|
public bool Validate()
|
|
{
|
|
if (!Enum.IsDefined(Slot))
|
|
return false;
|
|
if (GenderRace is GenderRace.Unknown || !Enum.IsDefined(GenderRace))
|
|
return false;
|
|
|
|
// No known check for set id.
|
|
return true;
|
|
}
|
|
|
|
public int CompareTo(EstIdentifier other)
|
|
{
|
|
var gr = GenderRace.CompareTo(other.GenderRace);
|
|
if (gr != 0)
|
|
return gr;
|
|
|
|
var id = SetId.Id.CompareTo(other.SetId.Id);
|
|
return id != 0 ? id : Slot.CompareTo(other.Slot);
|
|
}
|
|
|
|
public static EstIdentifier? FromJson(JObject jObj)
|
|
{
|
|
var gender = jObj["Gender"]?.ToObject<Gender>() ?? Gender.Unknown;
|
|
var race = jObj["Race"]?.ToObject<ModelRace>() ?? ModelRace.Unknown;
|
|
var setId = new PrimaryId(jObj["SetId"]?.ToObject<ushort>() ?? 0);
|
|
var slot = jObj["Slot"]?.ToObject<EstType>() ?? 0;
|
|
var ret = new EstIdentifier(setId, slot, Names.CombinedRace(gender, race));
|
|
return ret.Validate() ? ret : null;
|
|
}
|
|
|
|
public JObject AddToJson(JObject jObj)
|
|
{
|
|
var (gender, race) = GenderRace.Split();
|
|
jObj["Gender"] = gender.ToString();
|
|
jObj["Race"] = race.ToString();
|
|
jObj["SetId"] = SetId.Id.ToString();
|
|
jObj["Slot"] = Slot.ToString();
|
|
return jObj;
|
|
}
|
|
|
|
public MetaManipulationType Type
|
|
=> MetaManipulationType.Est;
|
|
}
|
|
|
|
[JsonConverter(typeof(Converter))]
|
|
public readonly record struct EstEntry(ushort Value)
|
|
{
|
|
public static readonly EstEntry Zero = new(0);
|
|
|
|
public PrimaryId AsId
|
|
=> new(Value);
|
|
|
|
private class Converter : JsonConverter<EstEntry>
|
|
{
|
|
public override void WriteJson(JsonWriter writer, EstEntry value, JsonSerializer serializer)
|
|
=> serializer.Serialize(writer, value.Value);
|
|
|
|
public override EstEntry ReadJson(JsonReader reader, Type objectType, EstEntry existingValue, bool hasExistingValue,
|
|
JsonSerializer serializer)
|
|
=> new(serializer.Deserialize<ushort>(reader));
|
|
}
|
|
}
|
|
|
|
public static class EstTypeExtension
|
|
{
|
|
public static string ToName(this EstType type)
|
|
=> type switch
|
|
{
|
|
EstType.Hair => "hair",
|
|
EstType.Face => "face",
|
|
EstType.Body => "top",
|
|
EstType.Head => "met",
|
|
_ => "unk",
|
|
};
|
|
}
|