Add some checks for valid variants in IMC Meta Edits.

This commit is contained in:
Ottermandias 2022-12-31 12:26:05 +01:00
parent a01f73cde4
commit 33b4905ae2
7 changed files with 39 additions and 16 deletions

View file

@ -963,7 +963,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi
} }
manips = new HashSet< MetaManipulation >( manipArray!.Length ); manips = new HashSet< MetaManipulation >( manipArray!.Length );
foreach( var manip in manipArray ) foreach( var manip in manipArray.Where( m => m.ManipulationType != MetaManipulation.Type.Unknown ) )
{ {
if( !manips.Add( manip ) ) if( !manips.Add( manip ) )
{ {

View file

@ -138,7 +138,11 @@ public partial class TexToolsMeta
{ {
if( _keepDefault || !value.Equals( def.GetEntry( partIdx, i ) ) ) if( _keepDefault || !value.Equals( def.GetEntry( partIdx, i ) ) )
{ {
MetaManipulations.Add( new ImcManipulation( manip.ObjectType, manip.BodySlot, manip.PrimaryId, manip.SecondaryId, i, manip.EquipSlot, value ) ); var imc = new ImcManipulation( manip.ObjectType, manip.BodySlot, manip.PrimaryId, manip.SecondaryId, i, manip.EquipSlot, value );
if( imc.Valid )
{
MetaManipulations.Add( imc );
}
} }
++i; ++i;

View file

@ -53,6 +53,11 @@ public partial class MetaManager
public bool ApplyMod( ImcManipulation manip ) public bool ApplyMod( ImcManipulation manip )
{ {
if( !manip.Valid )
{
return false;
}
_imcManipulations.AddOrReplace( manip ); _imcManipulations.AddOrReplace( manip );
var path = manip.GamePath(); var path = manip.GamePath();
try try
@ -91,7 +96,7 @@ public partial class MetaManager
public bool RevertMod( ImcManipulation m ) public bool RevertMod( ImcManipulation m )
{ {
if( !_imcManipulations.Remove( m ) ) if( !m.Valid || !_imcManipulations.Remove( m ) )
{ {
return false; return false;
} }

View file

@ -32,13 +32,17 @@ public readonly struct ImcManipulation : IMetaManipulation< ImcManipulation >
{ {
Entry = entry; Entry = entry;
PrimaryId = primaryId; PrimaryId = primaryId;
Variant = ( byte )variant; Variant = ( byte )Math.Clamp( variant, ( ushort )0, byte.MaxValue );
SecondaryId = 0; SecondaryId = 0;
ObjectType = equipSlot.IsAccessory() ? ObjectType.Accessory : ObjectType.Equipment; ObjectType = equipSlot.IsAccessory() ? ObjectType.Accessory : ObjectType.Equipment;
EquipSlot = equipSlot; EquipSlot = equipSlot;
BodySlot = BodySlot.Unknown; BodySlot = variant > byte.MaxValue ? BodySlot.Body : BodySlot.Unknown;
} }
// Variants were initially ushorts but got shortened to bytes.
// There are still some manipulations around that have values > 255 for variant,
// so we change the unused value to something nonsensical in that case, just so they do not compare equal,
// and clamp the variant to 255.
[JsonConstructor] [JsonConstructor]
internal ImcManipulation( ObjectType objectType, BodySlot bodySlot, ushort primaryId, ushort secondaryId, ushort variant, internal ImcManipulation( ObjectType objectType, BodySlot bodySlot, ushort primaryId, ushort secondaryId, ushort variant,
EquipSlot equipSlot, ImcEntry entry ) EquipSlot equipSlot, ImcEntry entry )
@ -46,16 +50,17 @@ public readonly struct ImcManipulation : IMetaManipulation< ImcManipulation >
Entry = entry; Entry = entry;
ObjectType = objectType; ObjectType = objectType;
PrimaryId = primaryId; PrimaryId = primaryId;
Variant = ( byte )variant; Variant = ( byte )Math.Clamp( variant, ( ushort )0, byte.MaxValue );
if( objectType is ObjectType.Accessory or ObjectType.Equipment ) if( objectType is ObjectType.Accessory or ObjectType.Equipment )
{ {
BodySlot = BodySlot.Unknown; BodySlot = variant > byte.MaxValue ? BodySlot.Body : BodySlot.Unknown;
SecondaryId = 0; SecondaryId = 0;
EquipSlot = equipSlot; EquipSlot = equipSlot;
} }
else if( objectType is ObjectType.DemiHuman ) else if( objectType is ObjectType.DemiHuman )
{ {
BodySlot = BodySlot.Unknown; BodySlot = variant > byte.MaxValue ? BodySlot.Body : BodySlot.Unknown;
SecondaryId = secondaryId; SecondaryId = secondaryId;
EquipSlot = equipSlot == EquipSlot.Unknown ? EquipSlot.Head : equipSlot; EquipSlot = equipSlot == EquipSlot.Unknown ? EquipSlot.Head : equipSlot;
} }
@ -63,10 +68,19 @@ public readonly struct ImcManipulation : IMetaManipulation< ImcManipulation >
{ {
BodySlot = bodySlot; BodySlot = bodySlot;
SecondaryId = secondaryId; SecondaryId = secondaryId;
EquipSlot = EquipSlot.Unknown; EquipSlot = variant > byte.MaxValue ? EquipSlot.All : EquipSlot.Unknown;
} }
} }
public bool Valid
=> ObjectType switch
{
ObjectType.Accessory => BodySlot == BodySlot.Unknown,
ObjectType.Equipment => BodySlot == BodySlot.Unknown,
ObjectType.DemiHuman => BodySlot == BodySlot.Unknown,
_ => EquipSlot == EquipSlot.Unknown,
};
public ImcManipulation Copy( ImcEntry entry ) public ImcManipulation Copy( ImcEntry entry )
=> new(ObjectType, BodySlot, PrimaryId, SecondaryId, Variant, EquipSlot, entry); => new(ObjectType, BodySlot, PrimaryId, SecondaryId, Variant, EquipSlot, entry);

View file

@ -100,7 +100,7 @@ public readonly struct MetaManipulation : IEquatable< MetaManipulation >, ICompa
return; return;
case ImcManipulation m: case ImcManipulation m:
Imc = m; Imc = m;
ManipulationType = Type.Imc; ManipulationType = m.Valid ? Type.Imc : Type.Unknown;
return; return;
} }
} }
@ -194,7 +194,7 @@ public readonly struct MetaManipulation : IEquatable< MetaManipulation >, ICompa
Type.Est => Est.Equals( other.Est ), Type.Est => Est.Equals( other.Est ),
Type.Rsp => Rsp.Equals( other.Rsp ), Type.Rsp => Rsp.Equals( other.Rsp ),
Type.Imc => Imc.Equals( other.Imc ), Type.Imc => Imc.Equals( other.Imc ),
_ => throw new ArgumentOutOfRangeException(), _ => false,
}; };
} }
@ -229,7 +229,7 @@ public readonly struct MetaManipulation : IEquatable< MetaManipulation >, ICompa
Type.Est => Est.GetHashCode(), Type.Est => Est.GetHashCode(),
Type.Rsp => Rsp.GetHashCode(), Type.Rsp => Rsp.GetHashCode(),
Type.Imc => Imc.GetHashCode(), Type.Imc => Imc.GetHashCode(),
_ => throw new ArgumentOutOfRangeException(), _ => 0,
}; };
public unsafe int CompareTo( MetaManipulation other ) public unsafe int CompareTo( MetaManipulation other )
@ -249,7 +249,7 @@ public readonly struct MetaManipulation : IEquatable< MetaManipulation >, ICompa
Type.Est => Est.ToString(), Type.Est => Est.ToString(),
Type.Rsp => Rsp.ToString(), Type.Rsp => Rsp.ToString(),
Type.Imc => Imc.ToString(), Type.Imc => Imc.ToString(),
_ => throw new ArgumentOutOfRangeException(), _ => "Invalid",
}; };
public string EntryToString() public string EntryToString()

View file

@ -173,7 +173,7 @@ public partial class Mod
var manips = json[ nameof( Manipulations ) ]; var manips = json[ nameof( Manipulations ) ];
if( manips != null ) if( manips != null )
{ {
foreach( var s in manips.Children().Select( c => c.ToObject< MetaManipulation >() ) ) foreach( var s in manips.Children().Select( c => c.ToObject< MetaManipulation >() ).Where( m => m.ManipulationType != MetaManipulation.Type.Unknown ) )
{ {
ManipulationData.Add( s ); ManipulationData.Add( s );
} }

View file

@ -930,7 +930,7 @@ public partial class ModEditWindow
var version = Functions.FromCompressedBase64< MetaManipulation[] >( clipboard, out var manips ); var version = Functions.FromCompressedBase64< MetaManipulation[] >( clipboard, out var manips );
if( version == MetaManipulation.CurrentVersion && manips != null ) if( version == MetaManipulation.CurrentVersion && manips != null )
{ {
foreach( var manip in manips ) foreach( var manip in manips.Where( m => m.ManipulationType != MetaManipulation.Type.Unknown ) )
{ {
_editor!.Meta.Set( manip ); _editor!.Meta.Set( manip );
} }
@ -950,7 +950,7 @@ public partial class ModEditWindow
if( version == MetaManipulation.CurrentVersion && manips != null ) if( version == MetaManipulation.CurrentVersion && manips != null )
{ {
_editor!.Meta.Clear(); _editor!.Meta.Clear();
foreach( var manip in manips ) foreach( var manip in manips.Where( m => m.ManipulationType != MetaManipulation.Type.Unknown ) )
{ {
_editor!.Meta.Set( manip ); _editor!.Meta.Set( manip );
} }