2019-10-30 12:29:06 +00:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
2019-12-04 01:26:26 +00:00
using System.Threading.Tasks ;
2019-10-30 12:29:06 +00:00
using Wabbajack.Common ;
2021-09-27 12:42:46 +00:00
using Wabbajack.Compression.BSA ;
using Wabbajack.DTOs ;
using Wabbajack.DTOs.BSA.ArchiveStates ;
using Wabbajack.DTOs.Directives ;
using Wabbajack.Paths ;
using Wabbajack.Paths.IO ;
using Wabbajack.VFS ;
namespace Wabbajack.Compiler.CompilationSteps
2019-10-30 12:29:06 +00:00
{
2019-10-31 02:24:42 +00:00
public class DeconstructBSAs : ACompilationStep
2019-10-30 12:29:06 +00:00
{
2020-04-27 21:32:19 +00:00
private readonly IEnumerable < RelativePath > _includeDirectly ;
2020-02-05 05:17:12 +00:00
private readonly Func < VirtualFile , List < ICompilationStep > > _microstack ;
private readonly Func < VirtualFile , List < ICompilationStep > > _microstackWithInclude ;
2019-11-18 00:17:06 +00:00
private readonly MO2Compiler _mo2Compiler ;
2019-10-30 12:29:06 +00:00
2019-11-03 16:45:49 +00:00
public DeconstructBSAs ( ACompiler compiler ) : base ( compiler )
2019-10-30 12:29:06 +00:00
{
2020-06-26 19:01:10 +00:00
_mo2Compiler = ( MO2Compiler ) compiler ;
2019-11-21 15:51:57 +00:00
_includeDirectly = _mo2Compiler . ModInis . Where ( kv = >
2019-10-30 12:29:06 +00:00
{
2021-09-27 12:42:46 +00:00
var general = kv . Value [ "General" ] ;
if ( general [ "notes" ] ! = null & & ( general [ "notes" ] . Contains ( Consts . WABBAJACK_INCLUDE ) | | general [ "notes" ] . Contains ( Consts . WABBAJACK_NOMATCH_INCLUDE ) ) ) return true ;
if ( general [ "comments" ] ! = null & & ( general [ "comments" ] . Contains ( Consts . WABBAJACK_INCLUDE ) | | general [ "comments" ] . Contains ( Consts . WABBAJACK_NOMATCH_INCLUDE ) ) ) return true ;
2019-10-30 12:29:06 +00:00
return false ;
} )
2021-09-27 12:42:46 +00:00
. Select ( kv = > kv . Key . RelativeTo ( _mo2Compiler . _settings . Source ) )
2019-10-30 12:29:06 +00:00
. ToList ( ) ;
2020-02-05 05:17:12 +00:00
_microstack = bsa = > new List < ICompilationStep >
2019-10-30 12:29:06 +00:00
{
2019-11-11 20:03:27 +00:00
new DirectMatch ( _mo2Compiler ) ,
2021-07-17 05:32:37 +00:00
new MatchSimilarTextures ( _mo2Compiler ) ,
2020-02-05 05:17:12 +00:00
new IncludePatches ( _mo2Compiler , bsa ) ,
2019-11-11 20:03:27 +00:00
new DropAll ( _mo2Compiler )
2019-10-30 12:29:06 +00:00
} ;
2020-02-05 05:17:12 +00:00
_microstackWithInclude = bsa = > new List < ICompilationStep >
2019-10-30 12:29:06 +00:00
{
2019-11-11 20:03:27 +00:00
new DirectMatch ( _mo2Compiler ) ,
2021-07-17 05:32:37 +00:00
new MatchSimilarTextures ( _mo2Compiler ) ,
2020-02-05 05:17:12 +00:00
new IncludePatches ( _mo2Compiler , bsa ) ,
2019-11-11 20:03:27 +00:00
new IncludeAll ( _mo2Compiler )
2019-10-30 12:29:06 +00:00
} ;
2019-10-31 02:24:42 +00:00
}
2019-10-30 12:29:06 +00:00
2020-04-09 18:14:05 +00:00
public override async ValueTask < Directive ? > Run ( RawSourceFile source )
2019-10-30 12:29:06 +00:00
{
2020-03-25 22:30:43 +00:00
if ( ! Consts . SupportedBSAs . Contains ( source . Path . Extension ) ) return null ;
2019-10-30 12:29:06 +00:00
var defaultInclude = false ;
2021-09-27 12:42:46 +00:00
if ( source . Path . RelativeTo ( _mo2Compiler . _settings . Source ) . InFolder ( _mo2Compiler . _settings . Source . Combine ( Consts . MO2ModFolderName ) ) )
if ( _includeDirectly . Any ( path = > source . Path . InFolder ( path ) ) )
2019-10-30 12:29:06 +00:00
defaultInclude = true ;
2021-09-27 12:42:46 +00:00
if ( source . AbsolutePath . Size ( ) > = ( long ) 2 < < 31 )
2020-04-20 21:36:33 +00:00
{
2021-09-27 12:42:46 +00:00
var bsaTest = await BSADispatch . Open ( source . AbsolutePath ) ;
if ( bsaTest . State is BSAState )
2020-04-20 21:36:33 +00:00
{
2021-09-27 12:42:46 +00:00
throw new CompilerException (
2020-04-20 21:36:33 +00:00
$"BSA {source.AbsolutePath.FileName} is over 2GB in size, very few programs (Including Wabbajack) can create BSA files this large without causing CTD issues." +
$"Please re-compress this BSA into a more manageable size." ) ;
}
}
2019-11-21 15:51:57 +00:00
var sourceFiles = source . File . Children ;
2019-10-30 12:29:06 +00:00
2020-02-05 05:17:12 +00:00
var stack = defaultInclude ? _microstackWithInclude ( source . File ) : _microstack ( source . File ) ;
2019-10-30 12:29:06 +00:00
var id = Guid . NewGuid ( ) . ToString ( ) ;
2020-04-27 21:32:19 +00:00
Func < Task > ? _cleanup = null ;
if ( defaultInclude )
{
2020-09-05 19:36:44 +00:00
//_cleanup = await source.File.Context.Stage(source.File.Children);
2020-04-27 21:32:19 +00:00
}
2020-06-26 19:01:10 +00:00
2021-10-21 03:18:15 +00:00
var matches = await sourceFiles . PMapAll ( _compiler . CompilerLimiter , e = > _mo2Compiler . RunStack ( stack , new RawSourceFile ( e , Consts . BSACreationDir . Combine ( ( RelativePath ) id , ( RelativePath ) e . Name ) ) ) )
2021-09-27 12:42:46 +00:00
. ToList ( ) ;
2019-10-30 12:29:06 +00:00
foreach ( var match in matches )
{
2019-10-31 02:24:42 +00:00
if ( match is IgnoredDirectly )
2021-09-27 12:42:46 +00:00
{
throw new CompilerException ( $"File required for BSA {source.Path} creation doesn't exist: {match.To}" ) ;
}
2019-11-11 20:03:27 +00:00
_mo2Compiler . ExtraFiles . Add ( match ) ;
2019-10-30 12:29:06 +00:00
}
2019-10-31 02:24:42 +00:00
2021-09-27 12:42:46 +00:00
var bsa = await BSADispatch . Open ( source . AbsolutePath ) ;
var directive = new CreateBSA
2019-10-30 12:29:06 +00:00
{
2021-09-27 12:42:46 +00:00
State = bsa . State ,
FileStates = bsa . Files . Select ( f = > f . State ) . ToArray ( ) ,
2020-06-26 19:01:10 +00:00
To = source . Path ,
2021-09-27 12:42:46 +00:00
Hash = source . Hash ,
2020-06-26 19:01:10 +00:00
TempID = ( RelativePath ) id ,
} ;
2019-10-30 12:29:06 +00:00
2020-04-27 21:32:19 +00:00
if ( _cleanup ! = null )
await _cleanup ( ) ;
2019-10-30 12:29:06 +00:00
return directive ;
}
}
2019-12-04 04:12:08 +00:00
}