| 
									
										
										
										
											2024-03-06 22:06:49 +08:00
										 |  |  | import { | 
					
						
							|  |  |  |     _decorator, | 
					
						
							|  |  |  |     Asset, | 
					
						
							|  |  |  |     assetManager, | 
					
						
							|  |  |  |     BufferAsset, | 
					
						
							|  |  |  |     Component, | 
					
						
							|  |  |  |     Node, | 
					
						
							|  |  |  |     resources, | 
					
						
							|  |  |  |     TextAsset, | 
					
						
							|  |  |  |     v2, | 
					
						
							|  |  |  |     v3, | 
					
						
							|  |  |  |     Vec2, | 
					
						
							|  |  |  | } from "cc"; | 
					
						
							|  |  |  | import { ReadStream } from "../Tool/ReadStream"; | 
					
						
							|  |  |  | import { Ani_Frame, ScriptAni, ScriptFile } from "../GlobalInterface/GlobalInterface"; | 
					
						
							|  |  |  | import { GlobalTool } from "../Tool/GlobalTool"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const { ccclass, property } = _decorator; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ScriptTree { | 
					
						
							|  |  |  |     //PVF文件头数据
 | 
					
						
							|  |  |  |     Index_Header_Data: Uint8Array; | 
					
						
							|  |  |  |     //PVF原始数据
 | 
					
						
							|  |  |  |     Script_Data_Buffer: Uint8Array; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //文件头读取流
 | 
					
						
							|  |  |  |     Index_Header_Read_Object: ReadStream; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //树Map
 | 
					
						
							|  |  |  |     TreeMap: Map<string, ScriptFile> = new Map<string, ScriptFile>(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     constructor(gIndex_Header_Data, gScript_Data_Buffer) { | 
					
						
							|  |  |  |         this.Index_Header_Data = gIndex_Header_Data; | 
					
						
							|  |  |  |         this.Script_Data_Buffer = gScript_Data_Buffer; | 
					
						
							|  |  |  |         this.Index_Header_Read_Object = new ReadStream(this.Index_Header_Data); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ReadTree(currPos, startPos, Index) { | 
					
						
							|  |  |  |         this.Index_Header_Read_Object.Seekg(currPos); | 
					
						
							|  |  |  |         const FileNumber = this.Index_Header_Read_Object.GetInt(); | 
					
						
							|  |  |  |         const FilePathLength = this.Index_Header_Read_Object.GetInt(); | 
					
						
							|  |  |  |         const FilePath = this.Index_Header_Read_Object.GetBufferByLength(FilePathLength); | 
					
						
							|  |  |  |         const FileLength = this.Index_Header_Read_Object.GetInt(); | 
					
						
							|  |  |  |         const Cre32 = this.Index_Header_Read_Object.GetInt(); | 
					
						
							|  |  |  |         //数据偏移
 | 
					
						
							|  |  |  |         const RelativeOffset = this.Index_Header_Read_Object.GetInt(); | 
					
						
							|  |  |  |         if (FileLength > 0) { | 
					
						
							|  |  |  |             //数据长度
 | 
					
						
							|  |  |  |             const RealFileLength = (FileLength + 3) & 4294967292; | 
					
						
							|  |  |  |             //文件路径
 | 
					
						
							|  |  |  |             const RealFilePath = GlobalTool.uint8ArrayToString(FilePath).replace("\\", "/"); | 
					
						
							|  |  |  |             //建立索引Map
 | 
					
						
							|  |  |  |             this.TreeMap.set(RealFilePath, { Cre32: Cre32, StartPos: startPos, Offset: RelativeOffset, Length: RealFileLength }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return FilePathLength + 20; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //原数据
 | 
					
						
							|  |  |  |     StringtableBaseBuf; | 
					
						
							|  |  |  |     //CRE key
 | 
					
						
							|  |  |  |     StringtableCre32; | 
					
						
							|  |  |  |     //读取Bin文件
 | 
					
						
							|  |  |  |     StringTable: Map<number, string> = new Map<number, string>(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //当前索引位置
 | 
					
						
							|  |  |  |     StringtableCurrentIndex: number = 0; | 
					
						
							|  |  |  |     //当前读取索引位置
 | 
					
						
							|  |  |  |     StringtableReadCurrentIndex: number = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //本类用的特殊解密 分段解密
 | 
					
						
							|  |  |  |     CrcDecodeSpecial(): boolean { | 
					
						
							|  |  |  |         const num: number = 2175242257; // 2175242257L in hexadecimal
 | 
					
						
							|  |  |  |         const dataView = new DataView( | 
					
						
							|  |  |  |             this.StringtableBaseBuf.buffer, | 
					
						
							|  |  |  |             this.StringtableBaseBuf.byteOffset, | 
					
						
							|  |  |  |             this.StringtableBaseBuf.byteLength, | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         //开始时间
 | 
					
						
							|  |  |  |         const StartTime = new Date().getTime(); | 
					
						
							|  |  |  |         //死循环读取树文件数据 但是每一次最多只读15毫秒 为了保证UI线程刷新
 | 
					
						
							|  |  |  |         while (true) { | 
					
						
							|  |  |  |             // Ensure we don't read beyond the end of the data  //如果当前索引位置加上4大于数组长度 说明读取完毕 返回true
 | 
					
						
							|  |  |  |             if (this.StringtableCurrentIndex >= this.StringtableBaseBuf.length) return true; | 
					
						
							|  |  |  |             //当前时间减去开始时间
 | 
					
						
							|  |  |  |             const NowTime = new Date().getTime(); | 
					
						
							|  |  |  |             //如果本轮循环已经读取了15毫秒了  就先返回刷新ui
 | 
					
						
							|  |  |  |             if (NowTime - StartTime >= 15) return false; | 
					
						
							|  |  |  |             // Read a 32-bit integer (little endian) from the buffer
 | 
					
						
							|  |  |  |             let anInt = dataView.getUint32(this.StringtableCurrentIndex, true); | 
					
						
							|  |  |  |             // Perform the XOR operations
 | 
					
						
							|  |  |  |             let val = anInt ^ num ^ this.StringtableCre32; | 
					
						
							|  |  |  |             // Rotate right 6 bits
 | 
					
						
							|  |  |  |             let jiemi = (val >>> 6) | (val << (32 - 6)); | 
					
						
							|  |  |  |             // Write the result back into the buffer
 | 
					
						
							|  |  |  |             dataView.setUint32(this.StringtableCurrentIndex, jiemi, true); | 
					
						
							|  |  |  |             this.StringtableCurrentIndex = this.StringtableCurrentIndex + 4; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     InitStringBin() { | 
					
						
							|  |  |  |         //如果这个是空就读取一下
 | 
					
						
							|  |  |  |         if (this.StringtableBaseBuf == undefined) { | 
					
						
							|  |  |  |             const FileObject = this.TreeMap.get("stringtable.bin"); | 
					
						
							| 
									
										
										
										
											2024-03-07 13:32:04 +08:00
										 |  |  |             if (FileObject == undefined) return true; | 
					
						
							| 
									
										
										
										
											2024-03-06 22:06:49 +08:00
										 |  |  |             this.StringtableBaseBuf = this.Script_Data_Buffer.slice( | 
					
						
							|  |  |  |                 FileObject.StartPos + FileObject.Offset, | 
					
						
							|  |  |  |                 FileObject.StartPos + FileObject.Offset + FileObject.Length | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  |             this.StringtableCre32 = FileObject.Cre32; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const Flag = this.CrcDecodeSpecial(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (Flag) { | 
					
						
							|  |  |  |             let Ro = new ReadStream(this.StringtableBaseBuf); | 
					
						
							|  |  |  |             const Count = Ro.GetInt(); | 
					
						
							|  |  |  |             //开始时间
 | 
					
						
							|  |  |  |             const StartTime = new Date().getTime(); | 
					
						
							|  |  |  |             while (true) { | 
					
						
							|  |  |  |                 //当前时间减去开始时间
 | 
					
						
							|  |  |  |                 const NowTime = new Date().getTime(); | 
					
						
							|  |  |  |                 //如果本轮循环已经读取了15毫秒了  就先返回刷新ui
 | 
					
						
							|  |  |  |                 if (NowTime - StartTime >= 15) return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (this.StringtableReadCurrentIndex < Count) { | 
					
						
							|  |  |  |                     Ro.Seekg(this.StringtableReadCurrentIndex * 4 + 4); | 
					
						
							|  |  |  |                     const StartPos = Ro.GetInt(); | 
					
						
							|  |  |  |                     const EndPos = Ro.GetInt(); | 
					
						
							|  |  |  |                     const Len = EndPos - StartPos; | 
					
						
							|  |  |  |                     Ro.Seekg(StartPos + 4); | 
					
						
							|  |  |  |                     const Str = Ro.GetString(Len); | 
					
						
							|  |  |  |                     this.StringTable.set(this.StringtableReadCurrentIndex, Str); | 
					
						
							|  |  |  |                     this.StringtableReadCurrentIndex++; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     return true; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //读取字符串索引
 | 
					
						
							|  |  |  |     Load_StringTable: Map<string, string> = new Map<string, string>(); | 
					
						
							|  |  |  |     InitLoad_String() { | 
					
						
							|  |  |  |         const FileObject = this.TreeMap.get("n_string.lst"); | 
					
						
							| 
									
										
										
										
											2024-03-07 13:32:04 +08:00
										 |  |  |         if (FileObject == undefined) return; | 
					
						
							| 
									
										
										
										
											2024-03-06 22:06:49 +08:00
										 |  |  |         let RealBuf = this.Script_Data_Buffer.slice( | 
					
						
							|  |  |  |             FileObject.StartPos + FileObject.Offset, | 
					
						
							|  |  |  |             FileObject.StartPos + FileObject.Offset + FileObject.Length | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         GlobalTool.CrcDecode(RealBuf, FileObject.Cre32); | 
					
						
							|  |  |  |         let Ro = new ReadStream(RealBuf); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const Count = Ro.GetUShort(); | 
					
						
							|  |  |  |         if (Count != 53424) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let i = 2; | 
					
						
							|  |  |  |         while (i < Ro.len()) { | 
					
						
							|  |  |  |             if (Ro.len() - i >= 10) { | 
					
						
							|  |  |  |                 Ro.Seekg(i + 6); | 
					
						
							|  |  |  |                 const Key = this.StringTable.get(Ro.GetInt()); | 
					
						
							|  |  |  |                 if (Key) { | 
					
						
							|  |  |  |                     const File = this.TreeMap.get(Key.toLocaleLowerCase()); | 
					
						
							|  |  |  |                     let FileBuf = this.Script_Data_Buffer.slice( | 
					
						
							|  |  |  |                         File.StartPos + File.Offset, | 
					
						
							|  |  |  |                         File.StartPos + File.Offset + File.Length | 
					
						
							|  |  |  |                     ); | 
					
						
							|  |  |  |                     GlobalTool.CrcDecode(FileBuf, File.Cre32); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     let Str = GlobalTool.uint8ArrayToString(FileBuf, 'big5'); | 
					
						
							|  |  |  |                     let StrArr = Str.split('\r\n'); | 
					
						
							|  |  |  |                     StrArr.forEach((strobj, index) => { | 
					
						
							|  |  |  |                         if (strobj.indexOf('>')) { | 
					
						
							|  |  |  |                             let strobjarr = strobj.split('>', 2); | 
					
						
							|  |  |  |                             this.Load_StringTable.set(strobjarr[0], strobjarr[1]); | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     }); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else break; | 
					
						
							|  |  |  |             i += 10; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //Pvf文件数据
 | 
					
						
							|  |  |  |     ScriptFileData = new Map(); | 
					
						
							|  |  |  |     GetFileData(Path: string) { | 
					
						
							|  |  |  |         //检查路径是否存在
 | 
					
						
							|  |  |  |         const FileObject = this.TreeMap.get(Path); | 
					
						
							|  |  |  |         if (FileObject == undefined) return false; | 
					
						
							|  |  |  |         //如果读过直接返回数据
 | 
					
						
							|  |  |  |         const FileData = this.ScriptFileData.get(Path); | 
					
						
							|  |  |  |         if (FileData != undefined) return FileData; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         //获取文件数据字节数组
 | 
					
						
							|  |  |  |         let RealBuf = this.Script_Data_Buffer.slice( | 
					
						
							|  |  |  |             FileObject.StartPos + FileObject.Offset, | 
					
						
							|  |  |  |             FileObject.StartPos + FileObject.Offset + FileObject.Length | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         GlobalTool.CrcDecode(RealBuf, FileObject.Cre32); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         //Ani的处理逻辑
 | 
					
						
							|  |  |  |         if (Path.indexOf(".ani") != -1) { | 
					
						
							|  |  |  |             // try {
 | 
					
						
							|  |  |  |             let Buf = this.Decompile_ani(RealBuf); | 
					
						
							|  |  |  |             this.ScriptFileData.set(Path, Buf); | 
					
						
							|  |  |  |             return Buf; | 
					
						
							|  |  |  |             // } catch (error) {
 | 
					
						
							|  |  |  |             // console.log(Path);
 | 
					
						
							|  |  |  |             // }
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             try { | 
					
						
							|  |  |  |                 let Buf = this.Decompile_script(RealBuf); | 
					
						
							|  |  |  |                 this.ScriptFileData.set(Path, Buf); | 
					
						
							|  |  |  |                 return Buf; | 
					
						
							|  |  |  |             } catch (error) { | 
					
						
							|  |  |  |                 // console.log(RealFilePath);
 | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Decompile_script(RealBuf: any) { | 
					
						
							|  |  |  |         const Ro = new ReadStream(RealBuf); | 
					
						
							|  |  |  |         let out: string = ""; | 
					
						
							|  |  |  |         if (Ro.len() >= 7) { | 
					
						
							|  |  |  |             //以5为单步从第二位开始遍历字节
 | 
					
						
							|  |  |  |             let i = 2; | 
					
						
							|  |  |  |             while (i < Ro.len()) { | 
					
						
							|  |  |  |                 //到最后了就不处理了防止内存越界
 | 
					
						
							|  |  |  |                 if (Ro.len() - i >= 5) { | 
					
						
							|  |  |  |                     Ro.Seekg(i); //内容指示位
 | 
					
						
							|  |  |  |                     let currentByte = Number(Ro.GetBufferByLength(1)); //内容指示位
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     let after = Ro.GetInt(); | 
					
						
							|  |  |  |                     switch (currentByte) { | 
					
						
							|  |  |  |                         case 10: | 
					
						
							|  |  |  |                             { | 
					
						
							|  |  |  |                                 Ro.Seekg(i - 4); | 
					
						
							|  |  |  |                                 const Before = Ro.GetInt(); | 
					
						
							|  |  |  |                                 let Buf = this.StringTable.get(after); | 
					
						
							|  |  |  |                                 if (!Buf) { | 
					
						
							|  |  |  |                                     Buf = ""; | 
					
						
							|  |  |  |                                 } else { | 
					
						
							|  |  |  |                                     Buf = "<" + Before + "::" + Buf + "`" + this.Load_StringTable.get(Buf) + "`>"; | 
					
						
							|  |  |  |                                 } | 
					
						
							|  |  |  |                                 Buf = Buf + "\r\n"; | 
					
						
							|  |  |  |                                 out += Buf; | 
					
						
							|  |  |  |                                 break; | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         case 2: | 
					
						
							|  |  |  |                             { | 
					
						
							|  |  |  |                                 out += after + '\t'; | 
					
						
							|  |  |  |                                 break; | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         case 4: | 
					
						
							|  |  |  |                             { | 
					
						
							|  |  |  |                                 const buffer = new ArrayBuffer(4); | 
					
						
							|  |  |  |                                 const view = new DataView(buffer); | 
					
						
							|  |  |  |                                 view.setInt32(0, after, true); | 
					
						
							|  |  |  |                                 const Buf = view.getFloat32(0); | 
					
						
							|  |  |  |                                 out += after + '\t'; | 
					
						
							|  |  |  |                                 break; | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         case 6: | 
					
						
							|  |  |  |                         case 8: | 
					
						
							|  |  |  |                         case 7: | 
					
						
							|  |  |  |                         case 5: | 
					
						
							|  |  |  |                             { | 
					
						
							|  |  |  |                                 let Buf = this.StringTable.get(after); | 
					
						
							|  |  |  |                                 if (!Buf) Buf = ""; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                                 if (currentByte == 5) { | 
					
						
							|  |  |  |                                     Buf = "\r\n" + Buf + "\r\n"; | 
					
						
							|  |  |  |                                 } | 
					
						
							|  |  |  |                                 else if (currentByte == 7) { | 
					
						
							|  |  |  |                                     Buf = "`" + Buf + "`\r\n"; | 
					
						
							|  |  |  |                                 } | 
					
						
							|  |  |  |                                 else if (currentByte == 6 || currentByte == 8) { | 
					
						
							|  |  |  |                                     Buf = "{{" + currentByte + "=`" + Buf + "`}}\r\n"; | 
					
						
							|  |  |  |                                 } | 
					
						
							|  |  |  |                                 out += Buf; | 
					
						
							|  |  |  |                                 break; | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         default: | 
					
						
							|  |  |  |                             out += ""; | 
					
						
							|  |  |  |                             break; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 i += 5; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return out; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //解包数据
 | 
					
						
							|  |  |  |     Unpack_Chr(pvfData, curr: number, after: number, before: number): string { | 
					
						
							|  |  |  |         switch (curr) { | 
					
						
							|  |  |  |             case 2: | 
					
						
							|  |  |  |                 return after.toString(); //整数型
 | 
					
						
							|  |  |  |             case 4: | 
					
						
							|  |  |  |             // return new Float32Array([after]).buffer.slice(0, 4).readFloatLE().toString();
 | 
					
						
							|  |  |  |             case 5: | 
					
						
							|  |  |  |             case 6: | 
					
						
							|  |  |  |             case 7: | 
					
						
							|  |  |  |             case 8: | 
					
						
							|  |  |  |                 if (pvfData.str_bin_map.has(after)) { | 
					
						
							|  |  |  |                     return pvfData.str_bin_map.get(after); | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     return ""; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             case 10: | 
					
						
							|  |  |  |                 if (!pvfData.str_bin_map.has(after)) { | 
					
						
							|  |  |  |                     return ""; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 let tempstr = pvfData.str_bin_map.get(after); | 
					
						
							|  |  |  |             // return `<${before}::\`${tempstr}\`${_getNString(pvfData, before, tempstr)}.toString()}>`;
 | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 return ""; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //读取Ani
 | 
					
						
							|  |  |  |     Decompile_ani(RealBuf: any): any { | 
					
						
							|  |  |  |         let AniObject: ScriptAni = { | 
					
						
							|  |  |  |             Img_List: new Array<string>(), | 
					
						
							|  |  |  |             Flag: new Map<string, number>(), | 
					
						
							|  |  |  |             Frame: new Array<Ani_Frame>(), | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const Ro = new ReadStream(RealBuf); | 
					
						
							|  |  |  |         //总帧数
 | 
					
						
							|  |  |  |         const Frame_Max = Ro.GetUShort(); | 
					
						
							|  |  |  |         //总共调用了多少个Img
 | 
					
						
							|  |  |  |         const Img_Count = Ro.GetUShort(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         //Img的路径读取 存入数组
 | 
					
						
							|  |  |  |         for (let index = 0; index < Img_Count; index++) { | 
					
						
							|  |  |  |             const Buf = Ro.GetInt(); | 
					
						
							|  |  |  |             //有可能Img有空路径
 | 
					
						
							|  |  |  |             AniObject.Img_List.push(Ro.GetString(Buf)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         //Ani头部标签数量
 | 
					
						
							|  |  |  |         const Ani_H_Item_Count = Ro.GetUShort(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         //处理标签
 | 
					
						
							|  |  |  |         for (let index = 0; index < Ani_H_Item_Count; index++) { | 
					
						
							|  |  |  |             //标签类型
 | 
					
						
							|  |  |  |             const Type = Ro.GetUShort(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             switch (Type) { | 
					
						
							|  |  |  |                 case 0: | 
					
						
							|  |  |  |                 case 1: { | 
					
						
							|  |  |  |                     const Key = this.Get_Ani_Flag(Type); | 
					
						
							|  |  |  |                     const Value = Number(Ro.GetBufferByLength(1)); | 
					
						
							|  |  |  |                     AniObject.Flag.set(Key, Value); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 case 3: | 
					
						
							|  |  |  |                 case 28: { | 
					
						
							|  |  |  |                     const Key = this.Get_Ani_Flag(Type); | 
					
						
							|  |  |  |                     const Value = Ro.GetUShort(); | 
					
						
							|  |  |  |                     AniObject.Flag.set(Key, Value); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 case 18: | 
					
						
							|  |  |  |                     //此处无解析 暂时先保证运行  残影功能暂时用不上
 | 
					
						
							|  |  |  |                     Ro.GetBufferByLength(1); | 
					
						
							|  |  |  |                     Ro.GetInt(); | 
					
						
							|  |  |  |                     Ro.GetInt(); | 
					
						
							|  |  |  |                     Ro.GetInt(); | 
					
						
							|  |  |  |                     Ro.Get256(); | 
					
						
							|  |  |  |                     Ro.Get256(); | 
					
						
							|  |  |  |                     Ro.Get256(); | 
					
						
							|  |  |  |                     Ro.Get256(); | 
					
						
							|  |  |  |                     Ro.GetUShort(); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 default: | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         //读取每一个Img
 | 
					
						
							|  |  |  |         for (let index = 0; index < Frame_Max; index++) { | 
					
						
							|  |  |  |             //帧结构体对象
 | 
					
						
							|  |  |  |             let FrameObject: Ani_Frame = { | 
					
						
							|  |  |  |                 Box: new Map<number, Array<number>>(), | 
					
						
							|  |  |  |                 Img_Path: null, | 
					
						
							|  |  |  |                 Img_Index: null, | 
					
						
							|  |  |  |                 Pos: null, | 
					
						
							|  |  |  |                 Flag: new Map<string, any>(), | 
					
						
							|  |  |  |                 Delay: null, | 
					
						
							|  |  |  |             }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             //碰撞框项目数量
 | 
					
						
							|  |  |  |             const Ani_Box_Item_Count = Ro.GetUShort(); | 
					
						
							|  |  |  |             for (let _i = 0; _i < Ani_Box_Item_Count; _i++) { | 
					
						
							|  |  |  |                 const Box_Type = Ro.GetUShort(); | 
					
						
							|  |  |  |                 let D_Box_b = []; | 
					
						
							|  |  |  |                 for (let _k = 0; _k < 6; _k++) { | 
					
						
							|  |  |  |                     D_Box_b.push(Ro.GetInt()); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 //0是攻击框 1是受击框
 | 
					
						
							|  |  |  |                 FrameObject.Box.set(15 - Box_Type, D_Box_b); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             //调用的第几个Img
 | 
					
						
							|  |  |  |             const Index_Buf = Ro.GetShort(); | 
					
						
							|  |  |  |             //如果等于-1说明是img路径为空
 | 
					
						
							|  |  |  |             if (Index_Buf >= 0) { | 
					
						
							|  |  |  |                 FrameObject.Img_Path = AniObject.Img_List[Index_Buf]; | 
					
						
							|  |  |  |                 //Img中的PNG下标
 | 
					
						
							|  |  |  |                 FrameObject.Img_Index = Ro.GetUShort(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 FrameObject.Img_Path = ""; | 
					
						
							|  |  |  |                 FrameObject.Img_Index = 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             //坐标
 | 
					
						
							|  |  |  |             FrameObject.Pos = v3(Ro.GetInt(), -Ro.GetInt(), 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             //Img中的项目数量
 | 
					
						
							|  |  |  |             const Img_Flag_Count = Ro.GetUShort(); | 
					
						
							|  |  |  |             for (let _o = 0; _o < Img_Flag_Count; _o++) { | 
					
						
							|  |  |  |                 const Img_Flag_Type = Ro.GetUShort(); | 
					
						
							|  |  |  |                 let Key; | 
					
						
							|  |  |  |                 let Value; | 
					
						
							|  |  |  |                 switch (Img_Flag_Type) { | 
					
						
							|  |  |  |                     case 0: | 
					
						
							|  |  |  |                     case 1: | 
					
						
							|  |  |  |                     case 10: | 
					
						
							|  |  |  |                         Key = this.Get_Ani_Flag(Img_Flag_Type); | 
					
						
							|  |  |  |                         Value = Number(Ro.GetBufferByLength(1)); | 
					
						
							|  |  |  |                         FrameObject.Flag.set(Key, Value); | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     case 3: | 
					
						
							|  |  |  |                         Key = "COORD"; | 
					
						
							|  |  |  |                         Value = Ro.GetUShort(); | 
					
						
							|  |  |  |                         FrameObject.Flag.set(Key, Value); | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     case 17: | 
					
						
							|  |  |  |                         Key = "PRELOAD"; | 
					
						
							|  |  |  |                         Value = 1; | 
					
						
							|  |  |  |                         FrameObject.Flag.set(Key, Value); | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     case 7: | 
					
						
							|  |  |  |                         Key = "IMAGE_RATE"; | 
					
						
							|  |  |  |                         Value = { x: Ro.GetFloat(), y: Ro.GetFloat() }; | 
					
						
							|  |  |  |                         FrameObject.Flag.set(Key, Value); | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     case 8: | 
					
						
							|  |  |  |                         Key = "IMAGE_ROTATE"; | 
					
						
							|  |  |  |                         Value = Ro.GetFloat(); | 
					
						
							|  |  |  |                         FrameObject.Flag.set(Key, Value); | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     case 9: | 
					
						
							|  |  |  |                         Key = "RGBA"; | 
					
						
							|  |  |  |                         Value = [ | 
					
						
							|  |  |  |                             Ro.Get256(), | 
					
						
							|  |  |  |                             Ro.Get256(), | 
					
						
							|  |  |  |                             Ro.Get256(), | 
					
						
							|  |  |  |                             Ro.Get256(), | 
					
						
							|  |  |  |                         ]; | 
					
						
							|  |  |  |                         FrameObject.Flag.set(Key, Value); | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     case 11: | 
					
						
							|  |  |  |                         const Effect_Type = Ro.GetUShort(); | 
					
						
							|  |  |  |                         Key = "GRAPHIC_EFFECT_" + this.Get_Ani_Effect_Type(Effect_Type); | 
					
						
							|  |  |  |                         switch (Effect_Type) { | 
					
						
							|  |  |  |                             case 5: | 
					
						
							|  |  |  |                                 Value = [Ro.Get256(), Ro.Get256(), Ro.Get256()]; | 
					
						
							|  |  |  |                                 break; | 
					
						
							|  |  |  |                             case 6: | 
					
						
							|  |  |  |                                 Value = [Ro.GetShort(), Ro.GetShort()]; | 
					
						
							|  |  |  |                                 break; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         FrameObject.Flag.set(Key, Value); | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     case 12: | 
					
						
							|  |  |  |                         Value = Ro.GetInt(); | 
					
						
							|  |  |  |                         FrameObject.Delay = Value; | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     case 13: | 
					
						
							|  |  |  |                         Key = "DAMAGE_TYPE"; | 
					
						
							|  |  |  |                         Value = this.Get_Ani_Damage_Type(Ro.GetUShort()); | 
					
						
							|  |  |  |                         FrameObject.Flag.set(Key, Value); | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     case 16: | 
					
						
							|  |  |  |                         const SoundTempSize = Ro.GetInt(); | 
					
						
							|  |  |  |                         Key = "PLAY_SOUND"; | 
					
						
							|  |  |  |                         Value = Ro.GetString(SoundTempSize); | 
					
						
							|  |  |  |                         FrameObject.Flag.set(Key, Value); | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     case 23: | 
					
						
							|  |  |  |                         Key = "SET_FLAG"; | 
					
						
							|  |  |  |                         Value = Ro.GetInt(); | 
					
						
							|  |  |  |                         FrameObject.Flag.set(Key, Value); | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     case 24: | 
					
						
							|  |  |  |                         Key = "FLIP_TYPE"; | 
					
						
							|  |  |  |                         Value = this.Get_Ani_Flip_Type(Ro.GetUShort()); | 
					
						
							|  |  |  |                         FrameObject.Flag.set(Key, Value); | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     case 25: | 
					
						
							|  |  |  |                         Key = "LOOP_START"; | 
					
						
							|  |  |  |                         FrameObject.Flag.set(Key, 1); | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     case 26: | 
					
						
							|  |  |  |                         Key = "LOOP_END"; | 
					
						
							|  |  |  |                         Value = Ro.GetInt(); | 
					
						
							|  |  |  |                         FrameObject.Flag.set(Key, Value); | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     case 27: | 
					
						
							|  |  |  |                         Key = "CLIP"; | 
					
						
							|  |  |  |                         Value = [ | 
					
						
							|  |  |  |                             Ro.GetShort(), | 
					
						
							|  |  |  |                             Ro.GetShort(), | 
					
						
							|  |  |  |                             Ro.GetShort(), | 
					
						
							|  |  |  |                             Ro.GetShort(), | 
					
						
							|  |  |  |                         ]; | 
					
						
							|  |  |  |                         FrameObject.Flag.set(Key, Value); | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     default: | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             //每一帧都是一个结构体 存入数组中
 | 
					
						
							|  |  |  |             AniObject.Frame.push(FrameObject); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return AniObject; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Get_Ani_Flip_Type(data: number): string { | 
					
						
							|  |  |  |         switch (data) { | 
					
						
							|  |  |  |             case 1: | 
					
						
							|  |  |  |                 return "HORIZON"; | 
					
						
							|  |  |  |             case 2: | 
					
						
							|  |  |  |                 return "VERTICAL"; | 
					
						
							|  |  |  |             case 3: | 
					
						
							|  |  |  |                 return "ALL"; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 return ""; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Get_Ani_Effect_Type(data: number): string { | 
					
						
							|  |  |  |         switch (data) { | 
					
						
							|  |  |  |             case 0: | 
					
						
							|  |  |  |                 return "NONE"; | 
					
						
							|  |  |  |             case 1: | 
					
						
							|  |  |  |                 return "DODGE"; | 
					
						
							|  |  |  |             case 2: | 
					
						
							|  |  |  |                 return "LINEARDODGE"; | 
					
						
							|  |  |  |             case 3: | 
					
						
							|  |  |  |                 return "DARK"; | 
					
						
							|  |  |  |             case 4: | 
					
						
							|  |  |  |                 return "XOR"; | 
					
						
							|  |  |  |             case 5: | 
					
						
							|  |  |  |                 return "MONOCHROME"; | 
					
						
							|  |  |  |             case 6: | 
					
						
							|  |  |  |                 return "SPACEDISTORT"; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 return ""; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Get_Ani_Damage_Type(data: number): any { | 
					
						
							|  |  |  |         switch (data) { | 
					
						
							|  |  |  |             case 0: | 
					
						
							|  |  |  |                 return "NORMAL"; | 
					
						
							|  |  |  |             case 1: | 
					
						
							|  |  |  |                 return "SUPERARMOR"; | 
					
						
							|  |  |  |             case 2: | 
					
						
							|  |  |  |                 return "UNBREAKABLE"; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 return ""; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Get_Ani_Flag(data: number): string { | 
					
						
							|  |  |  |         switch (data) { | 
					
						
							|  |  |  |             case 0: | 
					
						
							|  |  |  |                 return "LOOP"; | 
					
						
							|  |  |  |             case 1: | 
					
						
							|  |  |  |                 return "SHADOW"; | 
					
						
							|  |  |  |             case 3: | 
					
						
							|  |  |  |                 return "COORD"; | 
					
						
							|  |  |  |             case 7: | 
					
						
							|  |  |  |                 return "IMAGE_RATE"; | 
					
						
							|  |  |  |             case 8: | 
					
						
							|  |  |  |                 return "IMAGE_ROTATE"; | 
					
						
							|  |  |  |             case 9: | 
					
						
							|  |  |  |                 return "RGBA"; | 
					
						
							|  |  |  |             case 10: | 
					
						
							|  |  |  |                 return "INTERPOLATION"; | 
					
						
							|  |  |  |             case 11: | 
					
						
							|  |  |  |                 return "GRAPHIC_EFFECT"; | 
					
						
							|  |  |  |             case 12: | 
					
						
							|  |  |  |                 return "DELAY"; | 
					
						
							|  |  |  |             case 13: | 
					
						
							|  |  |  |                 return "DAMAGE_TYPE"; | 
					
						
							|  |  |  |             case 14: | 
					
						
							|  |  |  |                 return "DAMAGE_BOX"; | 
					
						
							|  |  |  |             case 15: | 
					
						
							|  |  |  |                 return "ATTACK_BOX"; | 
					
						
							|  |  |  |             case 16: | 
					
						
							|  |  |  |                 return "PLAY_SOUND"; | 
					
						
							|  |  |  |             case 17: | 
					
						
							|  |  |  |                 return "PRELOAD"; | 
					
						
							|  |  |  |             case 18: | 
					
						
							|  |  |  |                 return "SPECTRUM"; | 
					
						
							|  |  |  |             case 23: | 
					
						
							|  |  |  |                 return "SET_FLAG"; | 
					
						
							|  |  |  |             case 24: | 
					
						
							|  |  |  |                 return "FLIP_TYPE"; | 
					
						
							|  |  |  |             case 25: | 
					
						
							|  |  |  |                 return "LOOP_START"; | 
					
						
							|  |  |  |             case 26: | 
					
						
							|  |  |  |                 return "LOOP_END"; | 
					
						
							|  |  |  |             case 27: | 
					
						
							|  |  |  |                 return "CLIP"; | 
					
						
							|  |  |  |             case 28: | 
					
						
							|  |  |  |                 return "OPERATION"; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 return ""; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ScriptData { | 
					
						
							|  |  |  |     //Pvf数据
 | 
					
						
							|  |  |  |     ScriptDataBuffer; | 
					
						
							|  |  |  |     //读取UUID的长度
 | 
					
						
							|  |  |  |     UUID_LENGTH; | 
					
						
							|  |  |  |     //UUID  读 1 - 36位 构造 UTF8 string
 | 
					
						
							|  |  |  |     UUID; | 
					
						
							|  |  |  |     //版本号
 | 
					
						
							|  |  |  |     Version; | 
					
						
							|  |  |  |     // 文件路径数据的大小
 | 
					
						
							|  |  |  |     AlignedIndexHeaderSize; | 
					
						
							|  |  |  |     // 解密密钥
 | 
					
						
							|  |  |  |     IndexHeaderCrc; | 
					
						
							|  |  |  |     // 文件数量
 | 
					
						
							|  |  |  |     IndexSize; | 
					
						
							|  |  |  |     // 存放文件路径数据
 | 
					
						
							|  |  |  |     Index_Header_Data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //Pvf解密出的数据
 | 
					
						
							|  |  |  |     ScriptDataObject: ScriptTree = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     constructor( | 
					
						
							|  |  |  |         public buffer: Uint8Array, | 
					
						
							|  |  |  |         public uuidLength: number, | 
					
						
							|  |  |  |         public uuid: string, | 
					
						
							|  |  |  |         public version: number, | 
					
						
							|  |  |  |         public alignedIndexHeaderSize: number, | 
					
						
							|  |  |  |         public indexHeaderCrc: number, | 
					
						
							|  |  |  |         public indexSize: number, | 
					
						
							|  |  |  |         public indexHeaderData: Uint8Array | 
					
						
							|  |  |  |     ) { | 
					
						
							|  |  |  |         //Pvf数据
 | 
					
						
							|  |  |  |         this.ScriptDataBuffer = buffer; | 
					
						
							|  |  |  |         //读取UUID的长度
 | 
					
						
							|  |  |  |         this.UUID_LENGTH = uuidLength; | 
					
						
							|  |  |  |         //UUID  读 1 - 36位 构造 UTF8 string
 | 
					
						
							|  |  |  |         this.UUID = uuid; | 
					
						
							|  |  |  |         //版本号
 | 
					
						
							|  |  |  |         this.Version = version; | 
					
						
							|  |  |  |         // 文件路径数据的大小
 | 
					
						
							|  |  |  |         this.AlignedIndexHeaderSize = alignedIndexHeaderSize; | 
					
						
							|  |  |  |         // 解密密钥
 | 
					
						
							|  |  |  |         this.IndexHeaderCrc = indexHeaderCrc; | 
					
						
							|  |  |  |         // 文件数量
 | 
					
						
							|  |  |  |         this.IndexSize = indexSize; | 
					
						
							|  |  |  |         // 存放文件路径数据
 | 
					
						
							|  |  |  |         this.Index_Header_Data = indexHeaderData; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //初始化路径树  把所有文件路径建立起来还没有读
 | 
					
						
							|  |  |  |     InitPathTree() { | 
					
						
							|  |  |  |         //先进行Crc解密
 | 
					
						
							|  |  |  |         GlobalTool.CrcDecode(this.Index_Header_Data, this.IndexHeaderCrc); | 
					
						
							|  |  |  |         //构造PVF数据类
 | 
					
						
							|  |  |  |         this.ScriptDataObject = new ScriptTree( | 
					
						
							|  |  |  |             //文件数据
 | 
					
						
							|  |  |  |             this.Index_Header_Data, | 
					
						
							|  |  |  |             //整个Pvf的原始数据
 | 
					
						
							|  |  |  |             this.ScriptDataBuffer | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //当期读取树数据的Pos
 | 
					
						
							|  |  |  |     CurrentTreePos = 0; | 
					
						
							|  |  |  |     //当前读取文件下标
 | 
					
						
							|  |  |  |     CurrentIndex = 0; | 
					
						
							|  |  |  |     ReadPathTree() { | 
					
						
							|  |  |  |         //开始时间
 | 
					
						
							|  |  |  |         const StartTime = new Date().getTime(); | 
					
						
							|  |  |  |         //死循环读取树文件数据 但是每一次最多只读15毫秒 为了保证UI线程刷新
 | 
					
						
							|  |  |  |         while (true) { | 
					
						
							|  |  |  |             //当前时间减去开始时间
 | 
					
						
							|  |  |  |             const NowTime = new Date().getTime(); | 
					
						
							|  |  |  |             if ((NowTime - StartTime) >= 15) break; | 
					
						
							|  |  |  |             //当前读取的下标小于总数量
 | 
					
						
							|  |  |  |             if (this.CurrentIndex < this.IndexSize) { | 
					
						
							|  |  |  |                 const Length = this.ScriptDataObject.ReadTree( | 
					
						
							|  |  |  |                     this.CurrentTreePos, | 
					
						
							|  |  |  |                     this.AlignedIndexHeaderSize + 56, | 
					
						
							|  |  |  |                     this.CurrentIndex | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |                 this.CurrentTreePos += Length; | 
					
						
							|  |  |  |                 this.CurrentIndex++; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             //如果不小于 说明读完了
 | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 //读取bin文件 bin Map
 | 
					
						
							|  |  |  |                 const Flag = this.ScriptDataObject.InitStringBin(); | 
					
						
							|  |  |  |                 if (Flag) { | 
					
						
							|  |  |  |                     //读取字符串索引
 | 
					
						
							|  |  |  |                     this.ScriptDataObject.InitLoad_String(); | 
					
						
							|  |  |  |                     return true; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     GetDataByPath(Path: string) { | 
					
						
							|  |  |  |         return this.ScriptDataObject.TreeMap.get(Path); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @ccclass("GameScript") | 
					
						
							|  |  |  | export class GameScript extends Component { | 
					
						
							|  |  |  |     //全局单例类
 | 
					
						
							|  |  |  |     private static instance: GameScript; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private constructor() { | 
					
						
							|  |  |  |         super(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public static getInstance(): GameScript { | 
					
						
							|  |  |  |         if (!GameScript.instance) { | 
					
						
							|  |  |  |             GameScript.instance = new GameScript(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return GameScript.instance; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //Pvf对象
 | 
					
						
							|  |  |  |     PvfData: ScriptData; | 
					
						
							|  |  |  |     //加载完成后的回调函数
 | 
					
						
							|  |  |  |     LoadCallBack: Function; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //初始化Pvf
 | 
					
						
							|  |  |  |     Init(Func: Function) { | 
					
						
							|  |  |  |         //储存回调
 | 
					
						
							|  |  |  |         this.LoadCallBack = Func; | 
					
						
							|  |  |  |         //读取Pvf
 | 
					
						
							|  |  |  |         this.ReadPvf(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //读取原始数据
 | 
					
						
							|  |  |  |     ReadPvf() { | 
					
						
							|  |  |  |         resources.load("Script/Rindro_Script", BufferAsset, (err, content) => { | 
					
						
							|  |  |  |             //转化原始数据为Uint8数组
 | 
					
						
							|  |  |  |             const Buf = new Uint8Array(content.buffer()); | 
					
						
							|  |  |  |             //构造一个 读取流对象
 | 
					
						
							|  |  |  |             const ScriptObj = new ReadStream(Buf); | 
					
						
							|  |  |  |             //读取UUID的长度
 | 
					
						
							|  |  |  |             const UUID_LENGTH = ScriptObj.GetInt(); | 
					
						
							|  |  |  |             //UUID  读 1 - 36位 构造 UTF8 string
 | 
					
						
							|  |  |  |             const UUID = ScriptObj.GetString(UUID_LENGTH); | 
					
						
							|  |  |  |             //版本号
 | 
					
						
							|  |  |  |             const Version = ScriptObj.GetInt(); | 
					
						
							|  |  |  |             // 文件路径数据的大小
 | 
					
						
							|  |  |  |             const AlignedIndexHeaderSize = ScriptObj.GetInt(); | 
					
						
							|  |  |  |             // 解密密钥
 | 
					
						
							|  |  |  |             const IndexHeaderCrc = ScriptObj.GetInt(); | 
					
						
							|  |  |  |             // 文件数量
 | 
					
						
							|  |  |  |             const IndexSize = ScriptObj.GetInt(); | 
					
						
							|  |  |  |             // 存放文件路径数据
 | 
					
						
							|  |  |  |             const Index_Header_Data = ScriptObj.GetBufferByLength(AlignedIndexHeaderSize); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             this.PvfData = new ScriptData( | 
					
						
							|  |  |  |                 Buf, | 
					
						
							|  |  |  |                 UUID_LENGTH, | 
					
						
							|  |  |  |                 UUID, | 
					
						
							|  |  |  |                 Version, | 
					
						
							|  |  |  |                 AlignedIndexHeaderSize, | 
					
						
							|  |  |  |                 IndexHeaderCrc, | 
					
						
							|  |  |  |                 IndexSize, | 
					
						
							|  |  |  |                 Index_Header_Data | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             //建立文件索引树
 | 
					
						
							|  |  |  |             this.PvfData.InitPathTree(); | 
					
						
							|  |  |  |             //可以开始读取PVF数据
 | 
					
						
							|  |  |  |             this.StartInitFlag = true; | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //可以开始读取PVF数据
 | 
					
						
							|  |  |  |     StartInitFlag = false; | 
					
						
							|  |  |  |     //是否已经读取完成
 | 
					
						
							|  |  |  |     InitFlag = false; | 
					
						
							|  |  |  |     Update() { | 
					
						
							|  |  |  |         if (!this.InitFlag && this.StartInitFlag) { | 
					
						
							|  |  |  |             const Flag = this.PvfData.ReadPathTree(); | 
					
						
							|  |  |  |             if (Flag) { | 
					
						
							|  |  |  |                 this.LoadCallBack(); | 
					
						
							|  |  |  |                 this.InitFlag = true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     GetDataByPath(Path: string) { | 
					
						
							|  |  |  |         const Ret = this.PvfData.ScriptDataObject.GetFileData(Path); | 
					
						
							|  |  |  |         if (Ret) return Ret; | 
					
						
							|  |  |  |         else console.error("索引路径不存在: " + Path); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |