public async Task DePackageAsync(string sourceFile) { /* * * 最后一位为:8的偏移量是:17,对应资源文件:cboeffect.zip,cbohair.zip,cbohum.zip,cboweapon.zip,chrsel.zip,effect.zip,hair.zip,hair2.zip,hum.zip,hum2.zip,humeffect.zip,magic.zip,magic2.zip,magic3.zip,magic4.zip,magic5.zip,magic6.zip,mon-kulou.zip,mon1.zip,mon10.zip,mon11.zip,mon12.zip,mon13.zip,mon14.zip,mon15.zip,mon16.zip,mon17.zip,mon18.zip,mon19.zip,mon2.zip,mon20.zip,mon21.zip,mon22.zip,mon23.zip,mon24.zip,mon28.zip,mon3.zip,mon4.zip,mon5.zip,mon6.zip,mon7.zip,mon8.zip,mon9.zip,npc.zip,objects.zip,objects10.zip,objects13.zip,objects14.zip,objects2.zip,objects3.zip,objects4.zip,objects5.zip,objects6.zip,objects7.zip,objects8.zip,objects9.zip,prguse.zip,prguse2.zip,prguse3.zip,smtiles.zip,tiles.zip,weapon.zip,weapon2.zip * * 最后一位为:16的偏移量是:0,对应资源文件:dnitems.zip,hair2_ball.zip,hum3_ball.zip,items.zip,magic10.zip,magic7.zip,magic8.zip,mon34.zip,stateitem.zip,ui1.zip * * 最后一位为:0的偏移量是:0,后9位全是0,对应资源文件:mmap.zip,上一层目录的rs.zip */ ChildFiles = new List <ChildFile>(); using (var stream = CreateReadStream(sourceFile)) { if (!IsMobileResourceFile(stream)) { throw new Exception("不是正确的资源压缩包"); } //读取4个字节.应该png是长度 int pngNameListOffset = GetPngNameListOffset(stream); var array = new byte[4]; stream.Seek(pngNameListOffset, SeekOrigin.Begin); await stream.ReadAsync(array, 0, array.Length).ConfigureAwait(false); //读取4位,是有多少个文件 int fileCount = BitConverter.ToInt32(array, 0); for (int i = 0; i < fileCount; i++) { //读取4位是文件名长度 await stream.ReadAsync(array, 0, array.Length).ConfigureAwait(false); var fileLength = BitConverter.ToInt32(array, 0); //根据文件名长度,读取文件名 var fileNameArray = new byte[fileLength]; await stream.ReadAsync(fileNameArray, 0, fileLength).ConfigureAwait(false); var fileName = Encoding.UTF8.GetString(fileNameArray); //往下再读取4个byte,得到长度 await stream.ReadAsync(array, 0, array.Length).ConfigureAwait(false); var length = BitConverter.ToInt32(array, 0); //往下再读取4个byte,得到文件地址 await stream.ReadAsync(array, 0, array.Length).ConfigureAwait(false); var offset = BitConverter.ToInt32(array, 0); //剩下9个字节不知道干什么的 var otherParamArray = new byte[9]; stream.Read(otherParamArray, 0, otherParamArray.Length); var childFile = new ChildFile() { FileName = fileName, Offset = offset, Length = length, X = BitConverter.ToInt16(otherParamArray, 0), Y = BitConverter.ToInt16(otherParamArray, 2), Width = BitConverter.ToInt16(otherParamArray, 4), Height = BitConverter.ToInt16(otherParamArray, 6), TypeCode = otherParamArray[8] }; ChildFiles.Add(childFile); //Console.WriteLine($"{offset}\t{length}"); //Console.WriteLine(childFile.ToString()); } } if (ChildFiles.Count > 0) { this.TypeCode = ChildFiles[0].TypeCode; } SaveToFile(sourceFile); }
public async Task PackageAsync(string dir) { string iniPath = GetIniPath(dir); if (!File.Exists(iniPath)) { throw new FileNotFoundException("打包的文件夹必须是使用本软件解包的资源!"); } ReadIniFile(iniPath); this.ChildFiles = new List <ChildFile>(); //AsyncBinaryWriter Dispose时会关闭传入的流 using (var stream = File.Create(dir + ".zip")) { //写头 await stream.WriteAsync("www.sdo.com").ConfigureAwait(false); await stream.WriteAsync(byte.MinValue).ConfigureAwait(false); //写文件列表读取偏移量,先占位,后面写完后再修改 await stream.WriteAsync(0).ConfigureAwait(false); foreach (var file in Directory.GetFiles(dir, "*.*", SearchOption.AllDirectories)) { if (IsIniFile(file)) { continue; } var childFile = new ChildFile() { FileName = file.Replace(dir + Path.DirectorySeparatorChar, string.Empty).Replace('\\', '/'), TypeCode = this.TypeCode, Offset = (int)stream.Length }; //通过读取ini文件加载坐标 childFile.ReadIni(file); using (var childStream = CreateReadStream(file)) { childFile.Length = (int)childStream.Length + (this.TypeCode == 8 ? 17 : 0); //写入流 await stream.WriteAsync(await childStream.ReadBytesAsync((int)childStream.Length).ConfigureAwait(false)).ConfigureAwait(false); //加载长宽 if (this.TypeCode != 0) { using (Image image = Image.FromStream(childStream)) { childFile.Width = (short)image.Width; childFile.Height = (short)image.Height; } } } this.ChildFiles.Add(childFile); } //从此地址开始写文件列表 int fileListoffset = (int)stream.Length; //开始文件列表地址偏移量 stream.Seek(12, SeekOrigin.Begin); //覆盖最早写的int值(4字节) await stream.WriteAsync(fileListoffset).ConfigureAwait(false); //开始写文件列表 stream.Seek(0, SeekOrigin.End); //写文件数量 await stream.WriteAsync(this.ChildFiles.Count).ConfigureAwait(false); foreach (var childFile in this.ChildFiles) { await childFile.WriteFileInfoAsync(stream).ConfigureAwait(false); } await stream.FlushAsync().ConfigureAwait(false); } }