152 lines
4.7 KiB
C++
152 lines
4.7 KiB
C++
#pragma once
|
|
#include "DNFTOOL.hpp"
|
|
|
|
#include "zlib.h"
|
|
#include <ctime>
|
|
#include <sstream>
|
|
#include <chrono>
|
|
#include "json.hpp"
|
|
|
|
using json = nlohmann::json;
|
|
|
|
|
|
|
|
// 定义互斥锁和需要重载的文件列表
|
|
static std::mutex reloadListMutex;
|
|
static std::vector<std::string> reloadFileList;
|
|
struct AutoReloadSt
|
|
{
|
|
std::string Path;
|
|
};
|
|
std::string calculateMD5(const std::string& filePath)
|
|
{
|
|
std::ifstream file(filePath, std::ios::binary | std::ios::ate);
|
|
if (!file)
|
|
{
|
|
return "";
|
|
}
|
|
std::streampos size = file.tellg();
|
|
file.seekg(0, std::ios::beg);
|
|
|
|
unsigned char buffer[16];
|
|
MD5_CTX md5Context;
|
|
MD5_Init(&md5Context);
|
|
|
|
while (file.read(reinterpret_cast<char*>(buffer), sizeof(buffer)))
|
|
{
|
|
MD5_Update(&md5Context, buffer, file.gcount());
|
|
}
|
|
|
|
MD5_Final(buffer, &md5Context);
|
|
|
|
file.close();
|
|
return LenheartBase::CBASE64::encode((char*)buffer);
|
|
}
|
|
void processDirectory(const std::string& directoryPath, std::unordered_map<std::string, std::string>& fileMD5Map) {
|
|
std::string searchPath = directoryPath + "\\*";
|
|
WIN32_FIND_DATAA findData;
|
|
HANDLE hFind = FindFirstFileA(searchPath.c_str(), &findData);
|
|
|
|
if (hFind != INVALID_HANDLE_VALUE) {
|
|
do {
|
|
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
|
if (std::string(findData.cFileName) != "." && std::string(findData.cFileName) != "..") {
|
|
std::string subDirPath = directoryPath + "\\" + findData.cFileName;
|
|
processDirectory(subDirPath, fileMD5Map);
|
|
}
|
|
}
|
|
else {
|
|
std::string filePath = directoryPath + "\\" + findData.cFileName;
|
|
if (filePath.find(".nut") == std::string::npos)continue;
|
|
std::string currentMD5 = calculateMD5(filePath);
|
|
|
|
if (fileMD5Map.find(filePath) != fileMD5Map.end()) {
|
|
if (fileMD5Map[filePath] != currentMD5) {
|
|
fileMD5Map[filePath] = currentMD5;
|
|
// 加锁将需要重载的文件添加到列表中
|
|
std::lock_guard<std::mutex> lock(reloadListMutex);
|
|
reloadFileList.push_back(filePath);
|
|
}
|
|
}
|
|
else {
|
|
fileMD5Map[filePath] = currentMD5;
|
|
}
|
|
}
|
|
} while (FindNextFileA(hFind, &findData) != 0);
|
|
FindClose(hFind);
|
|
}
|
|
else {
|
|
std::cerr << "无法打开目录:" << directoryPath << std::endl;
|
|
}
|
|
}
|
|
static DWORD WINAPI AutoReloadThread(LPVOID lpParam)
|
|
{
|
|
AutoReloadSt* Info = static_cast<AutoReloadSt*>(lpParam);
|
|
std::string ReloadPath = Info->Path;
|
|
delete Info;
|
|
|
|
std::unordered_map<std::string, std::string> fileMD5Map;
|
|
while (true)
|
|
{
|
|
processDirectory(ReloadPath, fileMD5Map);
|
|
Sleep(10);
|
|
}
|
|
return 0;
|
|
}
|
|
static SQInteger AutoReload(HSQUIRRELVM v) {
|
|
const SQChar* value;
|
|
Sq_getstring((HSQUIRRELVM)v, 2, &value);
|
|
char* vOutPutText = DNFTOOL::SquirrelU2W(value);
|
|
std::string ReloadPath = vOutPutText;
|
|
delete[]vOutPutText;
|
|
//构造路径结构体传递
|
|
AutoReloadSt* Info = new AutoReloadSt();
|
|
Info->Path = ReloadPath;
|
|
|
|
DWORD threadID;
|
|
HANDLE Thand = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)AutoReloadThread, Info, 0, &threadID);
|
|
return 0;
|
|
}
|
|
static SQInteger ReloadLogic(HSQUIRRELVM v) {
|
|
// 加锁获取需要重载的文件列表
|
|
std::lock_guard<std::mutex> lock(reloadListMutex);
|
|
for (const auto& file : reloadFileList) {
|
|
std::string line = file;
|
|
|
|
std::string ContentString = "";
|
|
std::fstream F;
|
|
F.open((line).c_str(), std::ios::in);
|
|
if (F.is_open()) {
|
|
std::stringstream ContentStringStream;
|
|
ContentStringStream << F.rdbuf();
|
|
ContentString = (ContentStringStream.str());
|
|
F.close();
|
|
}
|
|
|
|
std::wstring filename = DNFTOOL::charTowchar_t((char*)line.c_str(), line.length());
|
|
std::wstring str = DNFTOOL::charTowchar_t((char*)ContentString.c_str(), ContentString.length());
|
|
if (sq_mycompilebuffer(v, str.c_str(), str.length(), filename.c_str(), true) >= 0) {
|
|
Sq_pushroottable(v);
|
|
Sq_call(v, 1, SQTrue, SQTrue);
|
|
Sq_pop(v, 1);
|
|
}
|
|
}
|
|
// 清空列表
|
|
reloadFileList.clear();
|
|
return 0;
|
|
}
|
|
|
|
static void RegisterNutApi_System(wchar_t* funcName, SQFUNCTION funcAddr)
|
|
{
|
|
HSQUIRRELVM v = *(HSQUIRRELVM*)0x1AF3544;
|
|
Sq_pushroottable(v);
|
|
Sq_pushstring(v, funcName, -1);
|
|
RealSqNewClosure(v, funcAddr, 0);
|
|
SQNewSlot(v, -3, SQFalse);
|
|
SQPopTop(v);
|
|
}
|
|
|
|
void R_Register_System() {
|
|
RegisterNutApi_System(L"Sq_AutoReload", AutoReload);//开启热重载
|
|
RegisterNutApi_System(L"Sq_ReloadLogic", ReloadLogic);//热重载逻辑(保持主线程加载)
|
|
} |