#pragma once #include "DNFTOOL.hpp" #include "zlib.h" #include #include #include #include "json.hpp" using json = nlohmann::json; // 定义互斥锁和需要重载的文件列表 static std::mutex reloadListMutex; static std::vector 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(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& 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 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(lpParam); std::string ReloadPath = Info->Path; delete Info; std::unordered_map 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 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);//热重载逻辑(保持主线程加载) }