#pragma once #include "IO_Ex.hpp" #include #include #include #include "squirrel.h" #include "sqstdaux.h" #include "sqstdblob.h" #include "sqstdio.h" #include "sqstdmath.h" #include "sqstdstring.h" #include "sqstdsystem.h" class PVF_IO : public IO_Ex { struct PvfFileInfo { int ROffset; int Cr32; int Length; bool DecodeFlag = false; }; private: int StartPos = 0; std::mapFileInfo; std::mapBinStringM; std::mapLoadStringM; public: // 构造函数 PVF_IO(const char* defaultFilename = "Script.pvf") : IO_Ex(defaultFilename) {} // 析构函数,在对象销毁时,基类(fstream)的析构函数会自动被调用,一般不需要额外特殊处理 ~PVF_IO() {} // 显式删除拷贝构造函数,禁止拷贝操作 PVF_IO(const PVF_IO&) = delete; // 也可以考虑同时删除拷贝赋值运算符,保持一致的语义,避免误用 PVF_IO& operator=(const PVF_IO&) = delete; public: void Init() { //读取头建立树 InitHeader(); //读取bin文件 InitBin(); //读取LoadString InitLoadString(); } void InitHeader() { //读取UUID的长度 int UUID_LENGTH = GetInt(); //UUID 读 1 - 36位 构造 UTF8 string std::string UUID = GetString(UUID_LENGTH); //版本号 int Version = GetInt(); // 文件路径数据的大小 int AlignedIndexHeaderSize = GetInt(); // 解密密钥 int IndexHeaderCrc = GetInt(); // 文件数量 int IndexSize = GetInt(); //文件起始位置 int FristPos = tellg(); //std::cout << "UUID_LENGTH: " << UUID_LENGTH << std::endl; //std::cout << "UUID: " << UUID << std::endl; //std::cout << "Version: " << Version << std::endl; //std::cout << "AlignedIndexHeaderSize: " << AlignedIndexHeaderSize << std::endl; //std::cout << "IndexHeaderCrc: " << IndexHeaderCrc << std::endl; //std::cout << "IndexSize: " << IndexSize << std::endl; CrcDecode(AlignedIndexHeaderSize, IndexHeaderCrc); int CurrPos = 0; StartPos = AlignedIndexHeaderSize + 56; //建立pvf文件索引表 for (size_t i = 0; i < IndexSize; i++) { seek(FristPos + CurrPos); int FileNumber = GetInt(); int FilePathLength = GetInt(); std::string FileName = tolower(GetString(FilePathLength)); int FileLength = GetInt(); int Cre32 = GetInt(); int RelativeOffset = GetInt(); if (FileLength > 0) { int RealFileLength = (FileLength + 3) & 4294967292; PvfFileInfo Info; Info.ROffset = RelativeOffset; Info.Cr32 = Cre32; Info.Length = RealFileLength; Info.DecodeFlag = false; FileInfo[FileName] = Info; } CurrPos += 20; CurrPos += FilePathLength; } } void InitBin() { if (FileInfo.count("stringtable.bin") == 0) { std::cout << "bin文件不存在" << std::endl; return; } PvfFileInfo BinInfo = FileInfo["stringtable.bin"]; seek(StartPos + BinInfo.ROffset); CrcDecode(BinInfo.Length, BinInfo.Cr32); seek(StartPos + BinInfo.ROffset); int FileHPos = tellg(); int Count = GetInt(); int CurrentIndex = 0; for (int i = 0; i < Count; i++) { seek(FileHPos + CurrentIndex * 4 + 4); int StartPos = GetInt(); int EndPos = GetInt(); int Len = EndPos - StartPos; seek(FileHPos + StartPos + 4); std::string Str = GetString(Len); BinStringM[CurrentIndex] = Str; CurrentIndex++; } } void InitLoadString() { if (FileInfo.count("n_string.lst") == 0) { std::cout << "LoadString文件不存在" << std::endl; return; } PvfFileInfo Info = FileInfo["n_string.lst"]; seek(StartPos + Info.ROffset); CrcDecode(Info.Length, Info.Cr32); seek(StartPos + Info.ROffset); int FileHPos = tellg(); int Flag = GetShort(); int i = 2; while (i < Info.Length) { if ((Info.Length - i) >= 10) { seek(FileHPos + i + 6); int FindKey = GetInt(); std::string Key = GetBinString(FindKey); if (Key.length() > 0) { PvfFileInfo* FileInfo = GetFileInfo(Key); if (FileInfo == nullptr)continue; seek(StartPos + FileInfo->ROffset); CrcDecode(FileInfo->Length, FileInfo->Cr32); seek(StartPos + FileInfo->ROffset); std::string Str = GetString(FileInfo->Length); std::vector StrArr = split(Str, "\r\n"); for (auto it = StrArr.begin(); it != StrArr.end(); ++it) { std::string strobj = *it; if (strobj.find(">") != std::string::npos) { std::vector strobjarr = split(strobj, ">"); if (strobjarr.size() > 1) LoadStringM[strobjarr[0]] = strobjarr[1]; } } } } else break; i += 10; } } public: std::string GetBinString(int Key) { if (BinStringM.count(Key))return BinStringM[Key]; return ""; } std::string GetLoadString(std::string Key) { if (LoadStringM.count(Key))return LoadStringM[Key]; return ""; } PvfFileInfo* GetFileInfo(std::string path) { path = tolower(path); if (FileInfo.count(path))return &FileInfo[path]; return nullptr; } void LoadFileToBlob(HSQUIRRELVM v ,std::string path, SQUserPointer blobp) { path = tolower(path); if (FileInfo.count(path)) { seek(StartPos + FileInfo[path].ROffset); if (FileInfo[path].DecodeFlag == false) { CrcDecode(FileInfo[path].Length, FileInfo[path].Cr32); seek(StartPos + FileInfo[path].ROffset); FileInfo[path].DecodeFlag = true; } read((char*)blobp, FileInfo[path].Length); return; } sq_pushnull(v); return; } };