Files
mini/source/mini/lua/lua.cpp
T
JailDoctor 49cb0af228 VERSIÓ 1.5.6:
- [FIX] Acallats warnings en findloader de lua
- [FIX] Acallats alguns 'Illegal music handle' innecesaris
- [NEW] Ara detecta que no s'ha conectat al debuger de vscode i trau els missatges per consola com abans
- [NEW] Missatges de error més clars
- [NEW] Ara també trau els missatges de debug per consola en la versió release
2026-05-13 11:57:08 +02:00

223 lines
7.3 KiB
C++

#include "lua.h"
#include "lua.wrappers.h"
#include "lua.debug.h"
#include "lua.utils.h"
#include "external/lua/lua.hpp"
#include "mini/file/file.h"
#include "other/log.h"
#include <algorithm>
#include <unistd.h>
namespace mini
{
namespace lua
{
lua_State *L;
bool is_playing = false;
bool init_exists = false;
bool update_exists = false;
bool running() {
debug::process_commands(L);
return is_playing;
}
std::string assemble_error_message(const char *lua_error_string) {
std::string error = lua_error_string; // tu cadena original
std::string nombre;
int linea = 0;
std::string mensaje;
// 1. Buscar el nombre entre comillas
auto p1 = error.find('"');
auto p2 = error.find('"', p1 + 1);
if (p1 != std::string::npos && p2 != std::string::npos)
nombre = error.substr(p1 + 1, p2 - (p1 + 1));
// 2. Buscar la línea después de "]:"
auto p3 = error.find("]:", p2);
if (p3 != std::string::npos) {
size_t start = p3 + 2;
linea = std::stoi(error.substr(start));
}
// 3. Buscar el mensaje después del siguiente ':'
auto p4 = error.find(':', p3 + 2);
if (p4 != std::string::npos)
mensaje = error.substr(p4 + 2); // saltar ": "
// Ahora tienes:
// nombre → "main"
// linea → 18
// mensaje → "unexpected symbol near '+'"
return debug::chunkToPath(nombre) + ":" + std::to_string(linea) + ":" + mensaje;
}
int MiniLoader(lua_State *L) {
const char *name = luaL_checkstring(L, 1);
// 1. Convertir puntos en barras
std::string path(name);
std::string regpath(name);
std::replace(path.begin(), path.end(), '.', '/');
// 2. Detectar comodín "/*"
bool load_all = false;
if (path.size() >= 2 && path.substr(path.size()-2) == "/*") {
load_all = true;
path = path.substr(0, path.size()-2); // quitar "/*"
regpath = regpath.substr(0, regpath.size()-2); // quitar "/*"
}
if (load_all) {
std::vector<std::string> files = file::listresourcesdir(path.c_str(), "lua");
// Ejecutar todos los módulos
for (auto &f : files) {
std::string fullpath = path + "/" + f;
std::string registerpath = std::string(regpath + "." + f.substr(0,f.size()-4));
int size;
char* buffer = file::getfilebuffer(fullpath.c_str(), size);
if (!buffer) continue;
if (luaL_loadbuffer(L, buffer, size, registerpath.c_str()) == LUA_OK) {
lua_pcall(L, 0, 0, 0); // ejecutar módulo, sin devolver nada
lua_getglobal(L, "package");
lua_getfield(L, -1, "loaded");
lua_pushboolean(L, 1);
lua_setfield(L, -2, registerpath.c_str());
lua_pop(L, 2);
} else {
log_msg(LOG_LUALD, "Error cargando %s: %s\n", fullpath.c_str(), assemble_error_message(lua_tostring(L, -1)).c_str());
lua_pop(L, 1);
}
free(buffer);
}
// Devolver un loader vacío
lua_pushcfunction(L, [](lua_State* L) -> int {
lua_pushboolean(L, 1); // require devuelve true
return 1;
});
return 1;
}
// 3. Cargar un único archivo
std::string filename = path + ".lua";
int size;
char* buffer = file::getfilebuffer(filename.c_str(), size);
if (!buffer) {
lua_pushnil(L);
return 1;
}
if (luaL_loadbuffer(L, buffer, size, name)) {
log_msg(LOG_LUALD, "%s\n", assemble_error_message(lua_tostring(L, -1)).c_str());
lua_pop(L, 1);
free(buffer);
lua_pushnil(L);
return 1;
}
free(buffer);
return 1;
}
void init(const char *main_lua_file) {
L = luaL_newstate();
luaL_openlibs(L);
push_functions(L);
lua_register(L, "mini_loader", MiniLoader);
luaL_dostring(L, "table.insert(package.searchers,2,mini_loader)\n");
int size;
char* buffer = file::getfilebuffer(main_lua_file, size);
if (luaL_loadbuffer(L, buffer, size, "main")) {
log_msg(LOG_LUALD, "%s\n", assemble_error_message(lua_tostring(L, -1)).c_str());
lua_pop(L,1);
return;
}
free(buffer);
if (lua_pcall(L,0, LUA_MULTRET, 0)) {
//luaL_traceback(L, L, NULL, 1);
log_msg(LOG_LUART, "%s\n", assemble_error_message(lua_tostring(L, -1)).c_str());
lua_pop(L,1);
return;
}
// Check if _init and _update exist
lua_getglobal(L, "mini");
lua_getfield(L, -1, "init");
if (lua_isfunction(L,-1)) init_exists = true;
lua_pop(L,1);
lua_pop(L,1);
lua_getglobal(L, "mini");
lua_getfield(L, -1, "update");
if (lua_isfunction(L,-1)) update_exists = true;
lua_pop(L,1);
lua_pop(L,1);
debug::init(L);
//std::thread(debugCommandThread).detach();
//printf("stdin isatty: %d\n", isatty(0));
is_playing = true;
}
void quit() {
if (!is_playing) return;
is_playing = false;
lua_close(L);
}
void cleanup() {
debug::kill_thread();
}
namespace callbacks
{
void init() {
if (!init_exists) return;
debug::process_commands(L);
lua_getglobal(L, "mini");
lua_getfield(L, -1, "init");
if (debug::is_enabled()) {
is_playing = debug::call_and_handle_exceptions(L);
} else {
if (lua_pcall(L, 0, 0, 0)) {
log_msg(LOG_LUART, "%s\n", assemble_error_message(lua_tostring(L, -1)).c_str());
lua_pop(L,1);
is_playing = false;
}
}
}
void update() {
if (!update_exists) return;
lua_getglobal(L, "mini");
lua_getfield(L, -1, "update");
if (debug::is_enabled()) {
is_playing = debug::call_and_handle_exceptions(L);
} else {
if (lua_pcall(L, 0, 0, 0)) {
log_msg(LOG_LUART, "%s\n", assemble_error_message(lua_tostring(L, -1)).c_str());
lua_pop(L,1);
is_playing = false;
}
}
}
}
}
}