Files
DNF_DEV/source/squirrel/SquirrelEx.cpp

267 lines
7.1 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "squirrel/SquirrelEx.h"
#include <dirent.h>
#include <string>
#include <fstream>
#include "SquirrelEx.h"
#include "Asset/Asset_Script.h"
SquirrelEx::SquirrelEx()
{
}
SquirrelEx::~SquirrelEx()
{
}
void SquirrelEx::printfunc(HSQUIRRELVM v, const SQChar *s, ...)
{
va_list vl;
va_start(vl, s);
int len = vsnprintf(NULL, 0, (const char *)s, vl);
if (len <= 0)
{
va_end(vl);
return;
}
char *buf = (char *)malloc(len + 1);
if (!buf)
{
va_end(vl);
return;
}
va_end(vl);
va_start(vl, s);
vsnprintf(buf, len + 1, (const char *)s, vl);
va_end(vl);
SDL_Log("%s", buf);
va_end(vl);
}
void SquirrelEx::errorfunc(HSQUIRRELVM v, const SQChar *s, ...)
{
va_list vl;
va_start(vl, s);
int len = vsnprintf(NULL, 0, (const char *)s, vl);
if (len <= 0)
{
va_end(vl);
return;
}
char *buf = (char *)malloc(len + 1);
if (!buf)
{
va_end(vl);
return;
}
va_end(vl);
va_start(vl, s);
vsnprintf(buf, len + 1, (const char *)s, vl);
va_end(vl);
SDL_LogError(0, "%s", buf);
va_end(vl);
}
bool SquirrelEx::Compilebuffer(std::string Path, std::string Code)
{
if (v == nullptr)
{
SDL_Log("松鼠虚拟机未初始化!");
return false;
}
if (sq_compilebuffer(v, Code.c_str(), Code.length(), Path.c_str(), SQTrue) >= 0)
{
sq_pushroottable(v);
sq_call(v, 1, SQFalse, SQTrue);
sq_pop(v, 1);
return true;
}
return false;
}
void SquirrelEx::Init()
{
// 初始化虚拟机
if (v == nullptr)
v = sq_open(1024); // 栈大小1024
sqstd_seterrorhandlers(v);
sq_pushroottable(v);
sqstd_register_bloblib(v);
sqstd_register_iolib(v);
sqstd_register_systemlib(v);
sqstd_register_mathlib(v);
sqstd_register_stringlib(v);
sq_setprintfunc(v, printfunc, errorfunc);
#ifdef __SWITCH__
#else
// 获取工作目录 switch 不允许)
WorkPath = SDL_GetBasePath();
FILE *file1 = fopen("DevMode.ini", "rb");
if (file1)
{
sq_enabledebuginfo(v, true);
dbg = sqdbg_attach_debugger(v);
sqdbg_listen_socket(dbg, 2222);
fclose(file1);
}
#endif
// 加载脚本
LoadLocalScript();
}
void SquirrelEx::RequestNetScript(std::string Ip, std::string Port)
{
// char *response = NULL;
// size_t response_size = 0;
// std::string url = "http://" + Ip + ":" + Port + "/get/getadvertisement?key=Files"; // 确保协议正确
// int result = http_get(url.c_str(), &response, &response_size);
// if (result == 0 && response != NULL && response_size > 0)
// {
// std::string response_str(response, response_size);
// free(response); // 释放内存
// nlohmann::json ex1 = nlohmann::json::parse(response_str);
// for (const auto &[key, value] : ex1.items())
// {
// std::string key_str = key;
// std::string value_str = value;
// bool Flag = Compilebuffer(key_str, value_str);
// if (!Flag)
// {
// SDL_Log("Squirrel Compilebuffer Error! FileName: %s", key_str.c_str());
// }
// }
// }
// else
// {
// if (response)
// free(response);
// }
}
void SquirrelEx::LoadLocalScript()
{
std::vector<std::string> lines;
std::ifstream file("sqr/SquirrelFileConfig.cfg");
if (file.is_open())
{
std::string line;
while (std::getline(file, line))
{
lines.push_back(line);
}
file.close();
}
else
{
SDL_LogError(0, "配置文件未找到,请检查项目目录 sqr/SquirrelFileConfig.cfg 文件是否存在");
}
for (const auto &line : lines)
{
std::string clean_line = line;
// 移除换行符和回车符
clean_line.erase(std::remove(clean_line.begin(), clean_line.end(), '\n'), clean_line.end());
clean_line.erase(std::remove(clean_line.begin(), clean_line.end(), '\r'), clean_line.end());
if (line.find(".nut") == std::string::npos)
continue;
std::string RegistPath = "sqr/" + clean_line;
#ifndef __SWITCH__
std::replace(RegistPath.begin(), RegistPath.end(), '/', '\\');
RegistPath = WorkPath + RegistPath;
_scriptmap[RegistPath] = Tool_get_file_size(RegistPath);
#endif
if (!SQ_SUCCEEDED(sqstd_dofile(v, (SQChar *)(RegistPath.c_str()), SQFalse, SQTrue)))
{
SDL_LogError(0, "脚本文件未找到,请检查项目目录 %s 文件是否存在", RegistPath.c_str());
}
{
// std::ifstream F;
// F.open((RegistPath).c_str(), std::ios::in | std::ios::binary);
// if (F.is_open())
// {
// std::stringstream ContentStringStream;
// ContentStringStream << F.rdbuf();
// std::string ContentString(ContentStringStream.str());
// std::string RealContentString = ContentString;
// if (RealContentString.length() > 0)
// {
// if (SQ_SUCCEEDED(sq_compilebuffer(v, (SQChar *)(RealContentString.c_str()), RealContentString.length(), (SQChar *)(RegistPath.c_str()), true)))
// {
// sq_pushroottable(v);
// sq_call(v, 1, 1, 1);
// sq_pop(v, 1);
// }
// }
// }
// else
// {
// SDL_LogError(0, "脚本文件未找到,请检查项目目录 %s 文件是否存在", RegistPath.c_str());
// }
// F.close();
}
}
}
void SquirrelEx::Run()
{
// 载入main函数
SQInteger top = sq_gettop(v); // saves the stack size before the call
sq_pushroottable(v); // pushes the global table
sq_pushstring(v, _SC("main"), -1);
if (SQ_SUCCEEDED(sq_get(v, -2)))
{ // gets the field 'foo' from the global table
sq_pushroottable(v); // push the 'this' (in this case is the global table)
sq_call(v, 1, SQFalse, SQTrue); // calls the function
}
sq_settop(v, top); // restores the original stack size
}
void SquirrelEx::Update(float Dt)
{
#ifdef __SWITCH__
#else
sqdbg_frame(dbg);
// 热重载
if (HotReload)
{
for (auto &script : _scriptmap)
{
std::string path = script.first;
int value = script.second;
int newvalue = Tool_get_file_size(path);
if (value != newvalue)
{
if (SQ_SUCCEEDED(sqstd_dofile(v, (SQChar *)(path.c_str()), SQFalse, SQTrue)))
{
SDL_Log("脚本文件热重载成功 %s", path.c_str());
_scriptmap[path] = newvalue;
}
else
{
SDL_Log("脚本文件热重载失败 %s", path.c_str());
}
}
}
}
#endif
}
void SquirrelEx::Clean()
{
sq_close(v);
v = nullptr;
}
HSQUIRRELVM SquirrelEx::GetSquirrelVM()
{
return v;
}