@@ -105,10 +105,38 @@ public void AddEnumFile(string filePath)
105105 }
106106 }
107107
108+ /// <summary>
109+ /// Tries to get all files that the base flow imports
110+ /// </summary>
111+ /// <param name="flowFormat">The format of the flowscript</param>
112+ /// <param name="library">The library to use for the flowscript</param>
113+ /// <param name="encoding">The encoding of the flowscript</param>
114+ /// <param name="foundImports">An array of absolute paths to all files that the base flows import,
115+ /// both directly and transitively. This includes the base files.</param>
116+ /// <returns></returns>
117+ public bool TryGetImports ( FlowFormatVersion flowFormat , Library library , Encoding encoding ,
118+ out string [ ] foundImports )
119+ {
120+ // Use compiler arg overrides (if they're there)
121+ if ( _library != null ) library = _library ;
122+ if ( _encoding != null ) encoding = _encoding ;
123+ if ( _flowFormat != null ) flowFormat = ( FlowFormatVersion ) _flowFormat ;
124+
125+ var compiler = new FlowScriptCompiler ( flowFormat ) ;
126+ compiler . Library = OverrideLibraries ( library ) ;
127+ compiler . Encoding = encoding ;
128+
129+ var imports = new List < string > ( ) ;
130+ imports . AddRange ( _flowFiles ) ;
131+ imports . AddRange ( _msgFiles ) ;
132+
133+ return compiler . TryGetImports ( imports , out foundImports ) ;
134+ }
135+
108136 /// <summary>
109137 /// Builds a BF file.
110138 /// </summary>
111- public unsafe Stream ? Build ( IntPtr originalHandle , string originalPath , FlowFormatVersion flowFormat , Library library , Encoding encoding , AtlusLogListener ? listener = null , bool noBaseBf = false )
139+ public EmulatedBf ? Build ( IntPtr originalHandle , string originalPath , FlowFormatVersion flowFormat , Library library , Encoding encoding , AtlusLogListener ? listener = null , bool noBaseBf = false )
112140 {
113141 _log ? . Info ( "[BfEmulator] Building BF File | {0}" , originalPath ) ;
114142
@@ -135,21 +163,43 @@ public void AddEnumFile(string filePath)
135163 imports . AddRange ( _flowFiles . GetRange ( 1 , _flowFiles . Count - 1 ) ) ;
136164 imports . AddRange ( _msgFiles ) ;
137165
138- if ( ! compiler . TryCompileWithImports ( bfStream , imports , baseFlow , out FlowScript flowScript ) )
166+ try
139167 {
140- _log ? . Error ( "[BfEmulator] Failed to compile BF File | {0}" , originalPath ) ;
141- return null ;
142- }
168+ if ( ! compiler . TryCompileWithImports ( bfStream , imports , baseFlow , out FlowScript flowScript ,
169+ out var sources ) )
170+ {
171+ _log ? . Error ( "[BfEmulator] Failed to compile BF File | {0}" , originalPath ) ;
172+ return null ;
173+ }
143174
144- // Return the compiled bf
145- var bfBinary = flowScript . ToBinary ( ) ;
146- var stream = StreamUtils . CreateMemoryStream ( bfBinary . Header . FileSize ) ;
147- bfBinary . ToStream ( stream , true ) ;
148- stream . Position = 0 ;
175+ // Return the compiled bf
176+ var bfBinary = flowScript . ToBinary ( ) ;
177+ var stream = StreamUtils . CreateMemoryStream ( bfBinary . Header . FileSize ) ;
178+ bfBinary . ToStream ( stream , true ) ;
179+ stream . Position = 0 ;
149180
150- return stream ;
181+ DateTime lastWrite = sources . Where ( x => x != null ) . Select ( Fiel . GetLastWriteTimeUtc ) . Max ( ) ;
182+ return new EmulatedBf ( stream , sources , lastWrite ) ;
183+ }
184+ catch ( Exception exception )
185+ {
186+ var flows = string . Join ( ", " , _flowFiles . Concat ( _msgFiles ) ) ;
187+ _log . Error (
188+ "[BF Builder] Failed to compile bf {0} with source files: {1}. This may be due to your mods not being translated. Error: {2}" ,
189+ originalPath , flows , exception . Message ) ;
190+ if ( exception . StackTrace != null )
191+ _log . Error ( exception . StackTrace ) ;
192+ return null ;
193+ }
151194 }
152195
196+ /// <summary>
197+ /// Applies library file overrides to the base library.
198+ /// This adds aliases to functions with different names, replaces functions with different
199+ /// return values or parameters, and adds any completely new functions.
200+ /// </summary>
201+ /// <param name="library">The base library to override</param>
202+ /// <returns>A deep copy of the base library with overrides applied</returns>
153203 private Library OverrideLibraries ( Library library )
154204 {
155205 if ( _libraryEnums . Count == 0 && _libraryFuncs . Count == 0 ) return library ;
@@ -176,7 +226,15 @@ private Library OverrideLibraries(Library library)
176226
177227 if ( module != - 1 && index != - 1 )
178228 {
179- library . FlowScriptModules [ module ] . Functions [ index ] = func ;
229+ var existingFunc = library . FlowScriptModules [ module ] . Functions [ index ] ;
230+ if ( FlowFunctionsSame ( existingFunc , func ) )
231+ {
232+ existingFunc . Aliases . Add ( func . Name ) ;
233+ }
234+ else
235+ {
236+ library . FlowScriptModules [ module ] . Functions [ index ] = func ;
237+ }
180238 }
181239 else
182240 {
@@ -188,4 +246,17 @@ private Library OverrideLibraries(Library library)
188246 library . FlowScriptModules [ 0 ] . Enums . AddRange ( _libraryEnums ) ;
189247 return library ;
190248 }
191- }
249+
250+ /// <summary>
251+ /// Checks if two flowscript functions are effectively the same.
252+ /// They are the same if the return type and parameter types are the same.
253+ /// </summary>
254+ /// <param name="func1">The first function to compare</param>
255+ /// <param name="func2">The other function to compare</param>
256+ /// <returns>Truee if the two functions are effectively the same, false otherwise</returns>
257+ private bool FlowFunctionsSame ( FlowScriptModuleFunction func1 , FlowScriptModuleFunction func2 )
258+ {
259+ return func1 . ReturnType == func2 . ReturnType && func1 . Parameters . Select ( param => param . Type )
260+ . SequenceEqual ( func2 . Parameters . Select ( param => param . Type ) ) ;
261+ }
262+ }
0 commit comments