#include "lua.h" #include "lua/lua.hpp" #include "lua.wrappers.h" #include "lua.debug.h" #include "jfile.h" #include "log.h" #include #include 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; } 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 files = file_listdir(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(), lua_tostring(L, -1)); 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", lua_tostring(L, -1)); 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", lua_tostring(L, -1)); 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", lua_tostring(L, -1)); 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); //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"); is_playing = debug::call_and_handle_exceptions(L); } void update() { if (!update_exists) return; lua_getglobal(L, "mini"); lua_getfield(L, -1, "update"); is_playing = debug::call_and_handle_exceptions(L); } } } }