DP_S/include/PVF_IO.hpp

226 lines
6.6 KiB
C++
Raw Permalink Normal View History

2025-03-27 20:24:19 +08:00
#pragma once
#include "IO_Ex.hpp"
#include <iostream>
#include <map>
#include <cstdint>
#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::map<std::string, PvfFileInfo> FileInfo;
std::map<int, std::string> BinStringM;
std::map<std::string, std::map<std::string, std::string>> LoadStringM;
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();
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);
std::string Type = tolower(Key.substr(0, Key.find("/")));
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 = GetStringNormal(FileInfo->Length);
std::vector<std::string> StrArr = split(Str, "\n");
for (auto it = StrArr.begin(); it != StrArr.end(); ++it)
{
std::string strobj = *it;
if (strobj.find(">") != std::string::npos)
{
std::vector<std::string> strobjarr = split(strobj, ">");
if (strobjarr.size() > 1)
{
LoadStringM[Type][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 Type, std::string Key)
{
if (LoadStringM.count(Type) && LoadStringM[Type].count(Key))
return LoadStringM[Type][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;
}
};