@@ -30,17 +30,33 @@ public bool Read(AssetsFileReader reader, bool allowCompressed = false)
3030 this . reader = reader ;
3131 reader . ReadNullTerminated ( ) ;
3232 uint version = reader . ReadUInt32 ( ) ;
33- if ( version == 6 || version == 7 )
33+ switch ( version )
3434 {
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+
4460 bundleInf6 = new AssetBundleBlockAndDirectoryList06 ( ) ;
4561 if ( ( bundleHeader6 . flags & 0x3F ) != 0 )
4662 {
@@ -59,23 +75,103 @@ public bool Read(AssetsFileReader reader, bool allowCompressed = false)
5975 bundleInf6 . Read ( bundleHeader6 . GetBundleInfoOffset ( ) , reader ) ;
6076 return true ;
6177 }
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 )
64118 {
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 ) ;
66124 }
67125 }
68- else if ( version == 3 )
126+
127+ foreach ( BundleReplacer replacer in addingReplacers . Values )
69128 {
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 ) ;
71132 }
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 )
73143 {
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 ) ;
75159 }
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 ;
77172 }
78- public bool Write ( AssetsFileWriter writer , List < BundleReplacer > replacers , ClassDatabaseFile typeMeta = null )
173+
174+ private bool Write06 ( AssetsFileWriter writer , List < BundleReplacer > replacers )
79175 {
80176 bundleHeader6 . Write ( writer ) ;
81177
@@ -84,15 +180,15 @@ public bool Write(AssetsFileWriter writer, List<BundleReplacer> replacers, Class
84180 writer . Align16 ( ) ;
85181 }
86182
87- AssetBundleBlockAndDirectoryList06 newBundleInf6 = new AssetBundleBlockAndDirectoryList06 ( )
183+ AssetBundleBlockAndDirectoryList06 newBundleInf6 = new AssetBundleBlockAndDirectoryList06
88184 {
89185 checksumLow = 0 ,
90186 checksumHigh = 0
91187 } ;
92188 //I could map the assets to their blocks but I don't
93189 //have any more-than-1-block files to test on
94190 //this should work just fine as far as I know
95- newBundleInf6 . blockInf = new AssetBundleBlockInfo06 [ ]
191+ newBundleInf6 . blockInf = new [ ]
96192 {
97193 new AssetBundleBlockInfo06
98194 {
@@ -108,19 +204,14 @@ public bool Write(AssetsFileWriter writer, List<BundleReplacer> replacers, Class
108204 List < AssetBundleDirectoryInfo06 > originalDirInfos = new List < AssetBundleDirectoryInfo06 > ( ) ;
109205 List < AssetBundleDirectoryInfo06 > dirInfos = new List < AssetBundleDirectoryInfo06 > ( ) ;
110206 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 ;
115207
116208 //write all original files, modify sizes if needed and skip those to be removed
117209 for ( int i = 0 ; i < bundleInf6 . directoryCount ; i ++ )
118210 {
119211 AssetBundleDirectoryInfo06 info = bundleInf6 . dirInf [ i ] ;
120212 originalDirInfos . Add ( info ) ;
121- AssetBundleDirectoryInfo06 newInfo = new AssetBundleDirectoryInfo06 ( )
213+ AssetBundleDirectoryInfo06 newInfo = new AssetBundleDirectoryInfo06
122214 {
123- offset = currentOffset ,
124215 decompressedSize = info . decompressedSize ,
125216 flags = info . flags ,
126217 name = info . name
@@ -131,19 +222,16 @@ public bool Write(AssetsFileWriter writer, List<BundleReplacer> replacers, Class
131222 currentReplacers . Remove ( replacer ) ;
132223 if ( replacer . GetReplacementType ( ) == BundleReplacementType . AddOrModify )
133224 {
134- newInfo = new AssetBundleDirectoryInfo06 ( )
225+ newInfo = new AssetBundleDirectoryInfo06
135226 {
136- offset = currentOffset ,
137- decompressedSize = replacer . GetSize ( ) ,
138227 flags = info . flags ,
139228 name = replacer . GetEntryName ( )
140229 } ;
141230 }
142231 else if ( replacer . GetReplacementType ( ) == BundleReplacementType . Rename )
143232 {
144- newInfo = new AssetBundleDirectoryInfo06 ( )
233+ newInfo = new AssetBundleDirectoryInfo06
145234 {
146- offset = currentOffset ,
147235 decompressedSize = info . decompressedSize ,
148236 flags = info . flags ,
149237 name = replacer . GetEntryName ( )
@@ -160,11 +248,6 @@ public bool Write(AssetsFileWriter writer, List<BundleReplacer> replacers, Class
160248 newToOriginalDirInfoLookup [ newInfo ] = info ;
161249 }
162250
163- if ( newInfo . decompressedSize != - 1 )
164- {
165- currentOffset += newInfo . decompressedSize ;
166- }
167-
168251 dirInfos . Add ( newInfo ) ;
169252 }
170253
@@ -176,12 +259,9 @@ public bool Write(AssetsFileWriter writer, List<BundleReplacer> replacers, Class
176259 {
177260 AssetBundleDirectoryInfo06 info = new AssetBundleDirectoryInfo06 ( )
178261 {
179- offset = currentOffset ,
180- decompressedSize = replacer . GetSize ( ) ,
181262 flags = ( uint ) ( replacer . HasSerializedData ( ) ? 0x04 : 0x00 ) ,
182263 name = replacer . GetEntryName ( )
183264 } ;
184- currentOffset += info . decompressedSize ;
185265
186266 dirInfos . Add ( info ) ;
187267 }
@@ -595,12 +675,24 @@ public int NumFiles
595675
596676 public bool IsAssetsFile ( int index )
597677 {
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 ) ;
600692 }
601693
602694 [ Obsolete ]
603- public bool IsAssetsFile ( AssetsFileReader reader , AssetBundleDirectoryInfo06 entry )
695+ public bool IsAssetsFile ( AssetBundleDirectoryInfo06 entry )
604696 {
605697 long offset = bundleHeader6 . GetFileDataOffset ( ) + entry . offset ;
606698 return AssetsFile . IsAssetsFile ( reader , offset , entry . decompressedSize ) ;
0 commit comments