11using System ;
22using System . Collections . Generic ;
33using System . Diagnostics . CodeAnalysis ;
4- using OtterGui . Filesystem ;
4+ using System . Linq ;
55using Penumbra . Meta ;
66using Penumbra . Meta . Files ;
77using Penumbra . Meta . Manipulations ;
@@ -11,113 +11,117 @@ namespace Penumbra.Collections.Cache;
1111
1212public readonly struct ImcCache : IDisposable
1313{
14- private readonly Dictionary < Utf8GamePath , ImcFile > _imcFiles = new ( ) ;
15- private readonly List < ImcManipulation > _imcManipulations = new ( ) ;
14+ private readonly Dictionary < Utf8GamePath , ImcFile > _imcFiles = new ( ) ;
15+ private readonly List < ( ImcManipulation , ImcFile ) > _imcManipulations = new ( ) ;
1616
1717 public ImcCache ( )
18- { }
18+ { }
1919
2020 public void SetFiles ( ModCollection collection , bool fromFullCompute )
2121 {
2222 if ( fromFullCompute )
23- {
2423 foreach ( var path in _imcFiles . Keys )
2524 collection . _cache ! . ForceFileSync ( path , CreateImcPath ( collection , path ) ) ;
26- }
2725 else
28- {
2926 foreach ( var path in _imcFiles . Keys )
3027 collection . _cache ! . ForceFile ( path , CreateImcPath ( collection , path ) ) ;
31- }
3228 }
3329
3430 public void Reset ( ModCollection collection )
3531 {
36- foreach ( var ( path , file ) in _imcFiles )
32+ foreach ( var ( path , file ) in _imcFiles )
3733 {
38- collection . _cache ! . RemovePath ( path ) ;
34+ collection . _cache ! . RemovePath ( path ) ;
3935 file . Reset ( ) ;
4036 }
4137
4238 _imcManipulations . Clear ( ) ;
4339 }
4440
45- public bool ApplyMod ( MetaFileManager manager , ModCollection collection , ImcManipulation manip )
41+ public bool ApplyMod ( MetaFileManager manager , ModCollection collection , ImcManipulation manip )
4642 {
47- if ( ! manip . Validate ( ) )
48- {
43+ if ( ! manip . Validate ( ) )
4944 return false ;
50- }
5145
52- _imcManipulations . AddOrReplace ( manip ) ;
46+ var idx = _imcManipulations . FindIndex ( p => p . Item1 . Equals ( manip ) ) ;
47+ if ( idx < 0 )
48+ {
49+ idx = _imcManipulations . Count ;
50+ _imcManipulations . Add ( ( manip , null ! ) ) ;
51+ }
52+
5353 var path = manip . GamePath ( ) ;
5454 try
5555 {
56- if ( ! _imcFiles . TryGetValue ( path , out var file ) )
57- {
58- file = new ImcFile ( manager , manip ) ;
59- }
56+ if ( ! _imcFiles . TryGetValue ( path , out var file ) )
57+ file = new ImcFile ( manager , manip ) ;
6058
61- if ( ! manip . Apply ( file ) )
62- {
59+ _imcManipulations [ idx ] = ( manip , file ) ;
60+ if ( ! manip . Apply ( file ) )
6361 return false ;
64- }
6562
66- _imcFiles [ path ] = file ;
67- var fullPath = CreateImcPath ( collection , path ) ;
68- collection . _cache ! . ForceFile ( path , fullPath ) ;
63+ _imcFiles [ path ] = file ;
64+ var fullPath = CreateImcPath ( collection , path ) ;
65+ collection . _cache ! . ForceFile ( path , fullPath ) ;
6966
7067 return true ;
7168 }
72- catch ( ImcException e )
69+ catch ( ImcException e )
7370 {
74- manager . ValidityChecker . ImcExceptions . Add ( e ) ;
75- Penumbra . Log . Error ( e . ToString ( ) ) ;
71+ manager . ValidityChecker . ImcExceptions . Add ( e ) ;
72+ Penumbra . Log . Error ( e . ToString ( ) ) ;
7673 }
77- catch ( Exception e )
74+ catch ( Exception e )
7875 {
79- Penumbra . Log . Error ( $ "Could not apply IMC Manipulation { manip } :\n { e } " ) ;
76+ Penumbra . Log . Error ( $ "Could not apply IMC Manipulation { manip } :\n { e } ") ;
8077 }
8178
8279 return false ;
8380 }
8481
85- public bool RevertMod ( MetaFileManager manager , ModCollection collection , ImcManipulation m )
82+ public bool RevertMod ( MetaFileManager manager , ModCollection collection , ImcManipulation m )
8683 {
87- if ( ! m . Validate ( ) || ! _imcManipulations . Remove ( m ) )
88- {
84+ if ( ! m . Validate ( ) )
85+ return false ;
86+
87+ var idx = _imcManipulations . FindIndex ( p => p . Item1 . Equals ( m ) ) ;
88+ if ( idx < 0 )
8989 return false ;
90- }
9190
92- var path = m . GamePath ( ) ;
93- if ( ! _imcFiles . TryGetValue ( path , out var file ) )
94- {
95- return false ;
96- }
91+ var ( _, file ) = _imcManipulations [ idx ] ;
92+ _imcManipulations . RemoveAt ( idx ) ;
9793
98- var def = ImcFile . GetDefault ( manager , path , m . EquipSlot , m . Variant , out _ ) ;
99- var manip = m . Copy ( def ) ;
100- if ( ! manip . Apply ( file ) )
94+ if ( _imcManipulations . All ( p => ! ReferenceEquals ( p . Item2 , file ) ) )
95+ {
96+ _imcFiles . Remove ( file . Path ) ;
97+ collection . _cache ! . ForceFile ( file . Path , FullPath . Empty ) ;
98+ file . Dispose ( ) ;
99+ return true ;
100+ }
101+
102+ var def = ImcFile . GetDefault ( manager , file . Path , m . EquipSlot , m . Variant , out _ ) ;
103+ var manip = m . Copy ( def ) ;
104+ if ( ! manip . Apply ( file ) )
101105 return false ;
102106
103- var fullPath = CreateImcPath ( collection , path ) ;
104- collection . _cache ! . ForceFile ( path , fullPath ) ;
107+ var fullPath = CreateImcPath ( collection , file . Path ) ;
108+ collection . _cache ! . ForceFile ( file . Path , fullPath ) ;
105109
106110 return true ;
107111 }
108112
109113 public void Dispose ( )
110114 {
111- foreach ( var file in _imcFiles . Values )
115+ foreach ( var file in _imcFiles . Values )
112116 file . Dispose ( ) ;
113117
114118 _imcFiles . Clear ( ) ;
115119 _imcManipulations . Clear ( ) ;
116120 }
117121
118- private static FullPath CreateImcPath ( ModCollection collection , Utf8GamePath path )
122+ private static FullPath CreateImcPath ( ModCollection collection , Utf8GamePath path )
119123 => new ( $ "|{ collection . Name } _{ collection . ChangeCounter } |{ path } ") ;
120124
121125 public bool GetImcFile ( Utf8GamePath path , [ NotNullWhen ( true ) ] out ImcFile ? file )
122126 => _imcFiles . TryGetValue ( path , out file ) ;
123- }
127+ }
0 commit comments