voxelcore/src/logic/scripting/scripting_functional.cpp
2025-06-28 11:46:10 +03:00

194 lines
5.9 KiB
C++

#include "scripting_functional.hpp"
#include "coders/json.hpp"
#include "debug/Logger.hpp"
#include "util/stringutil.hpp"
#include "util/type_helpers.hpp"
#include "lua/lua_engine.hpp"
using namespace scripting;
static debug::Logger logger("scripting_func");
runnable scripting::create_runnable(
const scriptenv& env, const std::string& src, const std::string& file
) {
auto L = lua::get_main_state();
try {
lua::loadbuffer(L, *env, src, file);
return lua::create_runnable(L);
} catch (const lua::luaerror& err) {
logger.error() << err.what();
return []() {};
}
}
static lua::State* process_callback(
const scriptenv& env, const std::string& src, const std::string& file
) {
auto L = lua::get_main_state();
try {
if (lua::eval(L, *env, src, file) != 0) {
return L;
}
} catch (lua::luaerror& err) {
logger.error() << err.what();
}
return nullptr;
}
key_handler scripting::create_key_handler(
const scriptenv& env, const std::string& src, const std::string& file
) {
return [=](int code) {
if (auto L = process_callback(env, src, file)) {
int top = lua::gettop(L);
if (lua::isfunction(L, -1)) {
lua::pushinteger(L, code);
lua::call_nothrow(L, 1);
}
int returned = lua::gettop(L) - top + 1;
if (returned) {
bool x = lua::toboolean(L, -1);
lua::pop(L, returned);
return x;
}
return false;
}
return false;
};
}
template<typename T, int(pushfunc)(lua::State*, remove_const_ref_if_primitive_t<const T&>)>
std::function<void(const T&)> create_consumer(
const scriptenv& env, const std::string& src, const std::string& file
) {
return [=](const T& x) {
if (auto L = process_callback(env, src, file)) {
pushfunc(L, x);
lua::call_nothrow(L, 1);
}
};
}
wstringconsumer scripting::create_wstring_consumer(
const scriptenv& env, const std::string& src, const std::string& file
) {
return create_consumer<std::wstring, lua::pushwstring>(env, src, file);
}
stringconsumer scripting::create_string_consumer(
const scriptenv& env, const std::string& src, const std::string& file
) {
return create_consumer<std::string, lua::pushstring>(env, src, file);
}
boolconsumer scripting::create_bool_consumer(
const scriptenv& env, const std::string& src, const std::string& file
) {
return create_consumer<bool, lua::pushboolean>(env, src, file);
}
doubleconsumer scripting::create_number_consumer(
const scriptenv& env, const std::string& src, const std::string& file
) {
return create_consumer<number_t, lua::pushnumber>(env, src, file);
}
template <typename T, T(tovalueFunc)(lua::State*, int)>
std::function<T()> create_supplier(
const scriptenv& env, const std::string& src, const std::string& file
) {
return [=]() {
if (auto L = process_callback(env, src, file)) {
if (lua::isfunction(L, -1)) {
lua::call_nothrow(L, 0);
}
auto str = tovalueFunc(L, -1);
lua::pop(L);
return str;
}
return T {};
};
}
wstringsupplier scripting::create_wstring_supplier(
const scriptenv& env, const std::string& src, const std::string& file
) {
return create_supplier<std::wstring, lua::require_wstring>(env, src, file);
}
boolsupplier scripting::create_bool_supplier(
const scriptenv& env, const std::string& src, const std::string& file
) {
return create_supplier<bool, lua::toboolean>(env, src, file);
}
doublesupplier scripting::create_number_supplier(
const scriptenv& env, const std::string& src, const std::string& file
) {
return create_supplier<number_t, lua::tonumber>(env, src, file);
}
wstringchecker scripting::create_wstring_validator(
const scriptenv& env, const std::string& src, const std::string& file
) {
return [=](const std::wstring& x) {
if (auto L = process_callback(env, src, file)) {
lua::pushwstring(L, x);
if (lua::call_nothrow(L, 1)) return lua::toboolean(L, -1);
}
return false;
};
}
int_array_consumer scripting::create_int_array_consumer(
const scriptenv& env, const std::string& src, const std::string& file
) {
return [=](const int arr[], size_t len) {
if (auto L = process_callback(env, src, file)) {
for (uint i = 0; i < len; i++) {
lua::pushinteger(L, arr[i]);
}
lua::call_nothrow(L, len);
}
};
}
vec2supplier scripting::create_vec2_supplier(
const scriptenv& env, const std::string& src, const std::string& file
) {
return [=]() {
if (auto L = process_callback(env, src, file)) {
if (lua::isfunction(L, -1)) {
lua::call_nothrow(L, 0);
}
auto y = lua::tonumber(L, -1);
lua::pop(L);
auto x = lua::tonumber(L, -1);
lua::pop(L);
return glm::vec2(x, y);
}
return glm::vec2(0, 0);
};
}
value_to_string_func scripting::create_tostring(
const scriptenv& env, const std::string& src, const std::string& file
) {
auto L = lua::get_main_state();
try {
lua::loadbuffer(L, *env, src, file);
lua::call(L, 0, 1);
auto func = lua::create_lambda(L);
return [func](const dv::value& value) {
auto result = func({value});
return json::stringify(result, true, " ");
};
} catch (const lua::luaerror& err) {
logger.error() << err.what();
return [](const auto& value) {
return json::stringify(value, true, " ");
};
}
}