spicetools/script/lib.cpp

156 lines
4.3 KiB
C++

#include "lib.h"
#include <thread>
#include <external/LuaBridge.h>
#include "util/logging.h"
#include "util/time.h"
#include "instance.h"
#include "api/analogs.h"
#include "api/buttons.h"
#include "api/capture.h"
#include "api/card.h"
#include "api/coin.h"
#include "api/control.h"
#include "api/drs.h"
#include "api/iidx.h"
#include "api/info.h"
#include "api/keypads.h"
#include "api/lcd.h"
#include "api/lights.h"
#include "api/memory.h"
#include "api/touch.h"
using namespace luabridge;
extern "C" const luaL_Reg *base_funcs_sandbox;
namespace script {
LUAMOD_API int luaopen_base_sandbox(lua_State *L) {
lua_pushglobaltable(L);
luaL_setfuncs(L, base_funcs_sandbox, 0);
lua_pushvalue(L, -1);
lua_setfield(L, -2, LUA_GNAME);
lua_pushliteral(L, LUA_VERSION);
lua_setfield(L, -2, "_VERSION");
return 1;
}
static const luaL_Reg LUA_LIBRARIES[] = {
{"_G", luaopen_base},
{LUA_LOADLIBNAME, luaopen_package},
{LUA_COLIBNAME, luaopen_coroutine},
{LUA_TABLIBNAME, luaopen_table},
{LUA_IOLIBNAME, luaopen_io},
{LUA_OSLIBNAME, luaopen_os},
{LUA_STRLIBNAME, luaopen_string},
{LUA_MATHLIBNAME, luaopen_math},
{LUA_UTF8LIBNAME, luaopen_utf8},
{LUA_DBLIBNAME, luaopen_debug},
#if defined(LUA_COMPAT_BITLIB)
{LUA_BITLIBNAME, luaopen_bit32},
#endif
{NULL, NULL}
};
static const luaL_Reg LUA_SANDBOX[] = {
{"_G", luaopen_base_sandbox},
{LUA_COLIBNAME, luaopen_coroutine},
{LUA_TABLIBNAME, luaopen_table},
{LUA_STRLIBNAME, luaopen_string},
{LUA_MATHLIBNAME, luaopen_math},
{LUA_UTF8LIBNAME, luaopen_utf8},
#if defined(LUA_COMPAT_BITLIB)
{LUA_BITLIBNAME, luaopen_bit32},
#endif
{NULL, NULL}
};
LuaRef require_sandbox(const std::string &path, lua_State *L) {
luaL_error(L, "require not available in sandbox");
return LuaRef(L);
}
void sleep(double duration) {
auto instance = script::INSTANCE;
double cur_slept = 0.0;
while (instance->is_running() && cur_slept < duration) {
auto diff = std::min(0.02, duration);
std::this_thread::sleep_for(std::chrono::microseconds(
(uint64_t) (diff * 1000000ULL)));
cur_slept += diff;
}
}
double time() {
return get_performance_seconds();
}
void yield() {
std::this_thread::yield();
}
void msgbox(const std::string &s) {
MessageBoxA(nullptr, s.c_str(), "Script", 0);
}
void log_fatal_(const std::string &s) {
log_fatal("script", "{}", s);
}
void log_warning_(const std::string &s) {
log_warning("script", "{}", s);
}
void log_info_(const std::string &s) {
log_info("script", "{}", s);
}
void log_misc_(const std::string &s) {
log_misc("script", "{}", s);
}
uint16_t GetAsyncKeyState_(const int vKey) {
return GetAsyncKeyState(vKey);
}
void load_libs(lua_State *L, bool sandbox) {
// load STD libs
for (const luaL_Reg *lib = sandbox ? LUA_SANDBOX : LUA_LIBRARIES; lib->func; ++lib) {
luaL_requiref(L, lib->name, lib->func, 1);
lua_pop(L, 1);
}
// add base functions
auto G = getGlobalNamespace(L);
G.addFunction("sleep", sleep);
G.addFunction("time", time);
G.addFunction("yield", yield);
G.addFunction("msgbox", msgbox);
G.addFunction("log_fatal", log_fatal_);
G.addFunction("log_warning", log_warning_);
G.addFunction("log_info", log_info_);
G.addFunction("log_misc", log_misc_);
if (sandbox) {
G.addFunction("require", require_sandbox);
} else {
G.addFunction("GetAsyncKeyState", GetAsyncKeyState_);
}
// add API modules
api::analogs::init(L);
api::buttons::init(L);
api::capture::init(L);
api::card::init(L);
api::coin::init(L);
api::control::init(L);
api::drs::init(L);
api::iidx::init(L);
api::info::init(L);
api::keypads::init(L);
api::lcd::init(L);
api::lights::init(L);
api::memory::init(L, sandbox);
api::touch::init(L);
}
}