mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Fix crash on load of meta files with secondary type / no slot info.
This commit is contained in:
parent
c3a8b4cb0b
commit
234712ca99
4 changed files with 47 additions and 34 deletions
|
|
@ -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,32 +93,30 @@ 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 )
|
||||||
}
|
{
|
||||||
|
case ObjectType.Equipment:
|
||||||
|
case ObjectType.Accessory:
|
||||||
|
if( GameData.SuffixToEquipSlot.TryGetValue( match.Groups[ "Slot" ].Value, out var tmpSlot ) )
|
||||||
|
{
|
||||||
|
EquipSlot = tmpSlot;
|
||||||
|
}
|
||||||
|
|
||||||
switch( PrimaryType )
|
break;
|
||||||
{
|
case ObjectType.Character:
|
||||||
case ObjectType.Equipment:
|
if( GameData.SuffixToCustomizationType.TryGetValue( match.Groups[ "Slot" ].Value, out var tmpCustom ) )
|
||||||
case ObjectType.Accessory:
|
{
|
||||||
if( GameData.SuffixToEquipSlot.TryGetValue( match.Groups[ "Slot" ].Value, out var tmpSlot ) )
|
CustomizationType = tmpCustom;
|
||||||
{
|
}
|
||||||
EquipSlot = tmpSlot;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ObjectType.Character:
|
}
|
||||||
if( GameData.SuffixToCustomizationType.TryGetValue( match.Groups[ "Slot" ].Value, out var tmpCustom ) )
|
|
||||||
{
|
|
||||||
CustomizationType = tmpCustom;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 ) )
|
||||||
{
|
{
|
||||||
SecondaryId = ushort.Parse( match.Groups[ "SecondaryId" ].Value );
|
SecondaryId = ushort.Parse( match.Groups[ "SecondaryId" ].Value );
|
||||||
}
|
}
|
||||||
|
|
@ -217,8 +215,8 @@ namespace Penumbra.Importer
|
||||||
var id = reader.ReadUInt16();
|
var id = reader.ReadUInt16();
|
||||||
var value = reader.ReadUInt16();
|
var value = reader.ReadUInt16();
|
||||||
if( !gr.IsValid()
|
if( !gr.IsValid()
|
||||||
|| info.PrimaryType == ObjectType.Character && info.SecondaryType != BodySlot.Face && info.SecondaryType != BodySlot.Hair
|
|| info.PrimaryType == ObjectType.Character && info.SecondaryType != BodySlot.Face && info.SecondaryType != BodySlot.Hair
|
||||||
|| info.PrimaryType == ObjectType.Equipment && info.EquipSlot != EquipSlot.Head && info.EquipSlot != EquipSlot.Body )
|
|| info.PrimaryType == ObjectType.Equipment && info.EquipSlot != EquipSlot.Head && info.EquipSlot != EquipSlot.Body )
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 )
|
||||||
{
|
{
|
||||||
|
|
@ -141,7 +141,7 @@ namespace Penumbra.MetaData
|
||||||
using var bw = new BinaryWriter( mem );
|
using var bw = new BinaryWriter( mem );
|
||||||
|
|
||||||
foreach( var parameter in blocks.Where( array => array != null )
|
foreach( var parameter in blocks.Where( array => array != null )
|
||||||
.SelectMany( array => array ) )
|
.SelectMany( array => array ) )
|
||||||
{
|
{
|
||||||
bw.Write( transform( parameter ) );
|
bw.Write( transform( parameter ) );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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,7 +82,16 @@ namespace Penumbra.MetaData
|
||||||
return ref parts[ idx ].DefaultVariant;
|
return ref parts[ idx ].DefaultVariant;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ref parts[ idx ].Variants[ imc.Variant - 1 ];
|
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 ];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ImcFile Clone( this ImcFile file )
|
public static ImcFile Clone( this ImcFile file )
|
||||||
|
|
@ -84,12 +99,12 @@ namespace Penumbra.MetaData
|
||||||
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 );
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue