1
1
using System ;
2
+ using System . Collections . Generic ;
2
3
using System . IO ;
3
4
using System . IO . Compression ;
5
+ using CommandLine ;
4
6
using LibBSP ;
5
7
6
8
namespace BSPPak
7
9
{
8
- internal class Program
10
+ public class Program
9
11
{
10
- private static void Main ( string [ ] args )
11
- {
12
- // TODO: use a proper parameter parsing plugin
13
- if ( args . Length < 2 || args . Length > 3 )
14
- {
15
- Console . WriteLine ( "Usage: BSPPak \" C:/Path/To/Map.bsp\" \" C:/Path/To/Content/Folder\" " ) ;
16
- Console . WriteLine ( "Usage: BSPPak -d \" C:/Path/To/Map.bsp\" \" C:/Path/To/Content/Folder\" " ) ;
17
- Console . WriteLine (
18
- "The content folder can contain a file named \" .pakfilter\" which contains .gitignore-like syntax for matching which files to pack. " +
19
- "Remember that the .pakfilter file matches inversely to a regular .gitignore, .gitignore acts as a blacklist while .pakfilter acts as a whitelist." ) ;
20
- Console . WriteLine ( "Use the -d flag to mark it as a dry run where the bsp will not get edited." ) ;
21
- return ;
22
- }
23
-
24
- bool isDryRun ;
25
- string bspPath ;
26
- string contentPath ;
27
- if ( args . Length == 2 )
28
- {
29
- isDryRun = false ;
30
- bspPath = args [ 0 ] ;
31
- contentPath = args [ 1 ] ;
32
- }
33
- else
34
- {
35
- isDryRun = true ;
36
- bspPath = args [ 1 ] ;
37
- contentPath = args [ 2 ] ;
38
- }
39
-
40
- var files = FileFinder . Find ( contentPath ) ;
41
-
42
- if ( isDryRun )
43
- {
44
- foreach ( var item in files )
45
- Console . WriteLine ( ToRelativePath ( item , contentPath ) ) ;
46
- Console . WriteLine ( $ "Found { files . Count } files matching the filter.") ;
47
- Console . WriteLine ( "Finished, dry run" ) ;
48
- return ;
49
- }
50
-
51
- if ( files . Count == 0 )
52
- {
53
- Console . WriteLine ( "No files found that matches the filter. Exiting." ) ;
54
- return ;
55
- }
12
+ public const int ExitFail = 1 ;
56
13
14
+ public static void PackFiles ( Options opts , IReadOnlyCollection < string > files )
15
+ {
57
16
Console . WriteLine ( $ "Found { files . Count } files matching the filter.") ;
58
17
59
- if ( ! File . Exists ( bspPath ) )
60
- {
61
- Console . WriteLine ( "Invalid bsp specified" ) ;
62
- return ;
63
- }
18
+ Console . WriteLine ( $ "Reading from { Path . GetFileName ( opts . BSPPath ) } ") ;
19
+ var bsp = new BSP ( opts . BSPPath ) ;
64
20
65
- Console . WriteLine ( "Reading and parsing BSP" ) ;
66
- var bsp = new BSP ( bspPath ) ;
67
-
68
- var pakLump = ( PakfileLump ) bsp . Lumps [ 40 ] ;
21
+ var pakLump = ( PakfileLump ) bsp . Lumps [ ( int ) LumpType . Pakfile ] ;
69
22
var archive = pakLump . OpenArchiveStream ( ZipArchiveMode . Update ) ;
70
23
71
24
var i = 0 ;
@@ -74,7 +27,7 @@ private static void Main(string[] args)
74
27
if ( i % 50 == 0 )
75
28
Console . WriteLine ( $ "{ i } /{ files . Count } Zipping files...") ;
76
29
77
- var relPath = ToRelativePath ( file , contentPath ) ;
30
+ var relPath = ToRelativePath ( file , opts . ContentPath ) ;
78
31
var entry = archive . GetEntry ( relPath ) ;
79
32
if ( entry != null )
80
33
Console . WriteLine ( $ "{ relPath } already packed, overwriting...") ;
@@ -90,18 +43,73 @@ private static void Main(string[] args)
90
43
91
44
pakLump . CloseArchiveStream ( ) ;
92
45
93
- Console . WriteLine ( "Writing BSP " ) ;
94
- bsp . WriteBSP ( bspPath ) ;
46
+ Console . WriteLine ( $ "Writing to { Path . GetFileName ( opts . BSPPath ) } ") ;
47
+ bsp . WriteBSP ( opts . BSPPath ) ;
95
48
96
49
Console . WriteLine ( "Done!" ) ;
97
50
}
98
51
99
- private static string ToRelativePath ( string fullPath , string relDir )
52
+ public static void PrintFiles ( Options opts , IReadOnlyCollection < string > files )
53
+ {
54
+ foreach ( var item in files )
55
+ Console . WriteLine ( ToRelativePath ( item , opts . ContentPath ) ) ;
56
+ Console . WriteLine ( $ "Found { files . Count } files matching the filter.") ;
57
+ }
58
+
59
+ public static void ValidateOptions ( Options opts )
60
+ {
61
+ if ( ! File . Exists ( opts . BSPPath ) )
62
+ throw new InvalidOptionException ( "Invalid .bsp file specified." ) ;
63
+
64
+ if ( ! Directory . Exists ( opts . ContentPath ) )
65
+ throw new InvalidOptionException ( "Invalid content folder specified." ) ;
66
+ }
67
+
68
+ private static void Main ( string [ ] args )
69
+ {
70
+ Parser . Default . ParseArguments < Options > ( args )
71
+ . WithParsed ( opts =>
72
+ {
73
+ try
74
+ {
75
+ ValidateOptions ( opts ) ;
76
+ }
77
+ catch ( InvalidOptionException e )
78
+ {
79
+ Console . WriteLine ( e . Message ) ;
80
+ Environment . ExitCode = ExitFail ;
81
+ return ;
82
+ }
83
+
84
+ var files = FileFinder . Find ( opts . ContentPath ) ;
85
+
86
+ if ( opts . DryRun )
87
+ PrintFiles ( opts , files ) ;
88
+ else
89
+ PackFiles ( opts , files ) ;
90
+ } ) ;
91
+ }
92
+
93
+ public static string ToRelativePath ( string fullPath , string relDir )
100
94
{
101
95
if ( ! fullPath . StartsWith ( relDir ) )
102
96
throw new ArgumentException ( "relDir is not a parent directory to fullPath!" ) ;
103
97
104
98
return fullPath . Substring ( relDir . Length ) . TrimStart ( '/' , '\\ ' ) ;
105
99
}
100
+
101
+ public class Options
102
+ {
103
+ [ Option ( 'd' , "dry-run" , Required = false ,
104
+ HelpText =
105
+ "Only output a list of files found in the content folder that passes the filter. The BSP file won't be edited." ) ]
106
+ public bool DryRun { get ; set ; }
107
+
108
+ [ Value ( 0 , MetaName = "BSP file" , HelpText = "The .bsp file to process." , Required = true ) ]
109
+ public string BSPPath { get ; set ; }
110
+
111
+ [ Value ( 1 , MetaName = "Content path" , HelpText = "The path to the content folder." , Required = true ) ]
112
+ public string ContentPath { get ; set ; }
113
+ }
106
114
}
107
115
}
0 commit comments