Fix crash on load of meta files with secondary type / no slot info.

This commit is contained in:
Ottermandias 2021-04-20 15:41:05 +02:00
parent c3a8b4cb0b
commit 234712ca99
4 changed files with 47 additions and 34 deletions

View file

@ -55,7 +55,7 @@ namespace Penumbra.Importer
ObjectType.Unknown => false, ObjectType.Unknown => false,
ObjectType.Weapon => false, ObjectType.Weapon => false,
ObjectType.World => false, ObjectType.World => false,
_ => false _ => false,
}; };
} }
@ -93,11 +93,8 @@ namespace Penumbra.Importer
} }
PrimaryId = ushort.Parse( match.Groups[ "PrimaryId" ].Value ); PrimaryId = ushort.Parse( match.Groups[ "PrimaryId" ].Value );
if( !match.Groups[ "Slot" ].Success ) if( match.Groups[ "Slot" ].Success )
{ {
return;
}
switch( PrimaryType ) switch( PrimaryType )
{ {
case ObjectType.Equipment: case ObjectType.Equipment:
@ -116,6 +113,7 @@ namespace Penumbra.Importer
break; break;
} }
}
if( match.Groups[ "SecondaryType" ].Success if( match.Groups[ "SecondaryType" ].Success
&& GameData.StringToBodySlot.TryGetValue( match.Groups[ "SecondaryType" ].Value, out SecondaryType ) ) && GameData.StringToBodySlot.TryGetValue( match.Groups[ "SecondaryType" ].Value, out SecondaryType ) )

View file

@ -108,7 +108,7 @@ namespace Penumbra.MetaData
protected T GetEntry< T >( T[]?[] blocks, ushort idx, T defaultEntry ) protected T GetEntry< T >( T[]?[] blocks, ushort idx, T defaultEntry )
{ {
// Skip the zeroth item. // Skip the zeroth item.
idx = idx == 0 ? 1 : idx; idx = idx == 0 ? ( ushort )1 : idx;
var block = BlockIdx( idx ); var block = BlockIdx( idx );
var array = block < blocks.Length ? blocks[ block ] : null; var array = block < blocks.Length ? blocks[ block ] : null;
if( array == null ) if( array == null )
@ -122,7 +122,7 @@ namespace Penumbra.MetaData
protected ref T GetTrueEntry< T >( T[]?[] blocks, ushort idx ) protected ref T GetTrueEntry< T >( T[]?[] blocks, ushort idx )
{ {
// Skip the zeroth item. // Skip the zeroth item.
idx = idx == 0 ? 1 : idx; idx = idx == 0 ? ( ushort )1 : idx;
var block = BlockIdx( idx ); var block = BlockIdx( idx );
if( block >= TotalBlockCount ) if( block >= TotalBlockCount )
{ {

View file

@ -101,7 +101,7 @@ namespace Penumbra.MetaData
return 0; return 0;
} }
return !setDict.TryGetValue( setId, out var entry ) ? 0 : entry; return !setDict.TryGetValue( setId, out var entry ) ? (ushort) 0 : entry;
} }
public byte[] WriteBytes() public byte[] WriteBytes()

View file

@ -1,6 +1,8 @@
using System;
using System.ComponentModel; using System.ComponentModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Dalamud.Plugin;
using Lumina.Data.Files; using Lumina.Data.Files;
using Penumbra.Game; using Penumbra.Game;
using Penumbra.Mods; using Penumbra.Mods;
@ -9,9 +11,13 @@ namespace Penumbra.MetaData
{ {
public static class ImcExtensions public static class ImcExtensions
{ {
public static bool Equal( this ImcFile.ImageChangeData lhs, ImcFile.ImageChangeData rhs ) => public static bool Equal( this ImcFile.ImageChangeData lhs, ImcFile.ImageChangeData rhs )
lhs.MaterialId == rhs.MaterialId && lhs.DecalId == rhs.DecalId && lhs.AttributeMask == rhs.AttributeMask => lhs.MaterialId == rhs.MaterialId
&& lhs.SoundId == rhs.SoundId && lhs.VfxId == rhs.VfxId && lhs.MaterialAnimationId == rhs.MaterialAnimationId; && lhs.DecalId == rhs.DecalId
&& lhs.AttributeMask == rhs.AttributeMask
&& lhs.SoundId == rhs.SoundId
&& lhs.VfxId == rhs.VfxId
&& lhs.MaterialAnimationId == rhs.MaterialAnimationId;
private static void WriteBytes( this ImcFile.ImageChangeData variant, BinaryWriter bw ) private static void WriteBytes( this ImcFile.ImageChangeData variant, BinaryWriter bw )
{ {
@ -67,7 +73,7 @@ namespace Penumbra.MetaData
EquipSlot.RingR => 3, EquipSlot.RingR => 3,
EquipSlot.Feet => 4, EquipSlot.Feet => 4,
EquipSlot.RingL => 4, EquipSlot.RingL => 4,
_ => throw new InvalidEnumArgumentException() _ => throw new InvalidEnumArgumentException(),
}; };
} }
@ -76,20 +82,29 @@ namespace Penumbra.MetaData
return ref parts[ idx ].DefaultVariant; return ref parts[ idx ].DefaultVariant;
} }
if( imc.Variant > parts[ idx ].Variants.Length )
{
PluginLog.Debug( "Trying to manipulate invalid variant {Variant} of {NumVariants} in file {FileName}.", imc.Variant,
parts[ idx ].Variants.Length, file.FilePath.Path );
return ref parts[ idx ].Variants[ parts[ idx ].Variants.Length - 1 ];
}
else
{
return ref parts[ idx ].Variants[ imc.Variant - 1 ]; return ref parts[ idx ].Variants[ imc.Variant - 1 ];
} }
}
public static ImcFile Clone( this ImcFile file ) public static ImcFile Clone( this ImcFile file )
{ {
var ret = new ImcFile var ret = new ImcFile
{ {
Count = file.Count, Count = file.Count,
PartMask = file.PartMask PartMask = file.PartMask,
}; };
var parts = file.GetParts().Select( P => new ImcFile.ImageChangeParts() var parts = file.GetParts().Select( P => new ImcFile.ImageChangeParts()
{ {
DefaultVariant = P.DefaultVariant, DefaultVariant = P.DefaultVariant,
Variants = ( ImcFile.ImageChangeData[] )P.Variants.Clone() Variants = ( ImcFile.ImageChangeData[] )P.Variants.Clone(),
} ).ToArray(); } ).ToArray();
var prop = ret.GetType().GetField( "Parts", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance ); var prop = ret.GetType().GetField( "Parts", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance );
prop!.SetValue( ret, parts ); prop!.SetValue( ret, parts );