Improve IMC Exception Handling.

This commit is contained in:
Ottermandias 2022-10-12 17:23:11 +02:00
parent b3814e61d1
commit 1be3b06292
5 changed files with 56 additions and 20 deletions

View file

@ -132,7 +132,7 @@ public partial class TexToolsMeta
{ {
if( metaFileInfo.PrimaryType is ObjectType.Equipment or ObjectType.Accessory ) if( metaFileInfo.PrimaryType is ObjectType.Equipment or ObjectType.Accessory )
{ {
var def = new ImcFile( new ImcManipulation( metaFileInfo.EquipSlot, i, metaFileInfo.PrimaryId, new ImcEntry() ).GamePath() ); var def = new ImcFile( new ImcManipulation( metaFileInfo.EquipSlot, i, metaFileInfo.PrimaryId, new ImcEntry() ) );
var partIdx = ImcFile.PartIndex( metaFileInfo.EquipSlot ); var partIdx = ImcFile.PartIndex( metaFileInfo.EquipSlot );
foreach( var value in values ) foreach( var value in values )
{ {
@ -148,7 +148,7 @@ public partial class TexToolsMeta
{ {
var def = new ImcFile( new ImcManipulation( metaFileInfo.PrimaryType, metaFileInfo.SecondaryType, metaFileInfo.PrimaryId, var def = new ImcFile( new ImcManipulation( metaFileInfo.PrimaryType, metaFileInfo.SecondaryType, metaFileInfo.PrimaryId,
metaFileInfo.SecondaryId, i, metaFileInfo.SecondaryId, i,
new ImcEntry() ).GamePath() ); new ImcEntry() ) );
foreach( var value in values ) foreach( var value in values )
{ {
if( !value.Equals( def.GetEntry( 0, i ) ) ) if( !value.Equals( def.GetEntry( 0, i ) ) )

View file

@ -5,6 +5,7 @@ using Penumbra.GameData.ByteString;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Util; using Penumbra.GameData.Util;
using Penumbra.Interop.Structs; using Penumbra.Interop.Structs;
using Penumbra.Meta.Manipulations;
namespace Penumbra.Meta.Files; namespace Penumbra.Meta.Files;
@ -54,6 +55,24 @@ public readonly struct ImcEntry : IEquatable< ImcEntry >
} }
} }
public class ImcException : Exception
{
public readonly ImcManipulation Manipulation;
public readonly string GamePath;
public ImcException( ImcManipulation manip, Utf8GamePath path )
{
Manipulation = manip;
GamePath = path.ToString();
}
public override string Message
=> "Could not obtain default Imc File.\n"
+ " Either the default file does not exist (possibly for offhand files from TexTools) or the installation is corrupted.\n"
+ $" Game Path: {GamePath}\n"
+ $" Manipulation: {Manipulation}";
}
public unsafe class ImcFile : MetaBaseFile public unsafe class ImcFile : MetaBaseFile
{ {
private const int PreambleSize = 4; private const int PreambleSize = 4;
@ -174,16 +193,14 @@ public unsafe class ImcFile : MetaBaseFile
} }
} }
public ImcFile( Utf8GamePath path ) public ImcFile( ImcManipulation manip )
: base( 0 ) : base( 0 )
{ {
Path = path; Path = manip.GamePath();
var file = Dalamud.GameData.GetFile( path.ToString() ); var file = Dalamud.GameData.GetFile( Path.ToString() );
if( file == null ) if( file == null )
{ {
throw new Exception( throw new ImcException( manip, Path );
"Could not obtain default Imc File.\n"
+ "Either the default file does not exist (possibly for offhand files from TexTools) or the installation is corrupted." );
} }
fixed( byte* ptr = file.Data ) fixed( byte* ptr = file.Data )
@ -211,6 +228,7 @@ public unsafe class ImcFile : MetaBaseFile
exists = true; exists = true;
return *entry; return *entry;
} }
return new ImcEntry(); return new ImcEntry();
} }
} }
@ -221,9 +239,10 @@ public unsafe class ImcFile : MetaBaseFile
var newData = Penumbra.MetaFileManager.AllocateDefaultMemory( ActualLength, 8 ); var newData = Penumbra.MetaFileManager.AllocateDefaultMemory( ActualLength, 8 );
if( newData == null ) if( newData == null )
{ {
Penumbra.Log.Error($"Could not replace loaded IMC data at 0x{(ulong) resource:X}, allocation failed." ); Penumbra.Log.Error( $"Could not replace loaded IMC data at 0x{( ulong )resource:X}, allocation failed." );
return; return;
} }
Functions.MemCpyUnchecked( newData, Data, ActualLength ); Functions.MemCpyUnchecked( newData, Data, ActualLength );
Penumbra.MetaFileManager.Free( data, length ); Penumbra.MetaFileManager.Free( data, length );

View file

@ -58,7 +58,7 @@ public partial class MetaManager
{ {
if( !_imcFiles.TryGetValue( path, out var file ) ) if( !_imcFiles.TryGetValue( path, out var file ) )
{ {
file = new ImcFile( path ); file = new ImcFile( manip );
} }
if( !manip.Apply( file ) ) if( !manip.Apply( file ) )
@ -75,12 +75,17 @@ public partial class MetaManager
return true; return true;
} }
catch( ImcException e )
{
Penumbra.ImcExceptions.Add( e );
Penumbra.Log.Error( e.ToString() );
}
catch( Exception e ) catch( Exception e )
{ {
++Penumbra.ImcExceptions; Penumbra.Log.Error( $"Could not apply IMC Manipulation {manip}:\n{e}" );
Penumbra.Log.Error( $"Could not apply IMC Manipulation:\n{e}" );
return false;
} }
return false;
} }
public bool RevertMod( ImcManipulation m ) public bool RevertMod( ImcManipulation m )

View file

@ -17,7 +17,6 @@ using OtterGui.Log;
using OtterGui.Widgets; using OtterGui.Widgets;
using Penumbra.Api; using Penumbra.Api;
using Penumbra.Api.Enums; using Penumbra.Api.Enums;
using Penumbra.GameData.Enums;
using Penumbra.Interop; using Penumbra.Interop;
using Penumbra.UI; using Penumbra.UI;
using Penumbra.Util; using Penumbra.Util;
@ -25,7 +24,6 @@ using Penumbra.Collections;
using Penumbra.Interop.Loader; using Penumbra.Interop.Loader;
using Penumbra.Interop.Resolver; using Penumbra.Interop.Resolver;
using Penumbra.Mods; using Penumbra.Mods;
using Action = System.Action;
using CharacterUtility = Penumbra.Interop.CharacterUtility; using CharacterUtility = Penumbra.Interop.CharacterUtility;
using ResidentResourceManager = Penumbra.Interop.ResidentResourceManager; using ResidentResourceManager = Penumbra.Interop.ResidentResourceManager;
@ -57,7 +55,7 @@ public class Penumbra : IDalamudPlugin
public static TempModManager TempMods { get; private set; } = null!; public static TempModManager TempMods { get; private set; } = null!;
public static ResourceLoader ResourceLoader { get; private set; } = null!; public static ResourceLoader ResourceLoader { get; private set; } = null!;
public static FrameworkManager Framework { get; private set; } = null!; public static FrameworkManager Framework { get; private set; } = null!;
public static int ImcExceptions = 0; public static readonly List< Exception > ImcExceptions = new();
public readonly ResourceLogger ResourceLogger; public readonly ResourceLogger ResourceLogger;
public readonly PathResolver PathResolver; public readonly PathResolver PathResolver;
@ -134,11 +132,10 @@ public class Penumbra : IDalamudPlugin
{ {
ResidentResources.Reload(); ResidentResources.Reload();
} }
Api = new PenumbraApi( this ); Api = new PenumbraApi( this );
IpcProviders = new PenumbraIpcProviders( Dalamud.PluginInterface, Api ); IpcProviders = new PenumbraIpcProviders( Dalamud.PluginInterface, Api );
SubscribeItemLinks(); SubscribeItemLinks();
if( ImcExceptions > 0 ) if( ImcExceptions.Count > 0 )
{ {
Log.Error( $"{ImcExceptions} IMC Exceptions thrown. Please repair your game files." ); Log.Error( $"{ImcExceptions} IMC Exceptions thrown. Please repair your game files." );
} }
@ -205,6 +202,7 @@ public class Penumbra : IDalamudPlugin
ResidentResources.Reload(); ResidentResources.Reload();
ObjectReloader.RedrawAll( RedrawType.Redraw ); ObjectReloader.RedrawAll( RedrawType.Redraw );
} }
EnabledChange?.Invoke( true ); EnabledChange?.Invoke( true );
return true; return true;
@ -227,6 +225,7 @@ public class Penumbra : IDalamudPlugin
ResidentResources.Reload(); ResidentResources.Reload();
ObjectReloader.RedrawAll( RedrawType.Redraw ); ObjectReloader.RedrawAll( RedrawType.Redraw );
} }
EnabledChange?.Invoke( false ); EnabledChange?.Invoke( false );
return true; return true;

View file

@ -3,6 +3,7 @@ using System.Numerics;
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Interface.Windowing; using Dalamud.Interface.Windowing;
using ImGuiNET; using ImGuiNET;
using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using Penumbra.UI.Classes; using Penumbra.UI.Classes;
@ -53,9 +54,9 @@ public sealed partial class ConfigWindow : Window, IDisposable
{ {
try try
{ {
if( Penumbra.ImcExceptions > 0 ) if( Penumbra.ImcExceptions.Count > 0 )
{ {
DrawProblemWindow( $"There were {Penumbra.ImcExceptions} errors while trying to load IMC files from the game data.\n" DrawProblemWindow( $"There were {Penumbra.ImcExceptions.Count} errors while trying to load IMC files from the game data.\n"
+ "This usually means that your game installation was corrupted by updating the game while having TexTools mods still active.\n" + "This usually means that your game installation was corrupted by updating the game while having TexTools mods still active.\n"
+ "It is recommended to not use TexTools and Penumbra (or other Lumina-based tools) at the same time.\n\n" + "It is recommended to not use TexTools and Penumbra (or other Lumina-based tools) at the same time.\n\n"
+ "Please use the Launcher's Repair Game Files function to repair your client installation." ); + "Please use the Launcher's Repair Game Files function to repair your client installation." );
@ -108,6 +109,18 @@ public sealed partial class ConfigWindow : Window, IDisposable
SettingsTab.DrawDiscordButton( 0 ); SettingsTab.DrawDiscordButton( 0 );
ImGui.SameLine(); ImGui.SameLine();
SettingsTab.DrawSupportButton(); SettingsTab.DrawSupportButton();
ImGui.NewLine();
ImGui.NewLine();
ImGui.TextUnformatted( "Exceptions" );
ImGui.Separator();
using var box = ImRaii.ListBox( "##Exceptions", new Vector2(-1, -1) );
foreach( var exception in Penumbra.ImcExceptions )
{
ImGuiUtil.TextWrapped( exception.ToString() );
ImGui.Separator();
ImGui.NewLine();
}
} }
public void Dispose() public void Dispose()