@@ -30,17 +30,33 @@ public bool Read(AssetsFileReader reader, bool allowCompressed = false)
30
30
this . reader = reader ;
31
31
reader . ReadNullTerminated ( ) ;
32
32
uint version = reader . ReadUInt32 ( ) ;
33
- if ( version == 6 || version == 7 )
33
+ switch ( version )
34
34
{
35
- reader . Position = 0 ;
36
- bundleHeader6 = new AssetBundleHeader06 ( ) ;
37
- bundleHeader6 . Read ( reader ) ;
38
- if ( bundleHeader6 . fileVersion >= 7 )
39
- {
40
- reader . Align16 ( ) ;
41
- }
42
- if ( bundleHeader6 . signature == "UnityFS" )
43
- {
35
+ case 3 :
36
+ reader . Position = 0 ;
37
+ bundleHeader3 = new AssetBundleHeader03 ( ) ;
38
+ bundleHeader3 . Read ( reader ) ;
39
+ if ( bundleHeader3 . signature != "UnityRaw" )
40
+ throw new NotImplementedException ( "Non UnityRaw bundles are not supported yet." ) ;
41
+
42
+ if ( bundleHeader3 . blockList . Any ( b => b . compressed != b . uncompressed ) )
43
+ throw new NotImplementedException ( "Compressed UnityRaw bundles are not supported yet." ) ;
44
+
45
+ assetsLists3 = new AssetsList ( ) ;
46
+ assetsLists3 . Read ( reader ) ;
47
+ return true ;
48
+
49
+ case 6 :
50
+ case 7 :
51
+ reader . Position = 0 ;
52
+ bundleHeader6 = new AssetBundleHeader06 ( ) ;
53
+ bundleHeader6 . Read ( reader ) ;
54
+ if ( bundleHeader6 . fileVersion >= 7 )
55
+ reader . Align16 ( ) ;
56
+
57
+ if ( bundleHeader6 . signature != "UnityFS" )
58
+ throw new NotImplementedException ( "Non UnityFS bundles are not supported yet." ) ;
59
+
44
60
bundleInf6 = new AssetBundleBlockAndDirectoryList06 ( ) ;
45
61
if ( ( bundleHeader6 . flags & 0x3F ) != 0 )
46
62
{
@@ -59,23 +75,103 @@ public bool Read(AssetsFileReader reader, bool allowCompressed = false)
59
75
bundleInf6 . Read ( bundleHeader6 . GetBundleInfoOffset ( ) , reader ) ;
60
76
return true ;
61
77
}
62
- }
63
- else
78
+
79
+ default :
80
+ throw new Exception ( "AssetsBundleFile.Read : Unknown file version!" ) ;
81
+ }
82
+ }
83
+
84
+ public bool Write ( AssetsFileWriter writer , List < BundleReplacer > replacers , ClassDatabaseFile typeMeta = null )
85
+ {
86
+ if ( bundleHeader3 != null )
87
+ return Write03 ( writer , replacers ) ;
88
+
89
+ if ( bundleHeader6 != null )
90
+ return Write06 ( writer , replacers ) ;
91
+
92
+ return false ;
93
+ }
94
+
95
+ private bool Write03 ( AssetsFileWriter writer , List < BundleReplacer > replacers )
96
+ {
97
+ AssetBundleHeader03 newBundleHeader3 = bundleHeader3 . Clone ( ) ;
98
+ newBundleHeader3 . blockList = new [ ] { new AssetsBundleOffsetPair ( ) } ;
99
+ newBundleHeader3 . Write ( writer ) ;
100
+
101
+ newBundleHeader3 . bundleDataOffs = ( uint ) writer . Position ;
102
+
103
+ Dictionary < string , BundleReplacer > addingReplacers =
104
+ replacers . Where ( r => r . GetReplacementType ( ) == BundleReplacementType . AddOrModify )
105
+ . ToDictionary ( r => r . GetOriginalEntryName ( ) ) ;
106
+
107
+ List < AssetsBundleEntry > newEntries = new List < AssetsBundleEntry > ( ) ;
108
+ Dictionary < AssetsBundleEntry , AssetsBundleEntry > newEntryToOldEntry = new Dictionary < AssetsBundleEntry , AssetsBundleEntry > ( ) ;
109
+ Dictionary < AssetsBundleEntry , BundleReplacer > newEntryToReplacer = new Dictionary < AssetsBundleEntry , BundleReplacer > ( ) ;
110
+ foreach ( AssetsBundleEntry entry in assetsLists3 . entries )
111
+ {
112
+ addingReplacers . Remove ( entry . name ) ;
113
+
114
+ BundleReplacer replacer = replacers . FirstOrDefault ( r => r . GetOriginalEntryName ( ) == entry . name ) ;
115
+ if ( replacer == null ||
116
+ replacer . GetReplacementType ( ) == BundleReplacementType . AddOrModify ||
117
+ replacer . GetReplacementType ( ) == BundleReplacementType . Rename )
64
118
{
65
- new NotImplementedException ( "Non UnityFS bundles are not supported yet." ) ;
119
+ AssetsBundleEntry newEntry = new AssetsBundleEntry { name = replacer ? . GetEntryName ( ) ?? entry . name } ;
120
+ newEntries . Add ( newEntry ) ;
121
+ newEntryToOldEntry . Add ( newEntry , entry ) ;
122
+ if ( replacer != null && replacer . GetReplacementType ( ) == BundleReplacementType . AddOrModify )
123
+ newEntryToReplacer . Add ( newEntry , replacer ) ;
66
124
}
67
125
}
68
- else if ( version == 3 )
126
+
127
+ foreach ( BundleReplacer replacer in addingReplacers . Values )
69
128
{
70
- new NotImplementedException ( "Version 3 bundles are not supported yet." ) ;
129
+ AssetsBundleEntry newEntry = new AssetsBundleEntry { name = replacer . GetEntryName ( ) } ;
130
+ newEntries . Add ( newEntry ) ;
131
+ newEntryToReplacer . Add ( newEntry , replacer ) ;
71
132
}
72
- else
133
+
134
+ bundleHeader3 . numberOfAssetsToDownload = ( uint ) newEntries . Count ;
135
+
136
+ AssetsList newAssetsList = new AssetsList { entries = newEntries . ToArray ( ) } ;
137
+ newAssetsList . Write ( writer ) ;
138
+ writer . Align16 ( ) ;
139
+
140
+ bundleHeader3 . assetsListSize = ( uint ) writer . Position - bundleHeader3 . bundleDataOffs ;
141
+
142
+ foreach ( AssetsBundleEntry newEntry in newEntries )
73
143
{
74
- new Exception ( "AssetsBundleFile.Read : Unknown file version!" ) ;
144
+ long newEntryPosition = writer . Position ;
145
+ newEntry . offset = ( uint ) ( writer . Position - bundleHeader3 . bundleDataOffs ) ;
146
+
147
+ if ( newEntryToReplacer . TryGetValue ( newEntry , out BundleReplacer replacer ) )
148
+ {
149
+ replacer . Write ( writer ) ;
150
+ }
151
+ else
152
+ {
153
+ AssetsBundleEntry oldEntry = newEntryToOldEntry [ newEntry ] ;
154
+ reader . Position = bundleHeader3 . bundleDataOffs + oldEntry . offset ;
155
+ reader . BaseStream . CopyToCompat ( writer . BaseStream , oldEntry . length ) ;
156
+ }
157
+
158
+ newEntry . length = ( uint ) ( writer . Position - newEntryPosition ) ;
75
159
}
76
- return false ;
160
+
161
+ newBundleHeader3 . minimumStreamedBytes = ( uint ) writer . Position ;
162
+ newBundleHeader3 . blockList [ 0 ] . compressed = ( uint ) writer . Position - newBundleHeader3 . bundleDataOffs ;
163
+ newBundleHeader3 . blockList [ 0 ] . uncompressed = ( uint ) writer . Position - newBundleHeader3 . bundleDataOffs ;
164
+ newBundleHeader3 . fileSize2 = ( uint ) writer . Position ;
165
+
166
+ writer . Position = 0 ;
167
+ newBundleHeader3 . Write ( writer ) ;
168
+ newAssetsList . Write ( writer ) ;
169
+
170
+ writer . Position = newBundleHeader3 . fileSize2 ;
171
+ return true ;
77
172
}
78
- public bool Write ( AssetsFileWriter writer , List < BundleReplacer > replacers , ClassDatabaseFile typeMeta = null )
173
+
174
+ private bool Write06 ( AssetsFileWriter writer , List < BundleReplacer > replacers )
79
175
{
80
176
bundleHeader6 . Write ( writer ) ;
81
177
@@ -84,15 +180,15 @@ public bool Write(AssetsFileWriter writer, List<BundleReplacer> replacers, Class
84
180
writer . Align16 ( ) ;
85
181
}
86
182
87
- AssetBundleBlockAndDirectoryList06 newBundleInf6 = new AssetBundleBlockAndDirectoryList06 ( )
183
+ AssetBundleBlockAndDirectoryList06 newBundleInf6 = new AssetBundleBlockAndDirectoryList06
88
184
{
89
185
checksumLow = 0 ,
90
186
checksumHigh = 0
91
187
} ;
92
188
//I could map the assets to their blocks but I don't
93
189
//have any more-than-1-block files to test on
94
190
//this should work just fine as far as I know
95
- newBundleInf6 . blockInf = new AssetBundleBlockInfo06 [ ]
191
+ newBundleInf6 . blockInf = new [ ]
96
192
{
97
193
new AssetBundleBlockInfo06
98
194
{
@@ -108,19 +204,14 @@ public bool Write(AssetsFileWriter writer, List<BundleReplacer> replacers, Class
108
204
List < AssetBundleDirectoryInfo06 > originalDirInfos = new List < AssetBundleDirectoryInfo06 > ( ) ;
109
205
List < AssetBundleDirectoryInfo06 > dirInfos = new List < AssetBundleDirectoryInfo06 > ( ) ;
110
206
List < BundleReplacer > currentReplacers = replacers . ToList ( ) ;
111
- //this is kind of useless at the moment but leaving it here
112
- //because if the AssetsFile size can be precalculated in the
113
- //future, we can use this to skip rewriting sizes
114
- long currentOffset = 0 ;
115
207
116
208
//write all original files, modify sizes if needed and skip those to be removed
117
209
for ( int i = 0 ; i < bundleInf6 . directoryCount ; i ++ )
118
210
{
119
211
AssetBundleDirectoryInfo06 info = bundleInf6 . dirInf [ i ] ;
120
212
originalDirInfos . Add ( info ) ;
121
- AssetBundleDirectoryInfo06 newInfo = new AssetBundleDirectoryInfo06 ( )
213
+ AssetBundleDirectoryInfo06 newInfo = new AssetBundleDirectoryInfo06
122
214
{
123
- offset = currentOffset ,
124
215
decompressedSize = info . decompressedSize ,
125
216
flags = info . flags ,
126
217
name = info . name
@@ -131,19 +222,16 @@ public bool Write(AssetsFileWriter writer, List<BundleReplacer> replacers, Class
131
222
currentReplacers . Remove ( replacer ) ;
132
223
if ( replacer . GetReplacementType ( ) == BundleReplacementType . AddOrModify )
133
224
{
134
- newInfo = new AssetBundleDirectoryInfo06 ( )
225
+ newInfo = new AssetBundleDirectoryInfo06
135
226
{
136
- offset = currentOffset ,
137
- decompressedSize = replacer . GetSize ( ) ,
138
227
flags = info . flags ,
139
228
name = replacer . GetEntryName ( )
140
229
} ;
141
230
}
142
231
else if ( replacer . GetReplacementType ( ) == BundleReplacementType . Rename )
143
232
{
144
- newInfo = new AssetBundleDirectoryInfo06 ( )
233
+ newInfo = new AssetBundleDirectoryInfo06
145
234
{
146
- offset = currentOffset ,
147
235
decompressedSize = info . decompressedSize ,
148
236
flags = info . flags ,
149
237
name = replacer . GetEntryName ( )
@@ -160,11 +248,6 @@ public bool Write(AssetsFileWriter writer, List<BundleReplacer> replacers, Class
160
248
newToOriginalDirInfoLookup [ newInfo ] = info ;
161
249
}
162
250
163
- if ( newInfo . decompressedSize != - 1 )
164
- {
165
- currentOffset += newInfo . decompressedSize ;
166
- }
167
-
168
251
dirInfos . Add ( newInfo ) ;
169
252
}
170
253
@@ -176,12 +259,9 @@ public bool Write(AssetsFileWriter writer, List<BundleReplacer> replacers, Class
176
259
{
177
260
AssetBundleDirectoryInfo06 info = new AssetBundleDirectoryInfo06 ( )
178
261
{
179
- offset = currentOffset ,
180
- decompressedSize = replacer . GetSize ( ) ,
181
262
flags = ( uint ) ( replacer . HasSerializedData ( ) ? 0x04 : 0x00 ) ,
182
263
name = replacer . GetEntryName ( )
183
264
} ;
184
- currentOffset += info . decompressedSize ;
185
265
186
266
dirInfos . Add ( info ) ;
187
267
}
@@ -595,12 +675,24 @@ public int NumFiles
595
675
596
676
public bool IsAssetsFile ( int index )
597
677
{
598
- GetFileRange ( index , out long offset , out long length ) ;
599
- return AssetsFile . IsAssetsFile ( reader , offset , length ) ;
678
+ if ( bundleHeader3 != null )
679
+ return IsAssetsFile ( assetsLists3 . entries [ index ] ) ;
680
+
681
+ if ( bundleHeader6 != null )
682
+ return IsAssetsFile ( bundleInf6 . dirInf [ index ] ) ;
683
+
684
+ return false ;
685
+ }
686
+
687
+ [ Obsolete ]
688
+ public bool IsAssetsFile ( AssetsBundleEntry entry )
689
+ {
690
+ long offset = bundleHeader3 . bundleDataOffs + entry . offset ;
691
+ return AssetsFile . IsAssetsFile ( reader , offset , entry . length ) ;
600
692
}
601
693
602
694
[ Obsolete ]
603
- public bool IsAssetsFile ( AssetsFileReader reader , AssetBundleDirectoryInfo06 entry )
695
+ public bool IsAssetsFile ( AssetBundleDirectoryInfo06 entry )
604
696
{
605
697
long offset = bundleHeader6 . GetFileDataOffset ( ) + entry . offset ;
606
698
return AssetsFile . IsAssetsFile ( reader , offset , entry . decompressedSize ) ;
0 commit comments