Merge pull request #243 from MihailRis/scripting-fix

Scripting fix
This commit is contained in:
MihailRis 2024-06-11 14:05:34 +03:00 committed by GitHub
commit 05410aa150
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
32 changed files with 1876 additions and 2038 deletions

View File

@ -13,6 +13,10 @@ Container::Container(glm::vec2 size) : UINode(size) {
setColor(glm::vec4());
}
Container::~Container() {
Container::clear();
}
std::shared_ptr<UINode> Container::getAt(glm::vec2 pos, std::shared_ptr<UINode> self) {
if (!isInteractive() || !isEnabled()) {
return nullptr;

View File

@ -17,6 +17,7 @@ namespace gui {
bool scrollable = true;
public:
Container(glm::vec2 size);
virtual ~Container();
virtual void act(float delta) override;
virtual void drawBackground(const DrawContext* pctx, Assets* assets);

View File

@ -1,501 +0,0 @@
#include "LuaState.hpp"
#include "lua_util.hpp"
#include "api_lua.hpp"
#include "../../../debug/Logger.hpp"
#include "../../../util/stringutil.hpp"
#include <iomanip>
#include <iostream>
inline std::string LAMBDAS_TABLE = "$L";
static debug::Logger logger("lua-state");
using namespace lua;
namespace scripting {
extern LuaState* state;
}
luaerror::luaerror(const std::string& message) : std::runtime_error(message) {
}
void LuaState::removeLibFuncs(const char* libname, const char* funcs[]) {
if (getglobal(libname)) {
for (uint i = 0; funcs[i]; i++) {
pushnil();
setfield(funcs[i], -2);
}
}
}
LuaState::LuaState() {
logger.info() << LUA_VERSION;
logger.info() << LUAJIT_VERSION;
L = luaL_newstate();
if (L == nullptr) {
throw luaerror("could not to initialize Lua");
}
// Allowed standard libraries
luaopen_base(L);
luaopen_math(L);
luaopen_string(L);
luaopen_table(L);
luaopen_debug(L);
luaopen_jit(L);
luaopen_bit(L);
luaopen_os(L);
const char* removed_os[] {
"execute",
"exit",
"remove",
"rename",
"setlocale",
"tmpname",
nullptr
};
removeLibFuncs("os", removed_os);
createLibs();
lua_pushvalue(L, LUA_GLOBALSINDEX);
setglobal(envName(0));
lua_createtable(L, 0, 0);
setglobal(LAMBDAS_TABLE);
}
std::string LuaState::envName(int env) {
return "_ENV"+util::mangleid(env);
}
LuaState::~LuaState() {
lua_close(L);
}
void LuaState::logError(const std::string& text) {
logger.error() << text;
}
void LuaState::addfunc(const std::string& name, lua_CFunction func) {
lua_pushcfunction(L, func);
lua_setglobal(L, name.c_str());
}
bool LuaState::getglobal(const std::string& name) {
lua_getglobal(L, name.c_str());
if (lua_isnil(L, lua_gettop(L))) {
lua_pop(L, lua_gettop(L));
return false;
}
return true;
}
bool LuaState::hasglobal(const std::string& name) {
lua_getglobal(L, name.c_str());
if (lua_isnil(L, lua_gettop(L))) {
lua_pop(L, lua_gettop(L));
return false;
}
lua_pop(L, lua_gettop(L));
return true;
}
void LuaState::setglobal(const std::string& name) {
lua_setglobal(L, name.c_str());
}
bool LuaState::rename(const std::string& from, const std::string& to) {
const char* src = from.c_str();
lua_getglobal(L, src);
if (lua_isnil(L, lua_gettop(L))) {
lua_pop(L, lua_gettop(L));
return false;
}
lua_setglobal(L, to.c_str());
// remove previous
lua_pushnil(L);
lua_setglobal(L, src);
return true;
}
void LuaState::remove(const std::string& name) {
lua_pushnil(L);
lua_setglobal(L, name.c_str());
}
void LuaState::createLibs() {
openlib("audio", audiolib);
openlib("block", blocklib);
openlib("console", consolelib);
openlib("core", corelib);
openlib("file", filelib);
openlib("gui", guilib);
openlib("input", inputlib);
openlib("inventory", inventorylib);
openlib("item", itemlib);
openlib("json", jsonlib);
openlib("pack", packlib);
openlib("player", playerlib);
openlib("time", timelib);
openlib("toml", tomllib);
openlib("world", worldlib);
addfunc("print", lua_wrap_errors<l_print>);
}
void LuaState::loadbuffer(int env, const std::string& src, const std::string& file) {
if (luaL_loadbuffer(L, src.c_str(), src.length(), file.c_str())) {
throw luaerror(lua_tostring(L, -1));
}
if (env && getglobal(envName(env))) {
lua_setfenv(L, -2);
}
}
int LuaState::call(int argc, int nresults) {
if (lua_pcall(L, argc, nresults, 0)) {
throw luaerror(lua_tostring(L, -1));
}
return 1;
}
int LuaState::callNoThrow(int argc) {
if (lua_pcall(L, argc, LUA_MULTRET, 0)) {
logError(lua_tostring(L, -1));
return 0;
}
return 1;
}
int LuaState::eval(int env, const std::string& src, const std::string& file) {
auto srcText = "return "+src;
loadbuffer(env, srcText, file);
return call(0);
}
int LuaState::execute(int env, const std::string& src, const std::string& file) {
loadbuffer(env, src, file);
return callNoThrow(0);
}
int LuaState::gettop() const {
return lua_gettop(L);
}
int LuaState::pushinteger(lua_Integer x) {
lua_pushinteger(L, x);
return 1;
}
int LuaState::pushnumber(lua_Number x) {
lua_pushnumber(L, x);
return 1;
}
int LuaState::pushboolean(bool x) {
lua_pushboolean(L, x);
return 1;
}
int LuaState::pushivec3(lua_Integer x, lua_Integer y, lua_Integer z) {
lua::pushivec3(L, x, y, z);
return 3;
}
int LuaState::pushstring(const std::string& str) {
lua_pushstring(L, str.c_str());
return 1;
}
int LuaState::pushenv(int env) {
if (getglobal(envName(env))) {
return 1;
}
return 0;
}
int LuaState::pushvalue(int idx) {
lua_pushvalue(L, idx);
return 1;
}
int LuaState::pushvalue(const dynamic::Value& value) {
using namespace dynamic;
if (auto* flag = std::get_if<bool>(&value)) {
pushboolean(*flag);
} else if (auto* num = std::get_if<integer_t>(&value)) {
pushinteger(*num);
} else if (auto* num = std::get_if<number_t>(&value)) {
pushnumber(*num);
} else if (auto* str = std::get_if<std::string>(&value)) {
pushstring(str->c_str());
} else if (auto listptr = std::get_if<List_sptr>(&value)) {
auto list = *listptr;
lua_createtable(L, list->size(), 0);
for (size_t i = 0; i < list->size(); i++) {
pushvalue(list->get(i));
lua_rawseti(L, -2, i+1);
}
} else if (auto mapptr = std::get_if<Map_sptr>(&value)) {
auto map = *mapptr;
lua_createtable(L, 0, map->size());
for (auto& entry : map->values) {
pushvalue(entry.second);
lua_setfield(L, -2, entry.first.c_str());
}
} else {
pushnil();
}
return 1;
}
int LuaState::pushglobals() {
lua_pushvalue(L, LUA_GLOBALSINDEX);
return 1;
}
int LuaState::pushcfunction(lua_CFunction function) {
lua_pushcfunction(L, function);
return 1;
}
void LuaState::pop(int n) {
lua_pop(L, n);
}
int LuaState::pushnil() {
lua_pushnil(L);
return 1;
}
bool LuaState::getfield(const std::string& name, int idx) {
lua_getfield(L, idx, name.c_str());
if (lua_isnil(L, -1)) {
lua_pop(L, -1);
return false;
}
return true;
}
void LuaState::setfield(const std::string& name, int idx) {
lua_setfield(L, idx, name.c_str());
}
bool LuaState::toboolean(int idx) {
return lua_toboolean(L, idx);
}
lua_Integer LuaState::tointeger(int idx) {
return lua_tointeger(L, idx);
}
lua_Number LuaState::tonumber(int idx) {
return lua_tonumber(L, idx);
}
glm::vec2 LuaState::tovec2(int idx) {
return lua::tovec2(L, idx);
}
glm::vec4 LuaState::tocolor(int idx) {
return lua::tocolor(L, idx);
}
const char* LuaState::tostring(int idx) {
return lua_tostring(L, idx);
}
dynamic::Value LuaState::tovalue(int idx) {
using namespace dynamic;
auto type = lua_type(L, idx);
switch (type) {
case LUA_TNIL:
case LUA_TNONE:
return dynamic::NONE;
case LUA_TBOOLEAN:
return lua_toboolean(L, idx) == 1;
case LUA_TNUMBER: {
auto number = lua_tonumber(L, idx);
auto integer = lua_tointeger(L, idx);
if (number == (lua_Number)integer) {
return integer;
} else {
return number;
}
}
case LUA_TSTRING:
return std::string(lua_tostring(L, idx));
case LUA_TTABLE: {
int len = lua_objlen(L, idx);
if (len) {
// array
auto list = create_list();
for (int i = 1; i <= len; i++) {
lua_rawgeti(L, idx, i);
list->put(tovalue(-1));
lua_pop(L, 1);
}
return list;
} else {
// table
auto map = create_map();
lua_pushvalue(L, idx);
lua_pushnil(L);
while (lua_next(L, -2)) {
lua_pushvalue(L, -2);
auto key = lua_tostring(L, -1);
map->put(key, tovalue(-2));
lua_pop(L, 2);
}
lua_pop(L, 1);
return map;
}
}
default:
throw std::runtime_error(
"lua type "+std::string(luaL_typename(L, type))+" is not supported"
);
}
}
bool LuaState::isstring(int idx) {
return lua_isstring(L, idx);
}
bool LuaState::isfunction(int idx) {
return lua_isfunction(L, idx);
}
void LuaState::openlib(const std::string& name, const luaL_Reg* libfuncs) {
lua_newtable(L);
luaL_setfuncs(L, libfuncs, 0);
lua_setglobal(L, name.c_str());
}
std::shared_ptr<std::string> LuaState::createLambdaHandler() {
auto ptr = reinterpret_cast<ptrdiff_t>(lua_topointer(L, -1));
auto name = util::mangleid(ptr);
lua_getglobal(L, LAMBDAS_TABLE.c_str());
lua_pushvalue(L, -2);
lua_setfield(L, -2, name.c_str());
lua_pop(L, 2);
return std::shared_ptr<std::string>(new std::string(name), [=](auto* name) {
lua_getglobal(L, LAMBDAS_TABLE.c_str());
lua_pushnil(L);
lua_setfield(L, -2, name->c_str());
lua_pop(L, 1);
delete name;
});
}
runnable LuaState::createRunnable() {
auto funcptr = createLambdaHandler();
return [=]() {
lua_getglobal(L, LAMBDAS_TABLE.c_str());
lua_getfield(L, -1, funcptr->c_str());
callNoThrow(0);
};
}
scripting::common_func LuaState::createLambda() {
auto funcptr = createLambdaHandler();
return [=](const std::vector<dynamic::Value>& args) {
lua_getglobal(L, LAMBDAS_TABLE.c_str());
lua_getfield(L, -1, funcptr->c_str());
for (const auto& arg : args) {
pushvalue(arg);
}
if (call(args.size(), 1)) {
auto result = tovalue(-1);
pop(1);
return result;
}
return dynamic::Value(dynamic::NONE);
};
}
const char* LuaState::requireString(int idx) {
if (!lua_isstring(L, idx)) {
throw luaerror("string expected at "+std::to_string(idx));
}
return lua_tostring(L, idx);
}
int LuaState::createEnvironment(int parent) {
int id = nextEnvironment++;
// local env = {}
lua_createtable(L, 0, 1);
// setmetatable(env, {__index=_G})
lua_createtable(L, 0, 1);
if (parent == 0) {
lua_pushvalue(L, LUA_GLOBALSINDEX);
} else {
if (pushenv(parent) == 0) {
lua_pushvalue(L, LUA_GLOBALSINDEX);
}
}
lua_setfield(L, -2, "__index");
lua_setmetatable(L, -2);
// envname = env
setglobal(envName(id));
return id;
}
void LuaState::removeEnvironment(int id) {
if (id == 0) {
return;
}
lua_pushnil(L);
setglobal(envName(id));
}
bool LuaState::emit_event(const std::string &name, std::function<int(LuaState *)> args) {
getglobal("events");
getfield("emit");
pushstring(name);
callNoThrow(args(this) + 1);
bool result = toboolean(-1);
pop(2);
return result;
}
void LuaState::dumpStack() {
int top = gettop();
for (int i = 1; i <= top; i++) {
std::cout << std::setw(3) << i << std::setw(20) << luaL_typename(L, i) << std::setw(30);
switch (lua_type(L, i)) {
case LUA_TNUMBER:
std::cout << tonumber(i);
break;
case LUA_TSTRING:
std::cout << tostring(i);
break;
case LUA_TBOOLEAN:
std::cout << (toboolean(i) ? "true" : "false");
break;
case LUA_TNIL:
std::cout << "nil";
break;
default:
std::cout << lua_topointer(L, i);
break;
}
std::cout << std::endl;
}
}
lua_State* LuaState::getLua() const {
return L;
}

View File

@ -1,82 +0,0 @@
#ifndef LOGIC_SCRIPTING_LUA_STATE_HPP_
#define LOGIC_SCRIPTING_LUA_STATE_HPP_
#include "lua_commons.hpp"
#include "../scripting_functional.hpp"
#include "../../../data/dynamic.hpp"
#include "../../../delegates.hpp"
#include <string>
#include <stdexcept>
namespace lua {
class luaerror : public std::runtime_error {
public:
luaerror(const std::string& message);
};
class LuaState {
lua_State* L;
int nextEnvironment = 1;
void logError(const std::string& text);
void removeLibFuncs(const char* libname, const char* funcs[]);
void createLibs();
std::shared_ptr<std::string> createLambdaHandler();
public:
LuaState();
~LuaState();
static std::string envName(int env);
void loadbuffer(int env, const std::string& src, const std::string& file);
int gettop() const;
int pushivec3(lua_Integer x, lua_Integer y, lua_Integer z);
int pushinteger(lua_Integer x);
int pushnumber(lua_Number x);
int pushboolean(bool x);
int pushstring(const std::string& str);
int pushenv(int env);
int pushvalue(int idx);
int pushvalue(const dynamic::Value& value);
int pushnil();
int pushglobals();
int pushcfunction(lua_CFunction function);
void pop(int n=1);
bool getfield(const std::string& name, int idx = -1);
void setfield(const std::string& name, int idx = -2);
bool toboolean(int idx);
lua_Integer tointeger(int idx);
lua_Number tonumber(int idx);
glm::vec2 tovec2(int idx);
glm::vec4 tocolor(int idx);
dynamic::Value tovalue(int idx);
const char* tostring(int idx);
bool isstring(int idx);
bool isfunction(int idx);
int call(int argc, int nresults=-1);
int callNoThrow(int argc);
int execute(int env, const std::string& src, const std::string& file="<string>");
int eval(int env, const std::string& src, const std::string& file="<eval>");
void openlib(const std::string& name, const luaL_Reg* libfuncs);
void addfunc(const std::string& name, lua_CFunction func);
bool getglobal(const std::string& name);
void setglobal(const std::string& name);
bool hasglobal(const std::string& name);
bool rename(const std::string& from, const std::string& to);
void remove(const std::string& name);;
runnable createRunnable();
scripting::common_func createLambda();
const char* requireString(int idx);
int createEnvironment(int parent);
void removeEnvironment(int id);
bool emit_event(const std::string& name, std::function<int(lua::LuaState*)> args=[](auto*){return 0;});
void dumpStack();
lua_State* getLua() const;
};
}
#endif // LOGIC_SCRIPTING_LUA_STATE_HPP_

View File

@ -1,7 +1,7 @@
#ifndef LOGIC_SCRIPTING_API_LUA_HPP_
#define LOGIC_SCRIPTING_API_LUA_HPP_
#include "lua_commons.hpp"
#include "lua_util.hpp"
#include <exception>
@ -24,6 +24,6 @@ extern const luaL_Reg tomllib [];
extern const luaL_Reg worldlib [];
// Lua Overrides
extern int l_print(lua_State* L);
extern int l_print(lua::State* L);
#endif // LOGIC_SCRIPTING_API_LUA_HPP_

View File

@ -1,17 +1,14 @@
#include "api_lua.hpp"
#include "lua_commons.hpp"
#include "lua_util.hpp"
#include "../../../audio/audio.hpp"
#include "../../../engine.hpp"
#include "../scripting.hpp"
inline const char* DEFAULT_CHANNEL = "regular";
inline int extract_channel_index(lua_State* L, int idx) {
inline int extract_channel_index(lua::State* L, int idx) {
const char* channel = DEFAULT_CHANNEL;
if (!lua_isnoneornil(L, idx)) {
channel = lua_tostring(L, idx);
if (!lua::isnoneornil(L, idx)) {
channel = lua::tostring(L, idx);
}
int index = audio::get_channel_index(channel);
if (index == 0) {
@ -23,11 +20,11 @@ inline int extract_channel_index(lua_State* L, int idx) {
inline audio::speakerid_t play_sound(
const char* name,
bool relative,
lua_Number x,
lua_Number y,
lua_Number z,
lua_Number volume,
lua_Number pitch,
lua::Number x,
lua::Number y,
lua::Number z,
lua::Number volume,
lua::Number pitch,
bool loop,
int channel
) {
@ -58,11 +55,11 @@ inline audio::speakerid_t play_sound(
inline audio::speakerid_t play_stream(
const char* filename,
bool relative,
lua_Number x,
lua_Number y,
lua_Number z,
lua_Number volume,
lua_Number pitch,
lua::Number x,
lua::Number y,
lua::Number z,
lua::Number volume,
lua::Number pitch,
bool loop,
int channel
) {
@ -94,21 +91,20 @@ inline audio::speakerid_t play_stream(
/// pitch: number,
/// channel: string = "regular",
/// loop: bool = false)
static int l_audio_play_stream(lua_State* L) {
lua_pushinteger(L, static_cast<lua_Integer>(
static int l_audio_play_stream(lua::State* L) {
return lua::pushinteger(L, static_cast<lua::Integer>(
play_stream(
lua_tostring(L, 1),
lua::tostring(L, 1),
false,
lua_tonumber(L, 2),
lua_tonumber(L, 3),
lua_tonumber(L, 4),
lua_tonumber(L, 5),
lua_tonumber(L, 6),
lua_toboolean(L, 8),
lua::tonumber(L, 2),
lua::tonumber(L, 3),
lua::tonumber(L, 4),
lua::tonumber(L, 5),
lua::tonumber(L, 6),
lua::toboolean(L, 8),
extract_channel_index(L, 7)
)
));
return 1;
}
/// @brief audio.play_stream_2d(
@ -117,19 +113,18 @@ static int l_audio_play_stream(lua_State* L) {
/// pitch: number,
/// channel: string = "regular",
/// loop: bool = false)
static int l_audio_play_stream_2d(lua_State* L) {
lua_pushinteger(L, static_cast<lua_Integer>(
static int l_audio_play_stream_2d(lua::State* L) {
return lua::pushinteger(L, static_cast<lua::Integer>(
play_stream(
lua_tostring(L, 1),
lua::tostring(L, 1),
true,
0.0, 0.0, 0.0,
lua_tonumber(L, 2),
lua_tonumber(L, 3),
lua_toboolean(L, 5),
lua::tonumber(L, 2),
lua::tonumber(L, 3),
lua::toboolean(L, 5),
extract_channel_index(L, 4)
)
));
return 1;
}
/// @brief audio.play_sound(
@ -141,21 +136,20 @@ static int l_audio_play_stream_2d(lua_State* L) {
/// pitch: number,
/// channel: string = "regular",
/// loop: bool = false)
static int l_audio_play_sound(lua_State* L) {
lua_pushinteger(L, static_cast<lua_Integer>(
static int l_audio_play_sound(lua::State* L) {
return lua::pushinteger(L, static_cast<lua::Integer>(
play_sound(
lua_tostring(L, 1),
lua::tostring(L, 1),
false,
lua_tonumber(L, 2),
lua_tonumber(L, 3),
lua_tonumber(L, 4),
lua_tonumber(L, 5),
lua_tonumber(L, 6),
lua_toboolean(L, 8),
lua::tonumber(L, 2),
lua::tonumber(L, 3),
lua::tonumber(L, 4),
lua::tonumber(L, 5),
lua::tonumber(L, 6),
lua::toboolean(L, 8),
extract_channel_index(L, 7)
)
));
return 1;
}
/// @brief audio.play_sound_2d(
@ -164,24 +158,23 @@ static int l_audio_play_sound(lua_State* L) {
/// pitch: number,
/// channel: string = "regular",
/// loop: bool = false)
static int l_audio_play_sound_2d(lua_State* L) {
lua_pushinteger(L, static_cast<lua_Integer>(
static int l_audio_play_sound_2d(lua::State* L) {
return lua::pushinteger(L, static_cast<lua::Integer>(
play_sound(
lua_tostring(L, 1),
lua::tostring(L, 1),
true,
0.0, 0.0, 0.0,
lua_tonumber(L, 2),
lua_tonumber(L, 3),
lua_toboolean(L, 5),
lua::tonumber(L, 2),
lua::tonumber(L, 3),
lua::toboolean(L, 5),
extract_channel_index(L, 4)
)
));
return 1;
}
/// @brief audio.stop(speakerid: integer) -> nil
static int l_audio_stop(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
static int l_audio_stop(lua::State* L) {
auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) {
speaker->stop();
}
@ -189,8 +182,8 @@ static int l_audio_stop(lua_State* L) {
}
/// @brief audio.pause(speakerid: integer) -> nil
static int l_audio_pause(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
static int l_audio_pause(lua::State* L) {
auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) {
speaker->pause();
}
@ -198,8 +191,8 @@ static int l_audio_pause(lua_State* L) {
}
/// @brief audio.resume(speakerid: integer) -> nil
static int l_audio_resume(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
static int l_audio_resume(lua::State* L) {
auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr && speaker->isPaused()) {
speaker->play();
}
@ -207,49 +200,48 @@ static int l_audio_resume(lua_State* L) {
}
/// @brief audio.set_loop(speakerid: integer, value: bool) -> nil
static int l_audio_set_loop(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
static int l_audio_set_loop(lua::State* L) {
auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) {
bool value = lua_toboolean(L, 2);
speaker->setLoop(value);
speaker->setLoop(lua::toboolean(L, 2));
}
return 0;
}
/// @brief audio.set_volume(speakerid: integer, value: number) -> nil
static int l_audio_set_volume(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
static int l_audio_set_volume(lua::State* L) {
auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) {
speaker->setVolume(static_cast<float>(lua_tonumber(L, 2)));
speaker->setVolume(static_cast<float>(lua::tonumber(L, 2)));
}
return 0;
}
/// @brief audio.set_pitch(speakerid: integer, value: number) -> nil
static int l_audio_set_pitch(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
static int l_audio_set_pitch(lua::State* L) {
auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) {
speaker->setPitch(static_cast<float>(lua_tonumber(L, 2)));
speaker->setPitch(static_cast<float>(lua::tonumber(L, 2)));
}
return 0;
}
/// @brief audio.set_time(speakerid: integer, value: number) -> nil
static int l_audio_set_time(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
static int l_audio_set_time(lua::State* L) {
auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) {
speaker->setTime(static_cast<audio::duration_t>(lua_tonumber(L, 2)));
speaker->setTime(static_cast<audio::duration_t>(lua::tonumber(L, 2)));
}
return 0;
}
/// @brief audio.set_position(speakerid: integer, x: number, y: number, z: number) -> nil
static int l_audio_set_position(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
static int l_audio_set_position(lua::State* L) {
auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) {
auto x = lua_tonumber(L, 2);
auto y = lua_tonumber(L, 3);
auto z = lua_tonumber(L, 4);
auto x = lua::tonumber(L, 2);
auto y = lua::tonumber(L, 3);
auto z = lua::tonumber(L, 4);
speaker->setPosition(glm::vec3(
static_cast<float>(x),
static_cast<float>(y),
@ -260,12 +252,12 @@ static int l_audio_set_position(lua_State* L) {
}
/// @brief audio.set_velocity(speakerid: integer, x: number, y: number, z: number) -> nil
static int l_audio_set_velocity(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
static int l_audio_set_velocity(lua::State* L) {
auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) {
auto x = lua_tonumber(L, 2);
auto y = lua_tonumber(L, 3);
auto z = lua_tonumber(L, 4);
auto x = lua::tonumber(L, 2);
auto y = lua::tonumber(L, 3);
auto z = lua::tonumber(L, 4);
speaker->setVelocity(glm::vec3(
static_cast<float>(x),
static_cast<float>(y),
@ -276,139 +268,120 @@ static int l_audio_set_velocity(lua_State* L) {
}
/// @brief audio.is_playing(speakerid: integer) -> bool
static int l_audio_is_playing(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
static int l_audio_is_playing(lua::State* L) {
auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) {
lua_pushboolean(L, speaker->isPlaying());
return 1;
return lua::pushboolean(L, speaker->isPlaying());
}
lua_pushboolean(L, false);
return 1;
return lua::pushboolean(L, false);
}
/// @brief audio.is_paused(speakerid: integer) -> bool
static int l_audio_is_paused(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
static int l_audio_is_paused(lua::State* L) {
auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) {
lua_pushboolean(L, speaker->isPaused());
return 1;
return lua::pushboolean(L, speaker->isPaused());
}
lua_pushboolean(L, false);
return 1;
return lua::pushboolean(L, false);
}
/// @brief audio.is_loop(speakerid: integer) -> bool
static int l_audio_is_loop(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
static int l_audio_is_loop(lua::State* L) {
auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) {
lua_pushboolean(L, speaker->isLoop());
return 1;
return lua::pushboolean(L, speaker->isLoop());
}
lua_pushboolean(L, false);
return 1;
return lua::pushboolean(L, false);
}
/// @brief audio.get_volume(speakerid: integer) -> number
static int l_audio_get_volume(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
static int l_audio_get_volume(lua::State* L) {
auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) {
lua_pushnumber(L, speaker->getVolume());
return 1;
return lua::pushnumber(L, speaker->getVolume());
}
lua_pushnumber(L, 0.0);
return 1;
return lua::pushnumber(L, 0.0);
}
/// @brief audio.get_pitch(speakerid: integer) -> number
static int l_audio_get_pitch(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
static int l_audio_get_pitch(lua::State* L) {
auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) {
lua_pushnumber(L, speaker->getPitch());
return 1;
return lua::pushnumber(L, speaker->getPitch());
}
lua_pushnumber(L, 1.0);
return 1;
return lua::pushnumber(L, 1.0);
}
/// @brief audio.get_time(speakerid: integer) -> number
static int l_audio_get_time(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
static int l_audio_get_time(lua::State* L) {
auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) {
lua_pushnumber(L, speaker->getTime());
return 1;
return lua::pushnumber(L, speaker->getTime());
}
lua_pushnumber(L, 0.0);
return 1;
return lua::pushnumber(L, 0.0);
}
/// @brief audio.get_duration(speakerid: integer) -> number
static int l_audio_get_duration(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
static int l_audio_get_duration(lua::State* L) {
auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) {
lua_pushnumber(L, speaker->getDuration());
return 1;
return lua::pushnumber(L, speaker->getDuration());
}
lua_pushnumber(L, 0.0);
return 1;
return lua::pushnumber(L, 0.0);
}
/// @brief audio.get_position(speakerid: integer) -> number, number, number
static int l_audio_get_position(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
static int l_audio_get_position(lua::State* L) {
auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) {
lua::pushvec3(L, speaker->getPosition());
return 1;
return lua::pushvec3(L, speaker->getPosition());
}
return 0;
}
/// @brief audio.get_velocity(speakerid: integer) -> number, number, number
static int l_audio_get_velocity(lua_State* L) {
auto speaker = audio::get_speaker(lua_tointeger(L, 1));
static int l_audio_get_velocity(lua::State* L) {
auto speaker = audio::get_speaker(lua::tointeger(L, 1));
if (speaker != nullptr) {
auto vec = speaker->getVelocity();
lua::pushvec3(L, vec);
return 1;
return lua::pushvec3(L, speaker->getVelocity());
}
return 0;
}
// @brief audio.count_speakers() -> integer
static int l_audio_count_speakers(lua_State* L) {
lua_pushinteger(L, audio::count_speakers());
return 1;
static int l_audio_count_speakers(lua::State* L) {
return lua::pushinteger(L, audio::count_speakers());
}
// @brief audio.count_streams() -> integer
static int l_audio_count_streams(lua_State* L) {
lua_pushinteger(L, audio::count_streams());
return 1;
static int l_audio_count_streams(lua::State* L) {
return lua::pushinteger(L, audio::count_streams());
}
const luaL_Reg audiolib [] = {
{"play_sound", lua_wrap_errors<l_audio_play_sound>},
{"play_sound_2d", lua_wrap_errors<l_audio_play_sound_2d>},
{"play_stream", lua_wrap_errors<l_audio_play_stream>},
{"play_stream_2d", lua_wrap_errors<l_audio_play_stream_2d>},
{"stop", lua_wrap_errors<l_audio_stop>},
{"pause", lua_wrap_errors<l_audio_pause>},
{"resume", lua_wrap_errors<l_audio_resume>},
{"set_loop", lua_wrap_errors<l_audio_set_loop>},
{"set_volume", lua_wrap_errors<l_audio_set_volume>},
{"set_pitch", lua_wrap_errors<l_audio_set_pitch>},
{"set_time", lua_wrap_errors<l_audio_set_time>},
{"set_position", lua_wrap_errors<l_audio_set_position>},
{"set_velocity", lua_wrap_errors<l_audio_set_velocity>},
{"is_playing", lua_wrap_errors<l_audio_is_playing>},
{"is_paused", lua_wrap_errors<l_audio_is_paused>},
{"is_loop", lua_wrap_errors<l_audio_is_loop>},
{"get_volume", lua_wrap_errors<l_audio_get_volume>},
{"get_pitch", lua_wrap_errors<l_audio_get_pitch>},
{"get_time", lua_wrap_errors<l_audio_get_time>},
{"get_duration", lua_wrap_errors<l_audio_get_duration>},
{"get_position", lua_wrap_errors<l_audio_get_position>},
{"get_velocity", lua_wrap_errors<l_audio_get_velocity>},
{"count_speakers", lua_wrap_errors<l_audio_count_speakers>},
{"count_streams", lua_wrap_errors<l_audio_count_streams>},
{"play_sound", lua::wrap<l_audio_play_sound>},
{"play_sound_2d", lua::wrap<l_audio_play_sound_2d>},
{"play_stream", lua::wrap<l_audio_play_stream>},
{"play_stream_2d", lua::wrap<l_audio_play_stream_2d>},
{"stop", lua::wrap<l_audio_stop>},
{"pause", lua::wrap<l_audio_pause>},
{"resume", lua::wrap<l_audio_resume>},
{"set_loop", lua::wrap<l_audio_set_loop>},
{"set_volume", lua::wrap<l_audio_set_volume>},
{"set_pitch", lua::wrap<l_audio_set_pitch>},
{"set_time", lua::wrap<l_audio_set_time>},
{"set_position", lua::wrap<l_audio_set_position>},
{"set_velocity", lua::wrap<l_audio_set_velocity>},
{"is_playing", lua::wrap<l_audio_is_playing>},
{"is_paused", lua::wrap<l_audio_is_paused>},
{"is_loop", lua::wrap<l_audio_is_loop>},
{"get_volume", lua::wrap<l_audio_get_volume>},
{"get_pitch", lua::wrap<l_audio_get_pitch>},
{"get_time", lua::wrap<l_audio_get_time>},
{"get_duration", lua::wrap<l_audio_get_duration>},
{"get_position", lua::wrap<l_audio_get_position>},
{"get_velocity", lua::wrap<l_audio_get_velocity>},
{"count_speakers", lua::wrap<l_audio_count_speakers>},
{"count_streams", lua::wrap<l_audio_count_streams>},
{NULL, NULL}
};

View File

@ -1,8 +1,4 @@
#include "lua_commons.hpp"
#include "api_lua.hpp"
#include "lua_util.hpp"
#include "../scripting.hpp"
#include "../../../world/Level.hpp"
#include "../../../voxels/Chunks.hpp"
@ -13,126 +9,118 @@
#include "../../../content/Content.hpp"
#include "../../../logic/BlocksController.hpp"
static Block* require_block(lua_State* L) {
auto indices = scripting::content->getIndices();
lua_Integer id = lua_tointeger(L, 1);
using namespace scripting;
static Block* require_block(lua::State* L) {
auto indices = content->getIndices();
auto id = lua::tointeger(L, 1);
if (static_cast<size_t>(id) >= indices->countBlockDefs()) {
return nullptr;
}
return indices->getBlockDef(id);
}
static int l_name(lua_State* L) {
static int l_name(lua::State* L) {
if (auto def = require_block(L)) {
lua_pushstring(L, def->name.c_str());
return 1;
return lua::pushstring(L, def->name);
}
return 0;
}
static int l_material(lua_State* L) {
static int l_material(lua::State* L) {
if (auto def = require_block(L)) {
lua_pushstring(L, def->material.c_str());
return 1;
return lua::pushstring(L, def->material);
}
return 0;
}
static int l_is_solid_at(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3);
static int l_is_solid_at(lua::State* L) {
auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3);
lua_pushboolean(L, scripting::level->chunks->isSolidBlock(x, y, z));
return 1;
return lua::pushboolean(L, level->chunks->isSolidBlock(x, y, z));
}
static int l_count(lua_State* L) {
lua_pushinteger(L, scripting::indices->countBlockDefs());
return 1;
static int l_count(lua::State* L) {
return lua::pushinteger(L, indices->countBlockDefs());
}
static int l_index(lua_State* L) {
std::string name = lua_tostring(L, 1);
lua_pushinteger(L, scripting::content->requireBlock(name).rt.id);
return 1;
static int l_index(lua::State* L) {
auto name = lua::require_string(L, 1);
return lua::pushinteger(L, content->requireBlock(name).rt.id);
}
static int l_is_extended(lua_State* L) {
static int l_is_extended(lua::State* L) {
if (auto def = require_block(L)) {
lua_pushboolean(L, def->rt.extended);
return 1;
return lua::pushboolean(L, def->rt.extended);
}
return 0;
}
static int l_get_size(lua_State* L) {
static int l_get_size(lua::State* L) {
if (auto def = require_block(L)) {
return lua::pushivec3(L, def->size.x, def->size.y, def->size.z);
}
return 0;
}
static int l_is_segment(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3);
auto vox = scripting::level->chunks->get(x, y, z);
lua_pushboolean(L, vox->state.segment);
return 1;
static int l_is_segment(lua::State* L) {
auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3);
auto vox = level->chunks->get(x, y, z);
return lua::pushboolean(L, vox->state.segment);
}
static int l_seek_origin(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3);
auto vox = scripting::level->chunks->get(x, y, z);
auto def = scripting::indices->getBlockDef(vox->id);
return lua::pushivec3(L, scripting::level->chunks->seekOrigin({x, y, z}, def, vox->state));
static int l_seek_origin(lua::State* L) {
auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3);
auto vox = level->chunks->get(x, y, z);
auto def = indices->getBlockDef(vox->id);
return lua::pushivec3(L, level->chunks->seekOrigin({x, y, z}, def, vox->state));
}
static int l_set(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3);
lua_Integer id = lua_tointeger(L, 4);
lua_Integer state = lua_tointeger(L, 5);
bool noupdate = lua_toboolean(L, 6);
if (static_cast<size_t>(id) >= scripting::indices->countBlockDefs()) {
static int l_set(lua::State* L) {
auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3);
auto id = lua::tointeger(L, 4);
auto state = lua::tointeger(L, 5);
bool noupdate = lua::toboolean(L, 6);
if (static_cast<size_t>(id) >= indices->countBlockDefs()) {
return 0;
}
if (!scripting::level->chunks->get(x, y, z)) {
if (!level->chunks->get(x, y, z)) {
return 0;
}
scripting::level->chunks->set(x, y, z, id, int2blockstate(state));
scripting::level->lighting->onBlockSet(x,y,z, id);
level->chunks->set(x, y, z, id, int2blockstate(state));
level->lighting->onBlockSet(x,y,z, id);
if (!noupdate) {
scripting::blocks->updateSides(x, y, z);
blocks->updateSides(x, y, z);
}
return 0;
}
static int l_get(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3);
voxel* vox = scripting::level->chunks->get(x, y, z);
static int l_get(lua::State* L) {
auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3);
auto vox = level->chunks->get(x, y, z);
int id = vox == nullptr ? -1 : vox->id;
lua_pushinteger(L, id);
return 1;
return lua::pushinteger(L, id);
}
static int l_get_x(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3);
voxel* vox = scripting::level->chunks->get(x, y, z);
static int l_get_x(lua::State* L) {
auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3);
auto vox = level->chunks->get(x, y, z);
if (vox == nullptr) {
return lua::pushivec3(L, 1, 0, 0);
}
auto def = scripting::level->content->getIndices()->getBlockDef(vox->id);
auto def = level->content->getIndices()->getBlockDef(vox->id);
if (!def->rotatable) {
return lua::pushivec3(L, 1, 0, 0);
} else {
@ -141,15 +129,15 @@ static int l_get_x(lua_State* L) {
}
}
static int l_get_y(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3);
voxel* vox = scripting::level->chunks->get(x, y, z);
static int l_get_y(lua::State* L) {
auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3);
auto vox = level->chunks->get(x, y, z);
if (vox == nullptr) {
return lua::pushivec3(L, 0, 1, 0);
}
auto def = scripting::level->content->getIndices()->getBlockDef(vox->id);
auto def = level->content->getIndices()->getBlockDef(vox->id);
if (!def->rotatable) {
return lua::pushivec3(L, 0, 1, 0);
} else {
@ -158,15 +146,15 @@ static int l_get_y(lua_State* L) {
}
}
static int l_get_z(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3);
voxel* vox = scripting::level->chunks->get(x, y, z);
static int l_get_z(lua::State* L) {
auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3);
auto vox = level->chunks->get(x, y, z);
if (vox == nullptr) {
return lua::pushivec3(L, 0, 0, 1);
}
auto def = scripting::level->content->getIndices()->getBlockDef(vox->id);
auto def = level->content->getIndices()->getBlockDef(vox->id);
if (!def->rotatable) {
return lua::pushivec3(L, 0, 0, 1);
} else {
@ -175,84 +163,80 @@ static int l_get_z(lua_State* L) {
}
}
static int l_get_rotation(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3);
voxel* vox = scripting::level->chunks->get(x, y, z);
static int l_get_rotation(lua::State* L) {
auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3);
voxel* vox = level->chunks->get(x, y, z);
int rotation = vox == nullptr ? 0 : vox->state.rotation;
lua_pushinteger(L, rotation);
return 1;
return lua::pushinteger(L, rotation);
}
static int l_set_rotation(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3);
lua_Integer value = lua_tointeger(L, 4);
scripting::level->chunks->setRotation(x, y, z, value);
static int l_set_rotation(lua::State* L) {
auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3);
auto value = lua::tointeger(L, 4);
level->chunks->setRotation(x, y, z, value);
return 0;
}
static int l_get_states(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3);
voxel* vox = scripting::level->chunks->get(x, y, z);
static int l_get_states(lua::State* L) {
auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3);
auto vox = level->chunks->get(x, y, z);
int states = vox == nullptr ? 0 : blockstate2int(vox->state);
lua_pushinteger(L, states);
return 1;
return lua::pushinteger(L, states);
}
static int l_set_states(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3);
lua_Integer states = lua_tointeger(L, 4);
static int l_set_states(lua::State* L) {
auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3);
auto states = lua::tointeger(L, 4);
Chunk* chunk = scripting::level->chunks->getChunkByVoxel(x, y, z);
auto chunk = level->chunks->getChunkByVoxel(x, y, z);
if (chunk == nullptr) {
return 0;
}
voxel* vox = scripting::level->chunks->get(x, y, z);
auto vox = level->chunks->get(x, y, z);
vox->state = int2blockstate(states);
chunk->setModifiedAndUnsaved();
return 0;
}
static int l_get_user_bits(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3);
lua_Integer offset = lua_tointeger(L, 4) + VOXEL_USER_BITS_OFFSET;
lua_Integer bits = lua_tointeger(L, 5);
static int l_get_user_bits(lua::State* L) {
auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3);
auto offset = lua::tointeger(L, 4) + VOXEL_USER_BITS_OFFSET;
auto bits = lua::tointeger(L, 5);
voxel* vox = scripting::level->chunks->get(x, y, z);
auto vox = level->chunks->get(x, y, z);
if (vox == nullptr) {
lua_pushinteger(L, 0);
return 1;
return lua::pushinteger(L, 0);
}
uint mask = ((1 << bits) - 1) << offset;
uint data = (blockstate2int(vox->state) & mask) >> offset;
lua_pushinteger(L, data);
return 1;
return lua::pushinteger(L, data);
}
static int l_set_user_bits(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3);
lua_Integer offset = lua_tointeger(L, 4);
lua_Integer bits = lua_tointeger(L, 5);
static int l_set_user_bits(lua::State* L) {
auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3);
auto offset = lua::tointeger(L, 4);
auto bits = lua::tointeger(L, 5);
size_t mask = ((1 << bits) - 1) << offset;
lua_Integer value = (lua_tointeger(L, 6) << offset) & mask;
auto value = (lua::tointeger(L, 6) << offset) & mask;
Chunk* chunk = scripting::level->chunks->getChunkByVoxel(x, y, z);
auto chunk = level->chunks->getChunkByVoxel(x, y, z);
if (chunk == nullptr) {
return 0;
}
voxel* vox = scripting::level->chunks->get(x, y, z);
auto vox = level->chunks->get(x, y, z);
if (vox == nullptr) {
return 0;
}
@ -261,45 +245,42 @@ static int l_set_user_bits(lua_State* L) {
return 0;
}
static int l_is_replaceable_at(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3);
lua_pushboolean(L, scripting::level->chunks->isReplaceableBlock(x, y, z));
return 1;
static int l_is_replaceable_at(lua::State* L) {
auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3);
return lua::pushboolean(L, level->chunks->isReplaceableBlock(x, y, z));
}
static int l_caption(lua_State* L) {
static int l_caption(lua::State* L) {
if (auto def = require_block(L)) {
lua_pushstring(L, def->caption.c_str());
return 1;
return lua::pushstring(L, def->caption);
}
return 0;
}
const luaL_Reg blocklib [] = {
{"index", lua_wrap_errors<l_index>},
{"name", lua_wrap_errors<l_name>},
{"material", lua_wrap_errors<l_material>},
{"caption", lua_wrap_errors<l_caption>},
{"defs_count", lua_wrap_errors<l_count>},
{"is_solid_at", lua_wrap_errors<l_is_solid_at>},
{"is_replaceable_at", lua_wrap_errors<l_is_replaceable_at>},
{"set", lua_wrap_errors<l_set>},
{"get", lua_wrap_errors<l_get>},
{"get_X", lua_wrap_errors<l_get_x>},
{"get_Y", lua_wrap_errors<l_get_y>},
{"get_Z", lua_wrap_errors<l_get_z>},
{"get_states", lua_wrap_errors<l_get_states>},
{"set_states", lua_wrap_errors<l_set_states>},
{"get_rotation", lua_wrap_errors<l_get_rotation>},
{"set_rotation", lua_wrap_errors<l_set_rotation>},
{"get_user_bits", lua_wrap_errors<l_get_user_bits>},
{"set_user_bits", lua_wrap_errors<l_set_user_bits>},
{"is_extended", lua_wrap_errors<l_is_extended>},
{"get_size", lua_wrap_errors<l_get_size>},
{"is_segment", lua_wrap_errors<l_is_segment>},
{"seek_origin", lua_wrap_errors<l_seek_origin>},
{"index", lua::wrap<l_index>},
{"name", lua::wrap<l_name>},
{"material", lua::wrap<l_material>},
{"caption", lua::wrap<l_caption>},
{"defs_count", lua::wrap<l_count>},
{"is_solid_at", lua::wrap<l_is_solid_at>},
{"is_replaceable_at", lua::wrap<l_is_replaceable_at>},
{"set", lua::wrap<l_set>},
{"get", lua::wrap<l_get>},
{"get_X", lua::wrap<l_get_x>},
{"get_Y", lua::wrap<l_get_y>},
{"get_Z", lua::wrap<l_get_z>},
{"get_states", lua::wrap<l_get_states>},
{"set_states", lua::wrap<l_set_states>},
{"get_rotation", lua::wrap<l_get_rotation>},
{"set_rotation", lua::wrap<l_set_rotation>},
{"get_user_bits", lua::wrap<l_get_user_bits>},
{"set_user_bits", lua::wrap<l_set_user_bits>},
{"is_extended", lua::wrap<l_is_extended>},
{"get_size", lua::wrap<l_get_size>},
{"is_segment", lua::wrap<l_is_segment>},
{"seek_origin", lua::wrap<l_seek_origin>},
{NULL, NULL}
};

View File

@ -1,26 +1,19 @@
#include "api_lua.hpp"
#include "lua_commons.hpp"
#include "LuaState.hpp"
#include "../scripting.hpp"
#include "../../CommandsInterpreter.hpp"
#include "../../../engine.hpp"
#include "../../../coders/commons.hpp"
namespace scripting {
extern lua::LuaState* state;
}
using namespace scripting;
static int l_add_command(lua_State* L) {
if (!lua_isfunction(L, 3)) {
static int l_add_command(lua::State* L) {
if (!lua::isfunction(L, 3)) {
throw std::runtime_error("invalid callback");
}
auto scheme = state->requireString(1);
auto description = state->requireString(2);
lua_pushvalue(L, 3);
auto func = state->createLambda();
auto scheme = lua::require_string(L, 1);
auto description = lua::require_string(L, 2);
lua::pushvalue(L, 3);
auto func = lua::create_lambda(L);
try {
engine->getCommandsInterpreter()->getRepository()->add(
scheme, description, [func](auto, auto args, auto kwargs) {
@ -33,36 +26,36 @@ static int l_add_command(lua_State* L) {
return 0;
}
static int l_execute(lua_State*) {
auto prompt = state->requireString(1);
static int l_execute(lua::State* L) {
auto prompt = lua::require_string(L, 1);
auto result = engine->getCommandsInterpreter()->execute(prompt);
state->pushvalue(result);
lua::pushvalue(L, result);
return 1;
}
static int l_set(lua_State*) {
auto name = state->requireString(1);
auto value = state->tovalue(2);
static int l_set(lua::State* L) {
auto name = lua::require_string(L, 1);
auto value = lua::tovalue(L, 2);
(*engine->getCommandsInterpreter())[name] = value;
return 0;
}
static int l_get_commands_list(lua_State* L) {
static int l_get_commands_list(lua::State* L) {
auto interpreter = engine->getCommandsInterpreter();
auto repo = interpreter->getRepository();
const auto& commands = repo->getCommands();
lua_createtable(L, commands.size(), 0);
lua::createtable(L, commands.size(), 0);
size_t index = 1;
for (const auto& entry : commands) {
lua_pushstring(L, entry.first.c_str());
lua_rawseti(L, -2, index++);
lua::pushstring(L, entry.first);
lua::rawseti(L, index++);
}
return 1;
}
static int l_get_command_info(lua_State* L) {
auto name = state->requireString(1);
static int l_get_command_info(lua::State* L) {
auto name = lua::require_string(L, 1);
auto interpreter = engine->getCommandsInterpreter();
auto repo = interpreter->getRepository();
auto command = repo->get(name);
@ -72,52 +65,52 @@ static int l_get_command_info(lua_State* L) {
const auto& args = command->getArgs();
const auto& kwargs = command->getKwArgs();
lua_createtable(L, 0, 4);
lua::createtable(L, 0, 4);
lua_pushstring(L, name);
lua_setfield(L, -2, "name");
lua::pushstring(L, name);
lua::setfield(L, "name");
lua_pushstring(L, command->getDescription().c_str());
lua_setfield(L, -2, "description");
lua::pushstring(L, command->getDescription());
lua::setfield(L, "description");
lua_createtable(L, args.size(), 0);
lua::createtable(L, args.size(), 0);
for (size_t i = 0; i < args.size(); i++) {
auto& arg = args.at(i);
lua_createtable(L, 0, 2);
lua::createtable(L, 0, 2);
lua_pushstring(L, arg.name.c_str());
lua_setfield(L, -2, "name");
lua::pushstring(L, arg.name);
lua::setfield(L, "name");
lua_pushstring(L, cmd::argtype_name(arg.type).c_str());
lua_setfield(L, -2, "type");
lua::pushstring(L, cmd::argtype_name(arg.type));
lua::setfield(L, "type");
if (arg.optional) {
lua_pushboolean(L, true);
lua_setfield(L, -2, "optional");
lua::pushboolean(L, true);
lua::setfield(L, "optional");
}
lua_rawseti(L, -2, i+1);
lua::rawseti(L, i+1);
}
lua_setfield(L, -2, "args");
lua::setfield(L, "args");
lua_createtable(L, 0, kwargs.size());
lua::createtable(L, 0, kwargs.size());
for (auto& entry : kwargs) {
auto& arg = entry.second;
lua_createtable(L, 0, 1);
lua::createtable(L, 0, 1);
lua_pushstring(L, cmd::argtype_name(arg.type).c_str());
lua_setfield(L, -2, "type");
lua_setfield(L, -2, arg.name.c_str());
lua::pushstring(L, cmd::argtype_name(arg.type));
lua::setfield(L, "type");
lua::setfield(L, arg.name);
}
lua_setfield(L, -2, "kwargs");
lua::setfield(L, "kwargs");
return 1;
}
const luaL_Reg consolelib [] = {
{"add_command", lua_wrap_errors<l_add_command>},
{"execute", lua_wrap_errors<l_execute>},
{"set", lua_wrap_errors<l_set>},
{"get_commands_list", lua_wrap_errors<l_get_commands_list>},
{"get_command_info", lua_wrap_errors<l_get_command_info>},
{"add_command", lua::wrap<l_add_command>},
{"execute", lua::wrap<l_execute>},
{"set", lua::wrap<l_set>},
{"get_commands_list", lua::wrap<l_get_commands_list>},
{"get_command_info", lua::wrap<l_get_command_info>},
{NULL, NULL}
};

View File

@ -1,6 +1,4 @@
#include "lua_commons.hpp"
#include "api_lua.hpp"
#include "LuaState.hpp"
#include "../../../engine.hpp"
#include "../../../files/settings_io.hpp"
@ -13,172 +11,166 @@
#include "../../../window/Events.hpp"
#include "../../../window/Window.hpp"
#include "../../../world/WorldGenerators.hpp"
#include "../scripting.hpp"
#include <vector>
#include <memory>
namespace scripting {
extern lua::LuaState* state;
}
using namespace scripting;
static int l_new_world(lua_State* L) {
auto name = lua_tostring(L, 1);
auto seed = lua_tostring(L, 2);
auto generator = lua_tostring(L, 3);
auto controller = scripting::engine->getController();
static int l_new_world(lua::State* L) {
auto name = lua::require_string(L, 1);
auto seed = lua::require_string(L, 2);
auto generator = lua::require_string(L, 3);
auto controller = engine->getController();
controller->createWorld(name, seed, generator);
return 0;
}
static int l_open_world(lua_State* L) {
auto name = lua_tostring(L, 1);
static int l_open_world(lua::State* L) {
auto name = lua::require_string(L, 1);
auto controller = scripting::engine->getController();
auto controller = engine->getController();
controller->openWorld(name, false);
return 0;
}
static int l_reopen_world(lua_State*) {
auto controller = scripting::engine->getController();
controller->reopenWorld(scripting::level->getWorld());
static int l_reopen_world(lua::State*) {
auto controller = engine->getController();
controller->reopenWorld(level->getWorld());
return 0;
}
static int l_close_world(lua_State* L) {
if (scripting::controller == nullptr) {
static int l_close_world(lua::State* L) {
if (controller == nullptr) {
throw std::runtime_error("no world open");
}
bool save_world = lua_toboolean(L, 1);
bool save_world = lua::toboolean(L, 1);
if (save_world) {
scripting::controller->saveWorld();
controller->saveWorld();
}
// destroy LevelScreen and run quit callbacks
scripting::engine->setScreen(nullptr);
engine->setScreen(nullptr);
// create and go to menu screen
scripting::engine->setScreen(std::make_shared<MenuScreen>(scripting::engine));
engine->setScreen(std::make_shared<MenuScreen>(engine));
return 0;
}
static int l_delete_world(lua_State* L) {
auto name = lua_tostring(L, 1);
auto controller = scripting::engine->getController();
static int l_delete_world(lua::State* L) {
auto name = lua::require_string(L, 1);
auto controller = engine->getController();
controller->deleteWorld(name);
return 0;
}
static int l_reconfig_packs(lua_State* L) {
if (!lua_istable(L, 1)) {
static int l_reconfig_packs(lua::State* L) {
if (!lua::istable(L, 1)) {
throw std::runtime_error("strings array expected as the first argument");
}
if (!lua_istable(L, 2)) {
if (!lua::istable(L, 2)) {
throw std::runtime_error("strings array expected as the second argument");
}
std::vector<std::string> addPacks;
if (!lua_istable(L, 1)) {
if (!lua::istable(L, 1)) {
throw std::runtime_error("an array expected as argument 1");
}
int addLen = lua_objlen(L, 1);
int addLen = lua::objlen(L, 1);
for (int i = 0; i < addLen; i++) {
lua_rawgeti(L, 1, i+1);
addPacks.emplace_back(lua_tostring(L, -1));
lua_pop(L, 1);
lua::rawgeti(L, i+1, 1);
addPacks.emplace_back(lua::tostring(L, -1));
lua::pop(L);
}
std::vector<std::string> remPacks;
if (!lua_istable(L, 2)) {
if (!lua::istable(L, 2)) {
throw std::runtime_error("an array expected as argument 2");
}
int remLen = lua_objlen(L, 2);
int remLen = lua::objlen(L, 2);
for (int i = 0; i < remLen; i++) {
lua_rawgeti(L, 2, i+1);
remPacks.emplace_back(lua_tostring(L, -1));
lua_pop(L, 1);
lua::rawgeti(L, i+1, 2);
remPacks.emplace_back(lua::tostring(L, -1));
lua::pop(L);
}
auto controller = scripting::engine->getController();
controller->reconfigPacks(scripting::controller, addPacks, remPacks);
auto engine_controller = engine->getController();
engine_controller->reconfigPacks(controller, addPacks, remPacks);
return 0;
}
static int l_get_setting(lua_State* L) {
auto name = lua_tostring(L, 1);
const auto value = scripting::engine->getSettingsHandler().getValue(name);
scripting::state->pushvalue(value);
return 1;
static int l_get_setting(lua::State* L) {
auto name = lua::require_string(L, 1);
const auto value = engine->getSettingsHandler().getValue(name);
return lua::pushvalue(L, value);
}
static int l_set_setting(lua_State* L) {
auto name = lua_tostring(L, 1);
const auto value = scripting::state->tovalue(2);
scripting::engine->getSettingsHandler().setValue(name, value);
static int l_set_setting(lua::State* L) {
auto name = lua::require_string(L, 1);
const auto value = lua::tovalue(L, 2);
engine->getSettingsHandler().setValue(name, value);
return 0;
}
static int l_str_setting(lua_State* L) {
auto name = lua_tostring(L, 1);
const auto string = scripting::engine->getSettingsHandler().toString(name);
scripting::state->pushstring(string);
return 1;
static int l_str_setting(lua::State* L) {
auto name = lua::require_string(L, 1);
const auto string = engine->getSettingsHandler().toString(name);
return lua::pushstring(L, string);
}
static int l_get_setting_info(lua_State* L) {
auto name = lua_tostring(L, 1);
auto setting = scripting::engine->getSettingsHandler().getSetting(name);
lua_createtable(L, 0, 1);
static int l_get_setting_info(lua::State* L) {
auto name = lua::require_string(L, 1);
auto setting = engine->getSettingsHandler().getSetting(name);
lua::createtable(L, 0, 1);
if (auto number = dynamic_cast<NumberSetting*>(setting)) {
lua_pushnumber(L, number->getMin());
lua_setfield(L, -2, "min");
lua_pushnumber(L, number->getMax());
lua_setfield(L, -2, "max");
lua::pushnumber(L, number->getMin());
lua::setfield(L, "min");
lua::pushnumber(L, number->getMax());
lua::setfield(L, "max");
return 1;
}
if (auto integer = dynamic_cast<IntegerSetting*>(setting)) {
lua_pushinteger(L, integer->getMin());
lua_setfield(L, -2, "min");
lua_pushinteger(L, integer->getMax());
lua_setfield(L, -2, "max");
lua::pushinteger(L, integer->getMin());
lua::setfield(L, "min");
lua::pushinteger(L, integer->getMax());
lua::setfield(L, "max");
return 1;
}
lua_pop(L, 1);
lua::pop(L);
throw std::runtime_error("unsupported setting type");
}
static int l_quit(lua_State*) {
static int l_quit(lua::State*) {
Window::setShouldClose(true);
return 0;
}
static int l_get_default_generator(lua_State* L) {
lua_pushstring(L, WorldGenerators::getDefaultGeneratorID().c_str());
return 1;
static int l_get_default_generator(lua::State* L) {
return lua::pushstring(L, WorldGenerators::getDefaultGeneratorID());
}
static int l_get_generators(lua_State* L) {
static int l_get_generators(lua::State* L) {
const auto& generators = WorldGenerators::getGeneratorsIDs();
lua_createtable(L, generators.size(), 0);
lua::createtable(L, generators.size(), 0);
int i = 0;
for (auto& id : generators) {
lua_pushstring(L, id.c_str());
lua_rawseti(L, -2, i + 1);
lua::pushstring(L, id);
lua::rawseti(L, i + 1);
i++;
}
return 1;
}
const luaL_Reg corelib [] = {
{"new_world", lua_wrap_errors<l_new_world>},
{"open_world", lua_wrap_errors<l_open_world>},
{"reopen_world", lua_wrap_errors<l_reopen_world>},
{"close_world", lua_wrap_errors<l_close_world>},
{"delete_world", lua_wrap_errors<l_delete_world>},
{"reconfig_packs", lua_wrap_errors<l_reconfig_packs>},
{"get_setting", lua_wrap_errors<l_get_setting>},
{"set_setting", lua_wrap_errors<l_set_setting>},
{"str_setting", lua_wrap_errors<l_str_setting>},
{"get_setting_info", lua_wrap_errors<l_get_setting_info>},
{"quit", lua_wrap_errors<l_quit>},
{"get_default_generator", lua_wrap_errors<l_get_default_generator>},
{"get_generators", lua_wrap_errors<l_get_generators>},
{"new_world", lua::wrap<l_new_world>},
{"open_world", lua::wrap<l_open_world>},
{"reopen_world", lua::wrap<l_reopen_world>},
{"close_world", lua::wrap<l_close_world>},
{"delete_world", lua::wrap<l_delete_world>},
{"reconfig_packs", lua::wrap<l_reconfig_packs>},
{"get_setting", lua::wrap<l_get_setting>},
{"set_setting", lua::wrap<l_set_setting>},
{"str_setting", lua::wrap<l_str_setting>},
{"get_setting_info", lua::wrap<l_get_setting_info>},
{"quit", lua::wrap<l_quit>},
{"get_default_generator", lua::wrap<l_get_default_generator>},
{"get_generators", lua::wrap<l_get_generators>},
{NULL, NULL}
};

View File

@ -1,7 +1,5 @@
#include "lua_commons.hpp"
#include "api_lua.hpp"
#include "LuaState.hpp"
#include "../scripting.hpp"
#include "../../../engine.hpp"
#include "../../../coders/gzip.hpp"
#include "../../../files/files.hpp"
@ -12,11 +10,6 @@
#include <filesystem>
namespace fs = std::filesystem;
namespace scripting {
extern lua::LuaState* state;
}
using namespace scripting;
static fs::path resolve_path(const std::string& path) {
@ -30,139 +23,133 @@ static fs::path resolve_path_soft(const std::string& path) {
return engine->getPaths()->resolve(path, false);
}
static int l_file_find(lua_State* L) {
std::string path = state->requireString(1);
static int l_file_find(lua::State* L) {
auto path = lua::require_string(L, 1);
try {
lua_pushstring(L, engine->getResPaths()->findRaw(path).c_str());
return 1;
return lua::pushstring(L, engine->getResPaths()->findRaw(path));
} catch (const std::runtime_error& err) {
return 0;
}
}
static int l_file_resolve(lua_State* L) {
fs::path path = resolve_path(state->requireString(1));
lua_pushstring(L, path.u8string().c_str());
return 1;
static int l_file_resolve(lua::State* L) {
fs::path path = resolve_path(lua::require_string(L, 1));
return lua::pushstring(L, path.u8string());
}
static int l_file_read(lua_State* L) {
fs::path path = resolve_path(state->requireString(1));
static int l_file_read(lua::State* L) {
fs::path path = resolve_path(lua::require_string(L, 1));
if (fs::is_regular_file(path)) {
lua_pushstring(L, files::read_string(path).c_str());
return 1;
return lua::pushstring(L, files::read_string(path));
}
throw std::runtime_error("file does not exists "+util::quote(path.u8string()));
}
static int l_file_write(lua_State*) {
fs::path path = resolve_path(state->requireString(1));
auto text = state->requireString(2);
static int l_file_write(lua::State* L) {
fs::path path = resolve_path(lua::require_string(L, 1));
std::string text = lua::require_string(L, 2);
files::write_string(path, text);
return 1;
}
static int l_file_remove(lua_State*) {
std::string rawpath = state->requireString(1);
static int l_file_remove(lua::State* L) {
std::string rawpath = lua::require_string(L, 1);
fs::path path = resolve_path(rawpath);
auto entryPoint = rawpath.substr(0, rawpath.find(':'));
if (entryPoint != "world") {
throw std::runtime_error("access denied");
}
return state->pushboolean(fs::remove(path));
return lua::pushboolean(L, fs::remove(path));
}
static int l_file_remove_tree(lua_State*) {
std::string rawpath = state->requireString(1);
static int l_file_remove_tree(lua::State* L) {
std::string rawpath = lua::require_string(L, 1);
fs::path path = resolve_path(rawpath);
auto entryPoint = rawpath.substr(0, rawpath.find(':'));
if (entryPoint != "world") {
throw std::runtime_error("access denied");
}
return state->pushinteger(fs::remove_all(path));
return lua::pushinteger(L, fs::remove_all(path));
}
static int l_file_exists(lua_State*) {
fs::path path = resolve_path_soft(state->requireString(1));
return state->pushboolean(fs::exists(path));
static int l_file_exists(lua::State* L) {
fs::path path = resolve_path_soft(lua::require_string(L, 1));
return lua::pushboolean(L, fs::exists(path));
}
static int l_file_isfile(lua_State*) {
fs::path path = resolve_path_soft(state->requireString(1));
return state->pushboolean(fs::is_regular_file(path));
static int l_file_isfile(lua::State* L) {
fs::path path = resolve_path_soft(lua::require_string(L, 1));
return lua::pushboolean(L, fs::is_regular_file(path));
}
static int l_file_isdir(lua_State*) {
fs::path path = resolve_path_soft(state->requireString(1));
return state->pushboolean(fs::is_directory(path));
static int l_file_isdir(lua::State* L) {
fs::path path = resolve_path_soft(lua::require_string(L, 1));
return lua::pushboolean(L, fs::is_directory(path));
}
static int l_file_length(lua_State* L) {
fs::path path = resolve_path(state->requireString(1));
static int l_file_length(lua::State* L) {
fs::path path = resolve_path(lua::require_string(L, 1));
if (fs::exists(path)){
lua_pushinteger(L, fs::file_size(path));
return lua::pushinteger(L, fs::file_size(path));
} else {
lua_pushinteger(L, -1);
return lua::pushinteger(L, -1);
}
return 1;
}
static int l_file_mkdir(lua_State* L) {
fs::path path = resolve_path(state->requireString(1));
lua_pushboolean(L, fs::create_directory(path));
return 1;
static int l_file_mkdir(lua::State* L) {
fs::path path = resolve_path(lua::require_string(L, 1));
return lua::pushboolean(L, fs::create_directory(path));
}
static int l_file_mkdirs(lua_State* L) {
fs::path path = resolve_path(state->requireString(1));
lua_pushboolean(L, fs::create_directories(path));
return 1;
static int l_file_mkdirs(lua::State* L) {
fs::path path = resolve_path(lua::require_string(L, 1));
return lua::pushboolean(L, fs::create_directories(path));
}
static int l_file_read_bytes(lua_State* L) {
fs::path path = resolve_path(state->requireString(1));
static int l_file_read_bytes(lua::State* L) {
fs::path path = resolve_path(lua::require_string(L, 1));
if (fs::is_regular_file(path)) {
size_t length = static_cast<size_t>(fs::file_size(path));
auto bytes = files::read_bytes(path, length);
lua_createtable(L, length, 0);
int newTable = lua_gettop(L);
lua::createtable(L, length, 0);
int newTable = lua::gettop(L);
for(size_t i = 0; i < length; i++) {
lua_pushinteger(L, bytes[i]);
lua_rawseti(L, newTable, i+1);
lua::pushinteger(L, bytes[i]);
lua::rawseti(L, i+1, newTable);
}
return 1;
}
throw std::runtime_error("file does not exists "+util::quote(path.u8string()));
}
static int read_bytes_from_table(lua_State* L, int tableIndex, std::vector<ubyte>& bytes) {
if(!lua_istable(L, tableIndex)) {
static int read_bytes_from_table(lua::State* L, int tableIndex, std::vector<ubyte>& bytes) {
if(!lua::istable(L, tableIndex)) {
throw std::runtime_error("table expected");
} else {
lua_pushnil(L);
while(lua_next(L, tableIndex - 1) != 0) {
const int byte = lua_tointeger(L, -1);
lua::pushnil(L);
while(lua::next(L, tableIndex - 1) != 0) {
const int byte = lua::tointeger(L, -1);
if(byte < 0 || byte > 255) {
throw std::runtime_error("invalid byte '"+std::to_string(byte)+"'");
}
bytes.push_back(byte);
lua_pop(L, 1);
lua::pop(L);
}
return 1;
}
}
static int l_file_write_bytes(lua_State* L) {
static int l_file_write_bytes(lua::State* L) {
int pathIndex = 1;
if(!lua_isstring(L, pathIndex)) {
if(!lua::isstring(L, pathIndex)) {
throw std::runtime_error("string expected");
}
fs::path path = resolve_path(state->requireString(pathIndex));
fs::path path = resolve_path(lua::require_string(L, pathIndex));
std::vector<ubyte> bytes;
@ -171,23 +158,22 @@ static int l_file_write_bytes(lua_State* L) {
if(result != 1) {
return result;
} else {
lua_pushboolean(L, files::write_bytes(path, bytes.data(), bytes.size()));
return 1;
return lua::pushboolean(L, files::write_bytes(path, bytes.data(), bytes.size()));
}
}
static int l_file_list_all_res(lua_State* L, const std::string& path) {
static int l_file_list_all_res(lua::State* L, const std::string& path) {
auto files = engine->getResPaths()->listdirRaw(path);
lua_createtable(L, files.size(), 0);
lua::createtable(L, files.size(), 0);
for (size_t i = 0; i < files.size(); i++) {
lua_pushstring(L, files[i].c_str());
lua_rawseti(L, -2, i+1);
lua::pushstring(L, files[i]);
lua::rawseti(L, i+1);
}
return 1;
}
static int l_file_list(lua_State* L) {
std::string dirname = state->requireString(1);
static int l_file_list(lua::State* L) {
std::string dirname = lua::require_string(L, 1);
if (dirname.find(':') == std::string::npos) {
return l_file_list_all_res(L, dirname);
}
@ -195,61 +181,59 @@ static int l_file_list(lua_State* L) {
if (!fs::is_directory(path)) {
throw std::runtime_error(util::quote(path.u8string())+" is not a directory");
}
lua_createtable(L, 0, 0);
lua::createtable(L, 0, 0);
size_t index = 1;
for (auto& entry : fs::directory_iterator(path)) {
auto name = entry.path().filename().u8string();
auto file = dirname + "/" + name;
lua_pushstring(L, file.c_str());
lua_rawseti(L, -2, index);
lua::pushstring(L, file);
lua::rawseti(L, index);
index++;
}
return 1;
}
static int l_file_gzip_compress(lua_State* L) {
fs::path path = resolve_path(state->requireString(1));
static int l_file_gzip_compress(lua::State* L) {
fs::path path = resolve_path(lua::require_string(L, 1));
if (fs::is_regular_file(path)) {
size_t length = static_cast<size_t>(fs::file_size(path));
auto compressed_bytes = gzip::compress(files::read_bytes(path, length).get(), length);
lua_pushboolean(L, files::write_bytes(path, compressed_bytes.data(), compressed_bytes.size()));
return 1;
return lua::pushboolean(L, files::write_bytes(path, compressed_bytes.data(), compressed_bytes.size()));
}
throw std::runtime_error("file does not exist " + util::quote(path.u8string()));
}
static int l_file_gzip_decompress(lua_State* L) {
fs::path path = resolve_path(state->requireString(1));
static int l_file_gzip_decompress(lua::State* L) {
fs::path path = resolve_path(lua::require_string(L, 1));
if (fs::is_regular_file(path)) {
size_t length = static_cast<size_t>(fs::file_size(path));
auto decompressed_bytes = gzip::decompress(files::read_bytes(path, length).get(), length);
lua_pushboolean(L, files::write_bytes(path, decompressed_bytes.data(), decompressed_bytes.size()));
return 1;
return lua::pushboolean(L, files::write_bytes(path, decompressed_bytes.data(), decompressed_bytes.size()));
}
throw std::runtime_error("file does not exist " + util::quote(path.u8string()));
}
const luaL_Reg filelib [] = {
{"exists", lua_wrap_errors<l_file_exists>},
{"find", lua_wrap_errors<l_file_find>},
{"isdir", lua_wrap_errors<l_file_isdir>},
{"isfile", lua_wrap_errors<l_file_isfile>},
{"length", lua_wrap_errors<l_file_length>},
{"list", lua_wrap_errors<l_file_list>},
{"mkdir", lua_wrap_errors<l_file_mkdir>},
{"mkdirs", lua_wrap_errors<l_file_mkdirs>},
{"read_bytes", lua_wrap_errors<l_file_read_bytes>},
{"read", lua_wrap_errors<l_file_read>},
{"remove", lua_wrap_errors<l_file_remove>},
{"remove_tree", lua_wrap_errors<l_file_remove_tree>},
{"resolve", lua_wrap_errors<l_file_resolve>},
{"write_bytes", lua_wrap_errors<l_file_write_bytes>},
{"write", lua_wrap_errors<l_file_write>},
{"gzip_compress", lua_wrap_errors<l_file_gzip_compress>},
{"gzip_decompress", lua_wrap_errors<l_file_gzip_decompress>},
{"exists", lua::wrap<l_file_exists>},
{"find", lua::wrap<l_file_find>},
{"isdir", lua::wrap<l_file_isdir>},
{"isfile", lua::wrap<l_file_isfile>},
{"length", lua::wrap<l_file_length>},
{"list", lua::wrap<l_file_list>},
{"mkdir", lua::wrap<l_file_mkdir>},
{"mkdirs", lua::wrap<l_file_mkdirs>},
{"read_bytes", lua::wrap<l_file_read_bytes>},
{"read", lua::wrap<l_file_read>},
{"remove", lua::wrap<l_file_remove>},
{"remove_tree", lua::wrap<l_file_remove_tree>},
{"resolve", lua::wrap<l_file_resolve>},
{"write_bytes", lua::wrap<l_file_write_bytes>},
{"write", lua::wrap<l_file_write>},
{"gzip_compress", lua::wrap<l_file_gzip_compress>},
{"gzip_decompress", lua::wrap<l_file_gzip_decompress>},
{NULL, NULL}
};

View File

@ -1,9 +1,5 @@
#include "lua_commons.hpp"
#include "api_lua.hpp"
#include "lua_util.hpp"
#include "LuaState.hpp"
#include "../scripting.hpp"
#include "../../../engine.hpp"
#include "../../../assets/Assets.hpp"
#include "../../../items/Inventories.hpp"
@ -23,19 +19,14 @@
#include "../../../world/Level.hpp"
using namespace gui;
namespace scripting {
extern lua::LuaState* state;
}
using namespace scripting;
struct DocumentNode {
UiDocument* document;
std::shared_ptr<UINode> node;
};
using namespace scripting;
static DocumentNode getDocumentNode(lua_State*, const std::string& name, const std::string& nodeName) {
static DocumentNode getDocumentNode(lua::State*, const std::string& name, const std::string& nodeName) {
auto doc = engine->getAssets()->getLayout(name);
if (doc == nullptr) {
throw std::runtime_error("document '"+name+"' not found");
@ -47,42 +38,42 @@ static DocumentNode getDocumentNode(lua_State*, const std::string& name, const s
return {doc, node};
}
static DocumentNode getDocumentNode(lua_State* L, int idx=1) {
lua_getfield(L, idx, "docname");
lua_getfield(L, idx, "name");
auto docname = state->requireString(-2);
auto name = state->requireString(-1);
static DocumentNode getDocumentNode(lua::State* L, int idx=1) {
lua::getfield(L, "docname", idx);
lua::getfield(L, "name", idx);
auto docname = lua::require_string(L, -2);
auto name = lua::require_string(L, -1);
auto node = getDocumentNode(L, docname, name);
lua_pop(L, 2);
lua::pop(L, 2);
return node;
}
static int l_menu_back(lua_State* L) {
static int l_menu_back(lua::State* L) {
auto node = getDocumentNode(L);
auto menu = dynamic_cast<Menu*>(node.node.get());
menu->back();
return 0;
}
static int l_menu_reset(lua_State* L) {
static int l_menu_reset(lua::State* L) {
auto node = getDocumentNode(L);
auto menu = dynamic_cast<Menu*>(node.node.get());
menu->reset();
return 0;
}
static int l_textbox_paste(lua_State* L) {
static int l_textbox_paste(lua::State* L) {
auto node = getDocumentNode(L);
auto box = dynamic_cast<TextBox*>(node.node.get());
auto text = state->requireString(2);
auto text = lua::require_string(L, 2);
box->paste(util::str2wstr_utf8(text));
return 0;
}
static int l_container_add(lua_State* L) {
static int l_container_add(lua::State* L) {
auto docnode = getDocumentNode(L);
auto node = dynamic_cast<Container*>(docnode.node.get());
auto xmlsrc = state->requireString(2);
auto xmlsrc = lua::require_string(L, 2);
try {
auto subnode = guiutil::create(xmlsrc, docnode.document->getEnvironment());
node->add(subnode);
@ -93,7 +84,7 @@ static int l_container_add(lua_State* L) {
return 0;
}
static int l_node_destruct(lua_State* L) {
static int l_node_destruct(lua::State* L) {
auto docnode = getDocumentNode(L);
auto node = std::dynamic_pointer_cast<Container>(docnode.node);
engine->getGUI()->postRunnable([node]() {
@ -105,7 +96,7 @@ static int l_node_destruct(lua_State* L) {
return 0;
}
static int l_container_clear(lua_State* L) {
static int l_container_clear(lua::State* L) {
auto node = getDocumentNode(L, 1);
if (auto container = std::dynamic_pointer_cast<Container>(node.node)) {
container->clear();
@ -113,230 +104,230 @@ static int l_container_clear(lua_State* L) {
return 0;
}
static int l_container_set_interval(lua_State* L) {
static int l_container_set_interval(lua::State* L) {
auto node = getDocumentNode(L, 1);
auto interval = state->tointeger(2) / 1000.0f;
auto interval = lua::tointeger(L, 2) / 1000.0f;
if (auto container = std::dynamic_pointer_cast<Container>(node.node)) {
state->pushvalue(3);
auto runnable = state->createRunnable();
lua::pushvalue(L, 3);
auto runnable = lua::create_runnable(L);
container->listenInterval(interval, runnable);
}
return 0;
}
static int l_move_into(lua_State* L) {
static int l_move_into(lua::State* L) {
auto node = getDocumentNode(L, 1);
auto dest = getDocumentNode(L, 2);
UINode::moveInto(node.node, std::dynamic_pointer_cast<Container>(dest.node));
return 0;
}
static int p_get_inventory(UINode* node) {
static int p_get_inventory(UINode* node, lua::State* L) {
if (auto inventory = dynamic_cast<InventoryView*>(node)) {
auto inv = inventory->getInventory();
return state->pushinteger(inv ? inv->getId() : 0);
return lua::pushinteger(L, inv ? inv->getId() : 0);
}
return 0;
}
static int p_get_reset(UINode* node) {
static int p_get_reset(UINode* node, lua::State* L) {
if (dynamic_cast<Menu*>(node)) {
return state->pushcfunction(l_menu_reset);
return lua::pushcfunction(L, l_menu_reset);
}
return 0;
}
static int p_get_back(UINode* node) {
static int p_get_back(UINode* node, lua::State* L) {
if (dynamic_cast<Menu*>(node)) {
return state->pushcfunction(l_menu_back);
return lua::pushcfunction(L, l_menu_back);
}
return 0;
}
static int p_get_paste(UINode* node) {
static int p_get_paste(UINode* node, lua::State* L) {
if (dynamic_cast<TextBox*>(node)) {
return state->pushcfunction(l_textbox_paste);
return lua::pushcfunction(L, l_textbox_paste);
}
return 0;
}
static int p_get_page(UINode* node) {
static int p_get_page(UINode* node, lua::State* L) {
if (auto menu = dynamic_cast<Menu*>(node)) {
return state->pushstring(menu->getCurrent().name);
return lua::pushstring(L, menu->getCurrent().name);
}
return 0;
}
static int p_is_checked(UINode* node) {
static int p_is_checked(UINode* node, lua::State* L) {
if (auto box = dynamic_cast<CheckBox*>(node)) {
return state->pushboolean(box->isChecked());
return lua::pushboolean(L, box->isChecked());
} else if (auto box = dynamic_cast<FullCheckBox*>(node)) {
return state->pushboolean(box->isChecked());
return lua::pushboolean(L, box->isChecked());
}
return 0;
}
static int p_get_value(UINode* node) {
static int p_get_value(UINode* node, lua::State* L) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
return state->pushnumber(bar->getValue());
return lua::pushnumber(L, bar->getValue());
}
return 0;
}
static int p_get_min(UINode* node) {
static int p_get_min(UINode* node, lua::State* L) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
return state->pushnumber(bar->getMin());
return lua::pushnumber(L, bar->getMin());
}
return 0;
}
static int p_get_max(UINode* node) {
static int p_get_max(UINode* node, lua::State* L) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
return state->pushnumber(bar->getMax());
return lua::pushnumber(L, bar->getMax());
}
return 0;
}
static int p_get_step(UINode* node) {
static int p_get_step(UINode* node, lua::State* L) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
return state->pushnumber(bar->getStep());
return lua::pushnumber(L, bar->getStep());
}
return 0;
}
static int p_get_track_width(UINode* node) {
static int p_get_track_width(UINode* node, lua::State* L) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
return state->pushnumber(bar->getTrackWidth());
return lua::pushnumber(L, bar->getTrackWidth());
}
return 0;
}
static int p_get_track_color(UINode* node) {
static int p_get_track_color(UINode* node, lua::State* L) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
return lua::pushcolor_arr(state->getLua(), bar->getTrackColor());
return lua::pushcolor_arr(L, bar->getTrackColor());
}
return 0;
}
static int p_is_valid(UINode* node) {
static int p_is_valid(UINode* node, lua::State* L) {
if (auto box = dynamic_cast<TextBox*>(node)) {
return state->pushboolean(box->validate());
return lua::pushboolean(L, box->validate());
}
return 0;
}
static int p_get_caret(UINode* node) {
static int p_get_caret(UINode* node, lua::State* L) {
if (auto box = dynamic_cast<TextBox*>(node)) {
return state->pushinteger(static_cast<integer_t>(box->getCaret()));
return lua::pushinteger(L, static_cast<integer_t>(box->getCaret()));
}
return 0;
}
static int p_get_placeholder(UINode* node) {
static int p_get_placeholder(UINode* node, lua::State* L) {
if (auto box = dynamic_cast<TextBox*>(node)) {
return state->pushstring(util::wstr2str_utf8(box->getPlaceholder()));
return lua::pushwstring(L, box->getPlaceholder());
}
return 0;
}
static int p_get_text(UINode* node) {
static int p_get_text(UINode* node, lua::State* L) {
if (auto button = dynamic_cast<Button*>(node)) {
return state->pushstring(util::wstr2str_utf8(button->getText()));
return lua::pushwstring(L, button->getText());
} else if (auto label = dynamic_cast<Label*>(node)) {
return state->pushstring(util::wstr2str_utf8(label->getText()));
return lua::pushwstring(L, label->getText());
} else if (auto box = dynamic_cast<TextBox*>(node)) {
return state->pushstring(util::wstr2str_utf8(box->getText()));
return lua::pushwstring(L, box->getText());
}
return 0;
}
static int p_get_editable(UINode* node) {
static int p_get_editable(UINode* node, lua::State* L) {
if (auto box = dynamic_cast<TextBox*>(node)) {
return state->pushboolean(box->isEditable());
return lua::pushboolean(L, box->isEditable());
}
return 0;
}
static int p_get_src(UINode* node) {
static int p_get_src(UINode* node, lua::State* L) {
if (auto image = dynamic_cast<Image*>(node)) {
return state->pushstring(image->getTexture());
return lua::pushstring(L, image->getTexture());
}
return 0;
}
static int p_get_add(UINode* node) {
static int p_get_add(UINode* node, lua::State* L) {
if (dynamic_cast<Container*>(node)) {
return state->pushcfunction(lua_wrap_errors<l_container_add>);
return lua::pushcfunction(L, lua::wrap<l_container_add>);
}
return 0;
}
static int p_get_destruct(UINode*) {
return state->pushcfunction(lua_wrap_errors<l_node_destruct>);
static int p_get_destruct(UINode*, lua::State* L) {
return lua::pushcfunction(L, lua::wrap<l_node_destruct>);
}
static int p_get_clear(UINode* node) {
static int p_get_clear(UINode* node, lua::State* L) {
if (dynamic_cast<Container*>(node)) {
return state->pushcfunction(lua_wrap_errors<l_container_clear>);
return lua::pushcfunction(L, lua::wrap<l_container_clear>);
}
return 0;
}
static int p_set_interval(UINode* node) {
static int p_set_interval(UINode* node, lua::State* L) {
if (dynamic_cast<Container*>(node)) {
return state->pushcfunction(lua_wrap_errors<l_container_set_interval>);
return lua::pushcfunction(L, lua::wrap<l_container_set_interval>);
}
return 0;
}
static int p_get_color(UINode* node) {
return lua::pushcolor_arr(state->getLua(), node->getColor());
static int p_get_color(UINode* node, lua::State* L) {
return lua::pushcolor_arr(L, node->getColor());
}
static int p_get_hover_color(UINode* node) {
return lua::pushcolor_arr(state->getLua(), node->getHoverColor());
static int p_get_hover_color(UINode* node, lua::State* L) {
return lua::pushcolor_arr(L, node->getHoverColor());
}
static int p_get_pressed_color(UINode* node) {
return lua::pushcolor_arr(state->getLua(), node->getPressedColor());
static int p_get_pressed_color(UINode* node, lua::State* L) {
return lua::pushcolor_arr(L, node->getPressedColor());
}
static int p_get_tooltip(UINode* node) {
return state->pushstring(util::wstr2str_utf8(node->getTooltip()));
static int p_get_tooltip(UINode* node, lua::State* L) {
return lua::pushwstring(L, node->getTooltip());
}
static int p_get_tooltip_delay(UINode* node) {
return state->pushnumber(node->getTooltipDelay());
static int p_get_tooltip_delay(UINode* node, lua::State* L) {
return lua::pushnumber(L, node->getTooltipDelay());
}
static int p_get_pos(UINode* node) {
return lua::pushvec2_arr(state->getLua(), node->getPos());
static int p_get_pos(UINode* node, lua::State* L) {
return lua::pushvec2_arr(L, node->getPos());
}
static int p_get_wpos(UINode* node) {
return lua::pushvec2_arr(state->getLua(), node->calcPos());
static int p_get_wpos(UINode* node, lua::State* L) {
return lua::pushvec2_arr(L, node->calcPos());
}
static int p_get_size(UINode* node) {
return lua::pushvec2_arr(state->getLua(), node->getSize());
static int p_get_size(UINode* node, lua::State* L) {
return lua::pushvec2_arr(L, node->getSize());
}
static int p_is_interactive(UINode* node) {
return state->pushboolean(node->isInteractive());
static int p_is_interactive(UINode* node, lua::State* L) {
return lua::pushboolean(L, node->isInteractive());
}
static int p_is_visible(UINode* node) {
return state->pushboolean(node->isVisible());
static int p_is_visible(UINode* node, lua::State* L) {
return lua::pushboolean(L, node->isVisible());
}
static int p_is_enabled(UINode* node) {
return state->pushboolean(node->isEnabled());
static int p_is_enabled(UINode* node, lua::State* L) {
return lua::pushboolean(L, node->isEnabled());
}
static int p_move_into(UINode*) {
return state->pushcfunction(l_move_into);
static int p_move_into(UINode*, lua::State* L) {
return lua::pushcfunction(L, l_move_into);
}
static int p_get_focused(UINode* node) {
return state->pushboolean(node->isFocused());
static int p_get_focused(UINode* node, lua::State* L) {
return lua::pushboolean(L, node->isFocused());
}
static int l_gui_getattr(lua_State* L) {
auto docname = state->requireString(1);
auto element = state->requireString(2);
auto attr = state->requireString(3);
static int l_gui_getattr(lua::State* L) {
auto docname = lua::require_string(L, 1);
auto element = lua::require_string(L, 2);
auto attr = lua::require_string(L, 3);
auto docnode = getDocumentNode(L, docname, element);
auto node = docnode.node;
static const std::unordered_map<std::string_view, std::function<int(UINode*)>> getters {
static const std::unordered_map<std::string_view, std::function<int(UINode*,lua::State*)>> getters {
{"color", p_get_color},
{"hoverColor", p_get_hover_color},
{"pressedColor", p_get_pressed_color},
@ -375,118 +366,118 @@ static int l_gui_getattr(lua_State* L) {
};
auto func = getters.find(attr);
if (func != getters.end()) {
return func->second(node.get());
return func->second(node.get(), L);
}
return 0;
}
static void p_set_color(UINode* node, int idx) {
node->setColor(state->tocolor(idx));
static void p_set_color(UINode* node, lua::State* L, int idx) {
node->setColor(lua::tocolor(L, idx));
}
static void p_set_hover_color(UINode* node, int idx) {
node->setHoverColor(state->tocolor(idx));
static void p_set_hover_color(UINode* node, lua::State* L, int idx) {
node->setHoverColor(lua::tocolor(L, idx));
}
static void p_set_pressed_color(UINode* node, int idx) {
node->setPressedColor(state->tocolor(idx));
static void p_set_pressed_color(UINode* node, lua::State* L, int idx) {
node->setPressedColor(lua::tocolor(L, idx));
}
static void p_set_tooltip(UINode* node, int idx) {
node->setTooltip(util::str2wstr_utf8(state->requireString(idx)));
static void p_set_tooltip(UINode* node, lua::State* L, int idx) {
node->setTooltip(lua::require_wstring(L, idx));
}
static void p_set_tooltip_delay(UINode* node, int idx) {
node->setTooltipDelay(state->tonumber(idx));
static void p_set_tooltip_delay(UINode* node, lua::State* L, int idx) {
node->setTooltipDelay(lua::tonumber(L, idx));
}
static void p_set_pos(UINode* node, int idx) {
node->setPos(state->tovec2(idx));
static void p_set_pos(UINode* node, lua::State* L, int idx) {
node->setPos(lua::tovec2(L, idx));
}
static void p_set_wpos(UINode* node, int idx) {
node->setPos(state->tovec2(idx)-node->calcPos());
static void p_set_wpos(UINode* node, lua::State* L, int idx) {
node->setPos(lua::tovec2(L, idx)-node->calcPos());
}
static void p_set_size(UINode* node, int idx) {
node->setSize(state->tovec2(idx));
static void p_set_size(UINode* node, lua::State* L, int idx) {
node->setSize(lua::tovec2(L, idx));
}
static void p_set_interactive(UINode* node, int idx) {
node->setInteractive(state->toboolean(idx));
static void p_set_interactive(UINode* node, lua::State* L, int idx) {
node->setInteractive(lua::toboolean(L, idx));
}
static void p_set_visible(UINode* node, int idx) {
node->setVisible(state->toboolean(idx));
static void p_set_visible(UINode* node, lua::State* L, int idx) {
node->setVisible(lua::toboolean(L, idx));
}
static void p_set_enabled(UINode* node, int idx) {
node->setEnabled(state->toboolean(idx));
static void p_set_enabled(UINode* node, lua::State* L, int idx) {
node->setEnabled(lua::toboolean(L, idx));
}
static void p_set_placeholder(UINode* node, int idx) {
static void p_set_placeholder(UINode* node, lua::State* L, int idx) {
if (auto box = dynamic_cast<TextBox*>(node)) {
box->setPlaceholder(util::str2wstr_utf8(state->requireString(idx)));
box->setPlaceholder(lua::require_wstring(L, idx));
}
}
static void p_set_text(UINode* node, int idx) {
static void p_set_text(UINode* node, lua::State* L, int idx) {
if (auto label = dynamic_cast<Label*>(node)) {
label->setText(util::str2wstr_utf8(state->requireString(idx)));
label->setText(lua::require_wstring(L, idx));
} else if (auto button = dynamic_cast<Button*>(node)) {
button->setText(util::str2wstr_utf8(state->requireString(idx)));
button->setText(lua::require_wstring(L, idx));
} else if (auto box = dynamic_cast<TextBox*>(node)) {
box->setText(util::str2wstr_utf8(state->requireString(idx)));
box->setText(lua::require_wstring(L, idx));
}
}
static void p_set_caret(UINode* node, int idx) {
static void p_set_caret(UINode* node, lua::State* L, int idx) {
if (auto box = dynamic_cast<TextBox*>(node)) {
box->setCaret(static_cast<ptrdiff_t>(state->tointeger(idx)));
box->setCaret(static_cast<ptrdiff_t>(lua::tointeger(L, idx)));
}
}
static void p_set_editable(UINode* node, int idx) {
static void p_set_editable(UINode* node, lua::State* L, int idx) {
if (auto box = dynamic_cast<TextBox*>(node)) {
box->setEditable(state->toboolean(idx));
box->setEditable(lua::toboolean(L, idx));
}
}
static void p_set_src(UINode* node, int idx) {
static void p_set_src(UINode* node, lua::State* L, int idx) {
if (auto image = dynamic_cast<Image*>(node)) {
image->setTexture(state->requireString(idx));
image->setTexture(lua::require_string(L, idx));
}
}
static void p_set_value(UINode* node, int idx) {
static void p_set_value(UINode* node, lua::State* L, int idx) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
bar->setValue(state->tonumber(idx));
bar->setValue(lua::tonumber(L, idx));
}
}
static void p_set_min(UINode* node, int idx) {
static void p_set_min(UINode* node, lua::State* L, int idx) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
bar->setMin(state->tonumber(idx));
bar->setMin(lua::tonumber(L, idx));
}
}
static void p_set_max(UINode* node, int idx) {
static void p_set_max(UINode* node, lua::State* L, int idx) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
bar->setMax(state->tonumber(idx));
bar->setMax(lua::tonumber(L, idx));
}
}
static void p_set_step(UINode* node, int idx) {
static void p_set_step(UINode* node, lua::State* L, int idx) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
bar->setStep(state->tonumber(idx));
bar->setStep(lua::tonumber(L, idx));
}
}
static void p_set_track_width(UINode* node, int idx) {
static void p_set_track_width(UINode* node, lua::State* L, int idx) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
bar->setTrackWidth(state->tointeger(idx));
bar->setTrackWidth(lua::tointeger(L, idx));
}
}
static void p_set_track_color(UINode* node, int idx) {
static void p_set_track_color(UINode* node, lua::State* L, int idx) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
bar->setTrackColor(state->tocolor(idx));
bar->setTrackColor(lua::tocolor(L, idx));
}
}
static void p_set_checked(UINode* node, int idx) {
static void p_set_checked(UINode* node, lua::State* L, int idx) {
if (auto box = dynamic_cast<CheckBox*>(node)) {
box->setChecked(state->toboolean(idx));
box->setChecked(lua::toboolean(L, idx));
} else if (auto box = dynamic_cast<FullCheckBox*>(node)) {
box->setChecked(state->toboolean(idx));
box->setChecked(lua::toboolean(L, idx));
}
}
static void p_set_page(UINode* node, int idx) {
static void p_set_page(UINode* node, lua::State* L, int idx) {
if (auto menu = dynamic_cast<Menu*>(node)) {
menu->setPage(state->requireString(idx));
menu->setPage(lua::require_string(L, idx));
}
}
static void p_set_inventory(UINode* node, int idx) {
static void p_set_inventory(UINode* node, lua::State* L, int idx) {
if (auto view = dynamic_cast<InventoryView*>(node)) {
auto inventory = level->inventories->get(state->tointeger(idx));
auto inventory = level->inventories->get(lua::tointeger(L, idx));
if (inventory == nullptr) {
view->unbind();
} else {
@ -494,23 +485,23 @@ static void p_set_inventory(UINode* node, int idx) {
}
}
}
static void p_set_focused(const std::shared_ptr<UINode> &node, int idx) {
if (state->toboolean(idx) && !node->isFocused()) {
scripting::engine->getGUI()->setFocus(node);
static void p_set_focused(const std::shared_ptr<UINode> &node, lua::State* L, int idx) {
if (lua::toboolean(L, idx) && !node->isFocused()) {
engine->getGUI()->setFocus(node);
} else if (node->isFocused()){
node->defocus();
}
}
static int l_gui_setattr(lua_State* L) {
auto docname = state->requireString(1);
auto element = state->requireString(2);
auto attr = state->requireString(3);
static int l_gui_setattr(lua::State* L) {
auto docname = lua::require_string(L, 1);
auto element = lua::require_string(L, 2);
auto attr = lua::require_string(L, 3);
auto docnode = getDocumentNode(L, docname, element);
auto node = docnode.node;
static const std::unordered_map<std::string_view, std::function<void(UINode*,int)>> setters {
static const std::unordered_map<std::string_view, std::function<void(UINode*,lua::State*,int)>> setters {
{"color", p_set_color},
{"hoverColor", p_set_hover_color},
{"pressedColor", p_set_pressed_color},
@ -539,42 +530,42 @@ static int l_gui_setattr(lua_State* L) {
};
auto func = setters.find(attr);
if (func != setters.end()) {
func->second(node.get(), 4);
func->second(node.get(), L, 4);
}
static const std::unordered_map<std::string_view, std::function<void(std::shared_ptr<UINode>,int)>> setters2 {
static const std::unordered_map<std::string_view, std::function<void(std::shared_ptr<UINode>,lua::State*,int)>> setters2 {
{"focused", p_set_focused},
};
auto func2 = setters2.find(attr);
if (func2 != setters2.end()) {
func2->second(node, 4);
func2->second(node, L, 4);
}
return 0;
}
static int l_gui_get_env(lua_State* L) {
auto name = state->requireString(1);
auto doc = scripting::engine->getAssets()->getLayout(name);
static int l_gui_get_env(lua::State* L) {
auto name = lua::require_string(L, 1);
auto doc = engine->getAssets()->getLayout(name);
if (doc == nullptr) {
throw std::runtime_error("document '"+std::string(name)+"' not found");
}
lua_getglobal(L, lua::LuaState::envName(*doc->getEnvironment()).c_str());
lua::getglobal(L, lua::env_name(*doc->getEnvironment()));
return 1;
}
static int l_gui_str(lua_State* L) {
auto text = util::str2wstr_utf8(state->requireString(1));
if (!lua_isnoneornil(L, 2)) {
auto context = util::str2wstr_utf8(state->requireString(2));
lua_pushstring(L, util::wstr2str_utf8(langs::get(text, context)).c_str());
static int l_gui_str(lua::State* L) {
auto text = lua::require_wstring(L, 1);
if (!lua::isnoneornil(L, 2)) {
auto context = lua::require_wstring(L, 2);
lua::pushwstring(L, langs::get(text, context));
} else {
lua_pushstring(L, util::wstr2str_utf8(langs::get(text)).c_str());
lua::pushwstring(L, langs::get(text));
}
return 1;
}
static int l_gui_reindex(lua_State* L) {
auto name = state->requireString(1);
auto doc = scripting::engine->getAssets()->getLayout(name);
static int l_gui_reindex(lua::State* L) {
auto name = lua::require_string(L, 1);
auto doc = engine->getAssets()->getLayout(name);
if (doc == nullptr) {
throw std::runtime_error("document '"+std::string(name)+"' not found");
}
@ -583,29 +574,29 @@ static int l_gui_reindex(lua_State* L) {
}
/// @brief gui.get_locales_info() -> table of tables
static int l_gui_get_locales_info(lua_State* L) {
static int l_gui_get_locales_info(lua::State* L) {
auto& locales = langs::locales_info;
lua_createtable(L, 0, locales.size());
lua::createtable(L, 0, locales.size());
for (auto& entry : locales) {
lua_createtable(L, 0, 1);
lua_pushstring(L, entry.second.name.c_str());
lua_setfield(L, -2, "name");
lua_setfield(L, -2, entry.first.c_str());
lua::createtable(L, 0, 1);
lua::pushstring(L, entry.second.name);
lua::setfield(L, "name");
lua::setfield(L, entry.first);
}
return 1;
}
static int l_gui_getviewport(lua_State* L) {
return lua::pushvec2_arr(L, scripting::engine->getGUI()->getContainer()->getSize());
static int l_gui_getviewport(lua::State* L) {
return lua::pushvec2_arr(L, engine->getGUI()->getContainer()->getSize());
}
const luaL_Reg guilib [] = {
{"get_viewport", lua_wrap_errors<l_gui_getviewport>},
{"getattr", lua_wrap_errors<l_gui_getattr>},
{"setattr", lua_wrap_errors<l_gui_setattr>},
{"get_env", lua_wrap_errors<l_gui_get_env>},
{"str", lua_wrap_errors<l_gui_str>},
{"get_locales_info", lua_wrap_errors<l_gui_get_locales_info>},
{"__reindex", lua_wrap_errors<l_gui_reindex>},
{"get_viewport", lua::wrap<l_gui_getviewport>},
{"getattr", lua::wrap<l_gui_getattr>},
{"setattr", lua::wrap<l_gui_setattr>},
{"get_env", lua::wrap<l_gui_get_env>},
{"str", lua::wrap<l_gui_str>},
{"get_locales_info", lua::wrap<l_gui_get_locales_info>},
{"__reindex", lua::wrap<l_gui_reindex>},
{NULL, NULL}
};

View File

@ -1,6 +1,4 @@
#include "lua_commons.hpp"
#include "api_lua.hpp"
#include "LuaState.hpp"
#include "../../../assets/Assets.hpp"
#include "../../../content/Content.hpp"
@ -16,7 +14,6 @@
#include "../../../voxels/Chunks.hpp"
#include "../../../voxels/voxel.hpp"
#include "../../../world/Level.hpp"
#include "../scripting.hpp"
#include <iostream>
#include <glm/glm.hpp>
@ -24,65 +21,66 @@
namespace scripting {
extern Hud* hud;
}
using namespace scripting;
static int l_hud_open_inventory(lua_State*) {
if (!scripting::hud->isInventoryOpen()) {
scripting::hud->openInventory();
static int l_hud_open_inventory(lua::State*) {
if (!hud->isInventoryOpen()) {
hud->openInventory();
}
return 0;
}
static int l_hud_close_inventory(lua_State*) {
if (scripting::hud->isInventoryOpen()) {
scripting::hud->closeInventory();
static int l_hud_close_inventory(lua::State*) {
if (hud->isInventoryOpen()) {
hud->closeInventory();
}
return 0;
}
static int l_hud_open_block(lua_State* L) {
auto x = lua_tointeger(L, 1);
auto y = lua_tointeger(L, 2);
auto z = lua_tointeger(L, 3);
bool playerInventory = !lua_toboolean(L, 4);
static int l_hud_open_block(lua::State* L) {
auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3);
bool playerInventory = !lua::toboolean(L, 4);
voxel* vox = scripting::level->chunks->get(x, y, z);
auto vox = level->chunks->get(x, y, z);
if (vox == nullptr) {
throw std::runtime_error("block does not exists at " +
std::to_string(x) + " " + std::to_string(y) + " " + std::to_string(z)
);
}
auto def = scripting::content->getIndices()->getBlockDef(vox->id);
auto assets = scripting::engine->getAssets();
auto def = content->getIndices()->getBlockDef(vox->id);
auto assets = engine->getAssets();
auto layout = assets->getLayout(def->uiLayout);
if (layout == nullptr) {
throw std::runtime_error("block '"+def->name+"' has no ui layout");
}
auto id = scripting::blocks->createBlockInventory(x, y, z);
scripting::hud->openInventory(
glm::ivec3(x, y, z), layout, scripting::level->inventories->get(id), playerInventory
auto id = blocks->createBlockInventory(x, y, z);
hud->openInventory(
glm::ivec3(x, y, z), layout, level->inventories->get(id), playerInventory
);
lua_pushinteger(L, id);
lua_pushstring(L, def->uiLayout.c_str());
lua::pushinteger(L, id);
lua::pushstring(L, def->uiLayout);
return 2;
}
static int l_hud_show_overlay(lua_State* L) {
const char* name = lua_tostring(L, 1);
bool playerInventory = lua_toboolean(L, 2);
static int l_hud_show_overlay(lua::State* L) {
auto name = lua::tostring(L, 1);
bool playerInventory = lua::toboolean(L, 2);
auto assets = scripting::engine->getAssets();
auto assets = engine->getAssets();
auto layout = assets->getLayout(name);
if (layout == nullptr) {
throw std::runtime_error("there is no ui layout "+util::quote(name));
}
scripting::hud->showOverlay(layout, playerInventory);
hud->showOverlay(layout, playerInventory);
return 0;
}
static UiDocument* require_layout(lua_State* L, const char* name) {
auto assets = scripting::engine->getAssets();
static UiDocument* require_layout(const char* name) {
auto assets = engine->getAssets();
auto layout = assets->getLayout(name);
if (layout == nullptr) {
throw std::runtime_error("layout '"+std::string(name)+"' is not found");
@ -90,54 +88,52 @@ static UiDocument* require_layout(lua_State* L, const char* name) {
return layout;
}
static int l_hud_open_permanent(lua_State* L) {
auto layout = require_layout(L, lua_tostring(L, 1));
scripting::hud->openPermanent(layout);
static int l_hud_open_permanent(lua::State* L) {
auto layout = require_layout(lua::tostring(L, 1));
hud->openPermanent(layout);
return 0;
}
static int l_hud_close(lua_State* L) {
auto layout = require_layout(L, lua_tostring(L, 1));
scripting::hud->remove(layout->getRoot());
static int l_hud_close(lua::State* L) {
auto layout = require_layout(lua::tostring(L, 1));
hud->remove(layout->getRoot());
return 0;
}
static int l_hud_pause(lua_State*) {
scripting::hud->setPause(true);
static int l_hud_pause(lua::State*) {
hud->setPause(true);
return 0;
}
static int l_hud_resume(lua_State*) {
scripting::hud->setPause(false);
static int l_hud_resume(lua::State*) {
hud->setPause(false);
return 0;
}
static int l_hud_get_block_inventory(lua_State* L) {
auto inventory = scripting::hud->getBlockInventory();
static int l_hud_get_block_inventory(lua::State* L) {
auto inventory = hud->getBlockInventory();
if (inventory == nullptr) {
lua_pushinteger(L, 0);
return lua::pushinteger(L, 0);
} else {
lua_pushinteger(L, inventory->getId());
return lua::pushinteger(L, inventory->getId());
}
return 1;
}
static int l_hud_get_player(lua_State* L) {
auto player = scripting::hud->getPlayer();
lua_pushinteger(L, player->getId());
return 1;
static int l_hud_get_player(lua::State* L) {
auto player = hud->getPlayer();
return lua::pushinteger(L, player->getId());
}
const luaL_Reg hudlib [] = {
{"open_inventory", lua_wrap_errors<l_hud_open_inventory>},
{"close_inventory", lua_wrap_errors<l_hud_close_inventory>},
{"open_block", lua_wrap_errors<l_hud_open_block>},
{"open_permanent", lua_wrap_errors<l_hud_open_permanent>},
{"show_overlay", lua_wrap_errors<l_hud_show_overlay>},
{"get_block_inventory", lua_wrap_errors<l_hud_get_block_inventory>},
{"close", lua_wrap_errors<l_hud_close>},
{"pause", lua_wrap_errors<l_hud_pause>},
{"resume", lua_wrap_errors<l_hud_resume>},
{"get_player", lua_wrap_errors<l_hud_get_player>},
{"open_inventory", lua::wrap<l_hud_open_inventory>},
{"close_inventory", lua::wrap<l_hud_close_inventory>},
{"open_block", lua::wrap<l_hud_open_block>},
{"open_permanent", lua::wrap<l_hud_open_permanent>},
{"show_overlay", lua::wrap<l_hud_show_overlay>},
{"get_block_inventory", lua::wrap<l_hud_get_block_inventory>},
{"close", lua::wrap<l_hud_close>},
{"pause", lua::wrap<l_hud_pause>},
{"resume", lua::wrap<l_hud_resume>},
{"get_player", lua::wrap<l_hud_get_player>},
{NULL, NULL}
};

View File

@ -1,8 +1,4 @@
#include "api_lua.hpp"
#include "lua_util.hpp"
#include "lua_commons.hpp"
#include "LuaState.hpp"
#include "../scripting.hpp"
#include "../../../window/input.hpp"
#include "../../../window/Events.hpp"
@ -13,32 +9,28 @@
#include "../../../engine.hpp"
namespace scripting {
extern lua::LuaState* state;
extern Hud* hud;
}
using namespace scripting;
static int l_keycode(lua_State* L) {
const char* name = state->requireString(1);
lua_pushinteger(L, static_cast<int>(input_util::keycode_from(name)));
return 1;
static int l_keycode(lua::State* L) {
auto name = lua::require_string(L, 1);
return lua::pushinteger(L, static_cast<int>(input_util::keycode_from(name)));
}
static int l_mousecode(lua_State* L) {
const char* name = state->requireString(1);
lua_pushinteger(L, static_cast<int>(input_util::mousecode_from(name)));
return 1;
static int l_mousecode(lua::State* L) {
auto name = lua::require_string(L, 1);
return lua::pushinteger(L, static_cast<int>(input_util::mousecode_from(name)));
}
static int l_add_callback(lua_State*) {
auto bindname = state->requireString(1);
static int l_add_callback(lua::State* L) {
auto bindname = lua::require_string(L, 1);
const auto& bind = Events::bindings.find(bindname);
if (bind == Events::bindings.end()) {
throw std::runtime_error("unknown binding "+util::quote(bindname));
}
state->pushvalue(2);
runnable actual_callback = state->createRunnable();
lua::pushvalue(L, 2);
runnable actual_callback = lua::create_runnable(L);
runnable callback = [=]() {
if (!scripting::engine->getGUI()->isFocusCaught()) {
actual_callback();
@ -52,29 +44,29 @@ static int l_add_callback(lua_State*) {
return 0;
}
static int l_get_mouse_pos(lua_State* L) {
static int l_get_mouse_pos(lua::State* L) {
return lua::pushvec2_arr(L, Events::cursor);
}
static int l_get_bindings(lua_State* L) {
static int l_get_bindings(lua::State* L) {
auto& bindings = Events::bindings;
lua_createtable(L, bindings.size(), 0);
lua::createtable(L, bindings.size(), 0);
int i = 0;
for (auto& entry : bindings) {
lua_pushstring(L, entry.first.c_str());
lua_rawseti(L, -2, i + 1);
lua::pushstring(L, entry.first);
lua::rawseti(L, i + 1);
i++;
}
return 1;
}
const luaL_Reg inputlib [] = {
{"keycode", lua_wrap_errors<l_keycode>},
{"mousecode", lua_wrap_errors<l_mousecode>},
{"add_callback", lua_wrap_errors<l_add_callback>},
{"get_mouse_pos", lua_wrap_errors<l_get_mouse_pos>},
{"get_bindings", lua_wrap_errors<l_get_bindings>},
{"keycode", lua::wrap<l_keycode>},
{"mousecode", lua::wrap<l_mousecode>},
{"add_callback", lua::wrap<l_add_callback>},
{"get_mouse_pos", lua::wrap<l_get_mouse_pos>},
{"get_bindings", lua::wrap<l_get_bindings>},
{NULL, NULL}
};

View File

@ -1,23 +1,21 @@
#include "lua_commons.hpp"
#include "api_lua.hpp"
#include "lua_util.hpp"
#include "../scripting.hpp"
#include "../../../content/Content.hpp"
#include "../../../world/Level.hpp"
#include "../../../items/ItemStack.hpp"
#include "../../../items/Inventories.hpp"
#include "../../../logic/BlocksController.hpp"
using namespace scripting;
static void validate_itemid(itemid_t id) {
if (id >= scripting::indices->countItemDefs()) {
if (id >= indices->countItemDefs()) {
throw std::runtime_error("invalid item id");
}
}
static std::shared_ptr<Inventory> get_inventory(int64_t id) {
auto inv = scripting::level->inventories->get(id);
auto inv = level->inventories->get(id);
if (inv == nullptr) {
throw std::runtime_error("inventory not found: "+std::to_string(id));
}
@ -25,7 +23,7 @@ static std::shared_ptr<Inventory> get_inventory(int64_t id) {
}
static std::shared_ptr<Inventory> get_inventory(int64_t id, int arg) {
auto inv = scripting::level->inventories->get(id);
auto inv = level->inventories->get(id);
if (inv == nullptr) {
throw std::runtime_error("inventory not found: "+std::to_string(id)+
" argument "+std::to_string(arg));
@ -39,22 +37,22 @@ static void validate_slotid(int slotid, Inventory* inv) {
}
}
static int l_inventory_get(lua_State* L) {
lua_Integer invid = lua_tointeger(L, 1);
lua_Integer slotid = lua_tointeger(L, 2);
static int l_inventory_get(lua::State* L) {
auto invid = lua::tointeger(L, 1);
auto slotid = lua::tointeger(L, 2);
auto inv = get_inventory(invid);
validate_slotid(slotid, inv.get());
const ItemStack& item = inv->getSlot(slotid);
lua_pushinteger(L, item.getItemId());
lua_pushinteger(L, item.getCount());
lua::pushinteger(L, item.getItemId());
lua::pushinteger(L, item.getCount());
return 2;
}
static int l_inventory_set(lua_State* L) {
lua_Integer invid = lua_tointeger(L, 1);
lua_Integer slotid = lua_tointeger(L, 2);
lua_Integer itemid = lua_tointeger(L, 3);
lua_Integer count = lua_tointeger(L, 4);
static int l_inventory_set(lua::State* L) {
auto invid = lua::tointeger(L, 1);
auto slotid = lua::tointeger(L, 2);
auto itemid = lua::tointeger(L, 3);
auto count = lua::tointeger(L, 4);
validate_itemid(itemid);
auto inv = get_inventory(invid);
@ -65,91 +63,86 @@ static int l_inventory_set(lua_State* L) {
return 0;
}
static int l_inventory_size(lua_State* L) {
lua_Integer invid = lua_tointeger(L, 1);
static int l_inventory_size(lua::State* L) {
auto invid = lua::tointeger(L, 1);
auto inv = get_inventory(invid);
lua_pushinteger(L, inv->size());
return 1;
return lua::pushinteger(L, inv->size());
}
static int l_inventory_add(lua_State* L) {
lua_Integer invid = lua_tointeger(L, 1);
lua_Integer itemid = lua_tointeger(L, 2);
lua_Integer count = lua_tointeger(L, 3);
static int l_inventory_add(lua::State* L) {
auto invid = lua::tointeger(L, 1);
auto itemid = lua::tointeger(L, 2);
auto count = lua::tointeger(L, 3);
validate_itemid(itemid);
auto inv = get_inventory(invid);
ItemStack item(itemid, count);
inv->move(item, scripting::indices);
lua_pushinteger(L, item.getCount());
return 1;
inv->move(item, indices);
return lua::pushinteger(L, item.getCount());
}
static int l_inventory_get_block(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3);
int64_t id = scripting::blocks->createBlockInventory(x, y, z);
lua_pushinteger(L, id);
return 1;
static int l_inventory_get_block(lua::State* L) {
auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3);
int64_t id = blocks->createBlockInventory(x, y, z);
return lua::pushinteger(L, id);
}
static int l_inventory_bind_block(lua_State* L) {
lua_Integer id = lua_tointeger(L, 1);
lua_Integer x = lua_tointeger(L, 2);
lua_Integer y = lua_tointeger(L, 3);
lua_Integer z = lua_tointeger(L, 4);
scripting::blocks->bindInventory(id, x, y, z);
static int l_inventory_bind_block(lua::State* L) {
auto id = lua::tointeger(L, 1);
auto x = lua::tointeger(L, 2);
auto y = lua::tointeger(L, 3);
auto z = lua::tointeger(L, 4);
blocks->bindInventory(id, x, y, z);
return 0;
}
static int l_inventory_unbind_block(lua_State* L) {
lua_Integer x = lua_tointeger(L, 1);
lua_Integer y = lua_tointeger(L, 2);
lua_Integer z = lua_tointeger(L, 3);
scripting::blocks->unbindInventory(x, y, z);
static int l_inventory_unbind_block(lua::State* L) {
auto x = lua::tointeger(L, 1);
auto y = lua::tointeger(L, 2);
auto z = lua::tointeger(L, 3);
blocks->unbindInventory(x, y, z);
return 0;
}
static int l_inventory_clone(lua_State* L) {
lua_Integer id = lua_tointeger(L, 1);
auto clone = scripting::level->inventories->clone(id);
static int l_inventory_clone(lua::State* L) {
auto id = lua::tointeger(L, 1);
auto clone = level->inventories->clone(id);
if (clone == nullptr) {
lua_pushinteger(L, 0);
return 1;
return lua::pushinteger(L, 0);
}
lua_pushinteger(L, clone->getId());
return 1;
return lua::pushinteger(L, clone->getId());
}
static int l_inventory_move(lua_State* L) {
lua_Integer invAid = lua_tointeger(L, 1);
lua_Integer slotAid = lua_tointeger(L, 2);
static int l_inventory_move(lua::State* L) {
auto invAid = lua::tointeger(L, 1);
auto slotAid = lua::tointeger(L, 2);
auto invA = get_inventory(invAid, 1);
validate_slotid(slotAid, invA.get());
lua_Integer invBid = lua_tointeger(L, 3);
lua_Integer slotBid = lua_isnil(L, 4) ? -1 : lua_tointeger(L, 4);
auto invBid = lua::tointeger(L, 3);
auto slotBid = lua::isnil(L, 4) ? -1 : lua::tointeger(L, 4);
auto invB = get_inventory(invBid, 3);
auto& slot = invA->getSlot(slotAid);
if (slotBid == -1) {
invB->move(slot, scripting::content->getIndices());
invB->move(slot, content->getIndices());
} else {
invB->move(slot, scripting::content->getIndices(), slotBid, slotBid+1);
invB->move(slot, content->getIndices(), slotBid, slotBid+1);
}
return 0;
}
const luaL_Reg inventorylib [] = {
{"get", lua_wrap_errors<l_inventory_get>},
{"set", lua_wrap_errors<l_inventory_set>},
{"size", lua_wrap_errors<l_inventory_size>},
{"add", lua_wrap_errors<l_inventory_add>},
{"move", lua_wrap_errors<l_inventory_move>},
{"get_block", lua_wrap_errors<l_inventory_get_block>},
{"bind_block", lua_wrap_errors<l_inventory_bind_block>},
{"unbind_block", lua_wrap_errors<l_inventory_unbind_block>},
{"clone", lua_wrap_errors<l_inventory_clone>},
{"get", lua::wrap<l_inventory_get>},
{"set", lua::wrap<l_inventory_set>},
{"size", lua::wrap<l_inventory_size>},
{"add", lua::wrap<l_inventory_add>},
{"move", lua::wrap<l_inventory_move>},
{"get_block", lua::wrap<l_inventory_get_block>},
{"bind_block", lua::wrap<l_inventory_bind_block>},
{"unbind_block", lua::wrap<l_inventory_unbind_block>},
{"clone", lua::wrap<l_inventory_clone>},
{NULL, NULL}
};

View File

@ -1,53 +1,43 @@
#include "lua_commons.hpp"
#include "api_lua.hpp"
#include "LuaState.hpp"
#include "../scripting.hpp"
#include "../../../content/Content.hpp"
#include "../../../items/ItemDef.hpp"
namespace scripting {
extern lua::LuaState* state;
}
using namespace scripting;
static int l_item_name(lua_State* L) {
auto indices = scripting::content->getIndices();
lua_Number id = lua_tointeger(L, 1);
static int l_item_name(lua::State* L) {
auto indices = content->getIndices();
auto id = lua::tointeger(L, 1);
if (static_cast<size_t>(id) >= indices->countItemDefs()) {
return 0;
}
auto def = indices->getItemDef(id);
lua_pushstring(L, def->name.c_str());
return 1;
return lua::pushstring(L, def->name);
}
static int l_item_index(lua_State* L) {
auto name = scripting::state->requireString(1);
lua_pushinteger(L, scripting::content->requireItem(name).rt.id);
return 1;
static int l_item_index(lua::State* L) {
auto name = lua::require_string(L, 1);
return lua::pushinteger(L, content->requireItem(name).rt.id);
}
static int l_item_stack_size(lua_State* L) {
auto indices = scripting::content->getIndices();
lua_Integer id = lua_tointeger(L, 1);
if (id < 0 || size_t(id) >= indices->countItemDefs()) {
static int l_item_stack_size(lua::State* L) {
auto indices = content->getIndices();
auto id = lua::tointeger(L, 1);
if (static_cast<size_t>(id) >= indices->countItemDefs()) {
return 0;
}
auto def = indices->getItemDef(id);
lua_pushinteger(L, def->stackSize);
return 1;
return lua::pushinteger(L, def->stackSize);
}
static int l_item_defs_count(lua_State* L) {
lua_pushinteger(L, scripting::indices->countItemDefs());
return 1;
static int l_item_defs_count(lua::State* L) {
return lua::pushinteger(L, indices->countItemDefs());
}
const luaL_Reg itemlib [] = {
{"index", lua_wrap_errors<l_item_index>},
{"name", lua_wrap_errors<l_item_name>},
{"stack_size", lua_wrap_errors<l_item_stack_size>},
{"defs_count", lua_wrap_errors<l_item_defs_count>},
{"index", lua::wrap<l_item_index>},
{"name", lua::wrap<l_item_name>},
{"stack_size", lua::wrap<l_item_stack_size>},
{"defs_count", lua::wrap<l_item_defs_count>},
{NULL, NULL}
};

View File

@ -1,36 +1,28 @@
#include "api_lua.hpp"
#include "lua_commons.hpp"
#include "LuaState.hpp"
#include "../../../coders/json.hpp"
#include "../../../data/dynamic.hpp"
namespace scripting {
extern lua::LuaState* state;
}
static int l_json_stringify(lua_State* L) {
auto value = scripting::state->tovalue(1);
static int l_json_stringify(lua::State* L) {
auto value = lua::tovalue(L, 1);
if (auto mapptr = std::get_if<dynamic::Map_sptr>(&value)) {
bool nice = lua_toboolean(L, 2);
bool nice = lua::toboolean(L, 2);
auto string = json::stringify(mapptr->get(), nice, " ");
lua_pushstring(L, string.c_str());
return 1;
return lua::pushstring(L, string);
} else {
throw std::runtime_error("table expected");
}
}
static int l_json_parse(lua_State* L) {
auto string = scripting::state->requireString(1);
static int l_json_parse(lua::State* L) {
auto string = lua::require_string(L, 1);
auto element = json::parse("<string>", string);
scripting::state->pushvalue(element);
return 1;
return lua::pushvalue(L, element);
}
const luaL_Reg jsonlib [] = {
{"tostring", lua_wrap_errors<l_json_stringify>},
{"parse", lua_wrap_errors<l_json_parse>},
{"tostring", lua::wrap<l_json_stringify>},
{"parse", lua::wrap<l_json_parse>},
{NULL, NULL}
};

View File

@ -1,7 +1,5 @@
#include "api_lua.hpp"
#include "lua_commons.hpp"
#include "../scripting.hpp"
#include "../../../engine.hpp"
#include "../../../assets/AssetsLoader.hpp"
#include "../../../files/engine_paths.hpp"
@ -14,76 +12,75 @@
#include <filesystem>
#include <algorithm>
static int l_pack_get_folder(lua_State* L) {
std::string packName = lua_tostring(L, 1);
using namespace scripting;
static int l_pack_get_folder(lua::State* L) {
std::string packName = lua::tostring(L, 1);
if (packName == "core") {
auto folder = scripting::engine->getPaths()->getResources().u8string()+"/";
lua_pushstring(L, folder.c_str());
return 1;
auto folder = engine->getPaths()->getResources().u8string()+"/";
return lua::pushstring(L, folder);
}
for (auto& pack : scripting::engine->getContentPacks()) {
for (auto& pack : engine->getContentPacks()) {
if (pack.id == packName) {
lua_pushstring(L, (pack.folder.u8string()+"/").c_str());
return 1;
return lua::pushstring(L, pack.folder.u8string()+"/");
}
}
lua_pushstring(L, "");
return 1;
return lua::pushstring(L, "");
}
/// @brief pack.get_installed() -> array<string>
static int l_pack_get_installed(lua_State* L) {
auto& packs = scripting::engine->getContentPacks();
lua_createtable(L, packs.size(), 0);
static int l_pack_get_installed(lua::State* L) {
auto& packs = engine->getContentPacks();
lua::createtable(L, packs.size(), 0);
for (size_t i = 0; i < packs.size(); i++) {
lua_pushstring(L, packs[i].id.c_str());
lua_rawseti(L, -2, i + 1);
lua::pushstring(L, packs[i].id);
lua::rawseti(L, i + 1);
}
return 1;
}
/// @brief pack.get_available() -> array<string>
static int l_pack_get_available(lua_State* L) {
static int l_pack_get_available(lua::State* L) {
fs::path worldFolder("");
if (scripting::level) {
worldFolder = scripting::level->getWorld()->wfile->getFolder();
if (level) {
worldFolder = level->getWorld()->wfile->getFolder();
}
auto manager = scripting::engine->createPacksManager(worldFolder);
auto manager = engine->createPacksManager(worldFolder);
manager.scan();
const auto& installed = scripting::engine->getContentPacks();
const auto& installed = engine->getContentPacks();
for (auto& pack : installed) {
manager.exclude(pack.id);
}
auto names = manager.getAllNames();
lua_createtable(L, names.size(), 0);
lua::createtable(L, names.size(), 0);
for (size_t i = 0; i < names.size(); i++) {
lua_pushstring(L, names[i].c_str());
lua_rawseti(L, -2, i + 1);
lua::pushstring(L, names[i]);
lua::rawseti(L, i + 1);
}
return 1;
}
static int l_pack_get_info(lua_State* L, const ContentPack& pack, const Content* content) {
lua_createtable(L, 0, 5);
static int l_pack_get_info(lua::State* L, const ContentPack& pack, const Content* content) {
lua::createtable(L, 0, 5);
lua_pushstring(L, pack.id.c_str());
lua_setfield(L, -2, "id");
lua::pushstring(L, pack.id);
lua::setfield(L, "id");
lua_pushstring(L, pack.title.c_str());
lua_setfield(L, -2, "title");
lua::pushstring(L, pack.title);
lua::setfield(L, "title");
lua_pushstring(L, pack.creator.c_str());
lua_setfield(L, -2, "creator");
lua::pushstring(L, pack.creator);
lua::setfield(L, "creator");
lua_pushstring(L, pack.description.c_str());
lua_setfield(L, -2, "description");
lua::pushstring(L, pack.description);
lua::setfield(L, "description");
lua_pushstring(L, pack.version.c_str());
lua_setfield(L, -2, "version");
lua::pushstring(L, pack.version);
lua::setfield(L, "version");
auto assets = scripting::engine->getAssets();
auto assets = engine->getAssets();
std::string icon = pack.id+".icon";
if (!AssetsLoader::loadExternalTexture(assets, icon, {
pack.folder/fs::path("icon.png")
@ -91,11 +88,11 @@ static int l_pack_get_info(lua_State* L, const ContentPack& pack, const Content*
icon = "gui/no_icon";
}
lua_pushstring(L, icon.c_str());
lua_setfield(L, -2, "icon");
lua::pushstring(L, icon);
lua::setfield(L, "icon");
if (!pack.dependencies.empty()) {
lua_createtable(L, pack.dependencies.size(), 0);
lua::createtable(L, pack.dependencies.size(), 0);
for (size_t i = 0; i < pack.dependencies.size(); i++) {
auto& dpack = pack.dependencies.at(i);
std::string prefix;
@ -105,16 +102,16 @@ static int l_pack_get_info(lua_State* L, const ContentPack& pack, const Content*
case DependencyLevel::weak: prefix = "~"; break;
default: throw std::runtime_error("");
}
lua_pushfstring(L, "%s%s", prefix.c_str(), dpack.id.c_str());
lua_rawseti(L, -2, i+1);
lua::pushfstring(L, "%s%s", prefix.c_str(), dpack.id.c_str());
lua::rawseti(L, i+1);
}
lua_setfield(L, -2, "dependencies");
lua::setfield(L, "dependencies");
}
auto runtime = content ? content->getPackRuntime(pack.id) : nullptr;
if (runtime) {
lua_pushboolean(L, runtime->getStats().hasSavingContent());
lua_setfield(L, -2, "has_indices");
lua::pushboolean(L, runtime->getStats().hasSavingContent());
lua::setfield(L, "has_indices");
}
return 1;
}
@ -126,21 +123,21 @@ static int l_pack_get_info(lua_State* L, const ContentPack& pack, const Content*
/// version: str,
/// [optional] has_indices: bool
/// } or nil
static int l_pack_get_info(lua_State* L) {
auto packid = lua_tostring(L, 1);
static int l_pack_get_info(lua::State* L) {
auto packid = lua::tostring(L, 1);
auto content = scripting::engine->getContent();
auto& packs = scripting::engine->getContentPacks();
auto content = engine->getContent();
auto& packs = engine->getContentPacks();
auto found = std::find_if(packs.begin(), packs.end(), [packid](const auto& pack) {
return pack.id == packid;
});
if (found == packs.end()) {
// TODO: optimize
fs::path worldFolder("");
if (scripting::level) {
worldFolder = scripting::level->getWorld()->wfile->getFolder();
if (level) {
worldFolder = level->getWorld()->wfile->getFolder();
}
auto manager = scripting::engine->createPacksManager(worldFolder);
auto manager = engine->createPacksManager(worldFolder);
manager.scan();
auto vec = manager.getAll({packid});
if (!vec.empty()) {
@ -152,21 +149,21 @@ static int l_pack_get_info(lua_State* L) {
return l_pack_get_info(L, pack, content);
}
static int l_pack_get_base_packs(lua_State* L) {
auto& packs = scripting::engine->getBasePacks();
lua_createtable(L, packs.size(), 0);
static int l_pack_get_base_packs(lua::State* L) {
auto& packs = engine->getBasePacks();
lua::createtable(L, packs.size(), 0);
for (size_t i = 0; i < packs.size(); i++) {
lua_pushstring(L, packs[i].c_str());
lua_rawseti(L, -2, i + 1);
lua::pushstring(L, packs[i]);
lua::rawseti(L, i + 1);
}
return 1;
}
const luaL_Reg packlib [] = {
{"get_folder", lua_wrap_errors<l_pack_get_folder>},
{"get_installed", lua_wrap_errors<l_pack_get_installed>},
{"get_available", lua_wrap_errors<l_pack_get_available>},
{"get_info", lua_wrap_errors<l_pack_get_info>},
{"get_base_packs", lua_wrap_errors<l_pack_get_base_packs>},
{"get_folder", lua::wrap<l_pack_get_folder>},
{"get_installed", lua::wrap<l_pack_get_installed>},
{"get_available", lua::wrap<l_pack_get_available>},
{"get_info", lua::wrap<l_pack_get_info>},
{"get_base_packs", lua::wrap<l_pack_get_base_packs>},
{NULL, NULL}
};

View File

@ -1,6 +1,5 @@
#include "lua_commons.hpp"
#include "api_lua.hpp"
#include "../scripting.hpp"
#include "../../../world/Level.hpp"
#include "../../../objects/Player.hpp"
#include "../../../physics/Hitbox.hpp"
@ -9,82 +8,69 @@
#include <glm/glm.hpp>
inline std::shared_ptr<Player> get_player(lua_State* L, int idx) {
return scripting::level->getObject<Player>(lua_tointeger(L, idx));
using namespace scripting;
inline std::shared_ptr<Player> get_player(lua::State* L, int idx) {
return level->getObject<Player>(lua::tointeger(L, idx));
}
static int l_player_get_pos(lua_State* L) {
static int l_player_get_pos(lua::State* L) {
if (auto player = get_player(L, 1)) {
return lua::pushvec3(L, player->hitbox->position);
}
return 0;
}
static int l_player_set_pos(lua::State* L) {
auto player = get_player(L, 1);
if (!player) {
return 0;
}
glm::vec3 pos = player->hitbox->position;
lua_pushnumber(L, pos.x);
lua_pushnumber(L, pos.y);
lua_pushnumber(L, pos.z);
return 3;
}
static int l_player_set_pos(lua_State* L) {
auto player = get_player(L, 1);
if (!player) {
return 0;
}
auto x = lua_tonumber(L, 2);
auto y = lua_tonumber(L, 3);
auto z = lua_tonumber(L, 4);
auto x = lua::tonumber(L, 2);
auto y = lua::tonumber(L, 3);
auto z = lua::tonumber(L, 4);
player->hitbox->position = glm::vec3(x, y, z);
return 0;
}
static int l_player_get_vel(lua_State* L) {
auto player = get_player(L, 1);
if (!player) {
return 0;
static int l_player_get_vel(lua::State* L) {
if (auto player = get_player(L, 1)) {
return lua::pushvec3(L, player->hitbox->velocity);
}
glm::vec3 vel = player->hitbox->velocity;
lua_pushnumber(L, vel.x);
lua_pushnumber(L, vel.y);
lua_pushnumber(L, vel.z);
return 3;
return 0;
}
static int l_player_set_vel(lua_State* L) {
static int l_player_set_vel(lua::State* L) {
auto player = get_player(L, 1);
if (!player) {
return 0;
}
auto x = lua_tonumber(L, 2);
auto y = lua_tonumber(L, 3);
auto z = lua_tonumber(L, 4);
auto x = lua::tonumber(L, 2);
auto y = lua::tonumber(L, 3);
auto z = lua::tonumber(L, 4);
player->hitbox->velocity = glm::vec3(x, y, z);
return 0;
}
static int l_player_get_rot(lua_State* L) {
auto player = get_player(L, 1);
if (!player) {
return 0;
static int l_player_get_rot(lua::State* L) {
if (auto player = get_player(L, 1)) {
return lua::pushvec3(L, player->cam);
}
const glm::vec3& rot = player->cam;
lua_pushnumber(L, rot.x);
lua_pushnumber(L, rot.y);
lua_pushnumber(L, rot.z);
return 3;
return 0;
}
static int l_player_set_rot(lua_State* L) {
static int l_player_set_rot(lua::State* L) {
auto player = get_player(L, 1);
if (!player) {
return 0;
}
glm::vec3& cam = player->cam;
lua_Number x = lua_tonumber(L, 2);
lua_Number y = lua_tonumber(L, 3);
lua_Number z = cam.z;
if (lua_isnumber(L, 4)) {
z = lua_tonumber(L, 4);
auto x = lua::tonumber(L, 2);
auto y = lua::tonumber(L, 3);
auto z = cam.z;
if (lua::isnumber(L, 4)) {
z = lua::tonumber(L, 4);
}
cam.x = x;
cam.y = y;
@ -92,72 +78,66 @@ static int l_player_set_rot(lua_State* L) {
return 0;
}
static int l_player_get_inv(lua_State* L) {
static int l_player_get_inv(lua::State* L) {
auto player = get_player(L, 1);
if (!player) {
return 0;
}
lua_pushinteger(L, player->getInventory()->getId());
lua_pushinteger(L, player->getChosenSlot());
lua::pushinteger(L, player->getInventory()->getId());
lua::pushinteger(L, player->getChosenSlot());
return 2;
}
static int l_player_is_flight(lua_State* L) {
static int l_player_is_flight(lua::State* L) {
if (auto player = get_player(L, 1)) {
lua_pushboolean(L, player->isFlight());
return 1;
return lua::pushboolean(L, player->isFlight());
}
return 0;
}
static int l_player_set_flight(lua_State* L) {
static int l_player_set_flight(lua::State* L) {
if (auto player = get_player(L, 1)) {
player->setFlight(lua_toboolean(L, 2));
player->setFlight(lua::toboolean(L, 2));
}
return 0;
}
static int l_player_is_noclip(lua_State* L) {
static int l_player_is_noclip(lua::State* L) {
if (auto player = get_player(L, 1)) {
lua_pushboolean(L, player->isNoclip());
return 1;
return lua::pushboolean(L, player->isNoclip());
}
return 0;
}
static int l_player_set_noclip(lua_State* L) {
static int l_player_set_noclip(lua::State* L) {
if (auto player = get_player(L, 1)) {
player->setNoclip(lua_toboolean(L, 2));
player->setNoclip(lua::toboolean(L, 2));
}
return 0;
}
static int l_player_get_selected_block(lua_State* L) {
static int l_player_get_selected_block(lua::State* L) {
if (auto player = get_player(L, 1)) {
if (player->selection.vox.id == BLOCK_VOID) {
return 0;
}
const glm::ivec3 pos = player->selection.position;
lua_pushinteger(L, pos.x);
lua_pushinteger(L, pos.y);
lua_pushinteger(L, pos.z);
return 3;
return lua::pushivec3(L, player->selection.position);
}
return 0;
}
const luaL_Reg playerlib [] = {
{"get_pos", lua_wrap_errors<l_player_get_pos>},
{"set_pos", lua_wrap_errors<l_player_set_pos>},
{"get_vel", lua_wrap_errors<l_player_get_vel>},
{"set_vel", lua_wrap_errors<l_player_set_vel>},
{"get_rot", lua_wrap_errors<l_player_get_rot>},
{"set_rot", lua_wrap_errors<l_player_set_rot>},
{"get_inventory", lua_wrap_errors<l_player_get_inv>},
{"is_flight", lua_wrap_errors<l_player_is_flight>},
{"set_flight", lua_wrap_errors<l_player_set_flight>},
{"is_noclip", lua_wrap_errors<l_player_is_noclip>},
{"set_noclip", lua_wrap_errors<l_player_set_noclip>},
{"get_selected_block", lua_wrap_errors<l_player_get_selected_block>},
{"get_pos", lua::wrap<l_player_get_pos>},
{"set_pos", lua::wrap<l_player_set_pos>},
{"get_vel", lua::wrap<l_player_get_vel>},
{"set_vel", lua::wrap<l_player_set_vel>},
{"get_rot", lua::wrap<l_player_get_rot>},
{"set_rot", lua::wrap<l_player_set_rot>},
{"get_inventory", lua::wrap<l_player_get_inv>},
{"is_flight", lua::wrap<l_player_is_flight>},
{"set_flight", lua::wrap<l_player_set_flight>},
{"is_noclip", lua::wrap<l_player_is_noclip>},
{"set_noclip", lua::wrap<l_player_set_noclip>},
{"get_selected_block", lua::wrap<l_player_get_selected_block>},
{NULL, NULL}
};

View File

@ -1,21 +1,18 @@
#include "api_lua.hpp"
#include "lua_commons.hpp"
#include "../scripting.hpp"
#include "../../../engine.hpp"
#include "../../../window/Window.hpp"
static int l_time_uptime(lua_State* L) {
lua_pushnumber(L, Window::time());
return 1;
static int l_time_uptime(lua::State* L) {
return lua::pushnumber(L, Window::time());
}
static int l_time_delta(lua_State* L) {
lua_pushnumber(L, scripting::engine->getDelta());
return 1;
static int l_time_delta(lua::State* L) {
return lua::pushnumber(L, scripting::engine->getDelta());
}
const luaL_Reg timelib [] = {
{"uptime", lua_wrap_errors<l_time_uptime>},
{"delta", lua_wrap_errors<l_time_delta>},
{"uptime", lua::wrap<l_time_uptime>},
{"delta", lua::wrap<l_time_delta>},
{NULL, NULL}
};

View File

@ -1,37 +1,30 @@
#include "api_lua.hpp"
#include "lua_commons.hpp"
#include "LuaState.hpp"
#include "../../../coders/toml.hpp"
#include "../../../data/dynamic.hpp"
namespace scripting {
extern lua::LuaState* state;
}
using namespace scripting;
static int l_toml_stringify(lua_State* L) {
auto value = state->tovalue(1);
static int l_toml_stringify(lua::State* L) {
auto value = lua::tovalue(L, 1);
if (auto mapptr = std::get_if<dynamic::Map_sptr>(&value)) {
auto string = toml::stringify(**mapptr);
lua_pushstring(L, string.c_str());
return 1;
return lua::pushstring(L, string);
} else {
throw std::runtime_error("table expected");
}
}
static int l_toml_parse(lua_State*) {
auto string = state->requireString(1);
static int l_toml_parse(lua::State* L) {
auto string = lua::require_string(L, 1);
auto element = toml::parse("<string>", string);
auto value = std::make_unique<dynamic::Value>(element);
state->pushvalue(*value);
return 1;
return lua::pushvalue(L, *value);
}
const luaL_Reg tomllib [] = {
{"tostring", lua_wrap_errors<l_toml_stringify>},
{"parse", lua_wrap_errors<l_toml_parse>},
{"tostring", lua::wrap<l_toml_stringify>},
{"parse", lua::wrap<l_toml_parse>},
{NULL, NULL}
};

View File

@ -1,7 +1,5 @@
#include "lua_commons.hpp"
#include "api_lua.hpp"
#include "../scripting.hpp"
#include "../../../assets/Assets.hpp"
#include "../../../assets/AssetsLoader.hpp"
#include "../../../files/engine_paths.hpp"
@ -12,21 +10,22 @@
#include <cmath>
#include <filesystem>
using namespace scripting;
namespace fs = std::filesystem;
static int l_world_get_list(lua_State* L) {
auto paths = scripting::engine->getPaths();
static int l_world_get_list(lua::State* L) {
auto paths = engine->getPaths();
auto worlds = paths->scanForWorlds();
lua_createtable(L, worlds.size(), 0);
lua::createtable(L, worlds.size(), 0);
for (size_t i = 0; i < worlds.size(); i++) {
lua_createtable(L, 0, 1);
lua::createtable(L, 0, 1);
auto name = worlds[i].filename().u8string();
lua_pushstring(L, name.c_str());
lua_setfield(L, -2, "name");
lua::pushstring(L, name);
lua::setfield(L, "name");
auto assets = scripting::engine->getAssets();
auto assets = engine->getAssets();
std::string icon = "world:"+name+".icon";
if (!AssetsLoader::loadExternalTexture(assets, icon, {
worlds[i]/fs::path("icon.png"),
@ -34,48 +33,43 @@ static int l_world_get_list(lua_State* L) {
})) {
icon = "gui/no_world_icon";
}
lua_pushstring(L, icon.c_str());
lua_setfield(L, -2, "icon");
lua_rawseti(L, -2, i + 1);
lua::pushstring(L, icon);
lua::setfield(L, "icon");
lua::rawseti(L, i + 1);
}
return 1;
}
static int l_world_get_total_time(lua_State* L) {
lua_pushnumber(L, scripting::level->getWorld()->totalTime);
return 1;
static int l_world_get_total_time(lua::State* L) {
return lua::pushnumber(L, level->getWorld()->totalTime);
}
static int l_world_get_day_time(lua_State* L) {
lua_pushnumber(L, scripting::level->getWorld()->daytime);
return 1;
static int l_world_get_day_time(lua::State* L) {
return lua::pushnumber(L, level->getWorld()->daytime);
}
static int l_world_set_day_time(lua_State* L) {
double value = lua_tonumber(L, 1);
scripting::level->getWorld()->daytime = fmod(value, 1.0);
static int l_world_set_day_time(lua::State* L) {
auto value = lua::tonumber(L, 1);
level->getWorld()->daytime = fmod(value, 1.0);
return 0;
}
static int l_world_get_seed(lua_State* L) {
lua_pushinteger(L, scripting::level->getWorld()->getSeed());
return 1;
static int l_world_get_seed(lua::State* L) {
return lua::pushinteger(L, level->getWorld()->getSeed());
}
static int l_world_exists(lua_State* L) {
auto name = lua_tostring(L, 1);
auto worldsDir = scripting::engine->getPaths()->getWorldFolder(name);
lua_pushboolean(L, fs::is_directory(worldsDir));
return 1;
static int l_world_exists(lua::State* L) {
auto name = lua::require_string(L, 1);
auto worldsDir = engine->getPaths()->getWorldFolder(name);
return lua::pushboolean(L, fs::is_directory(worldsDir));
}
const luaL_Reg worldlib [] = {
{"get_list", lua_wrap_errors<l_world_get_list>},
{"get_total_time", lua_wrap_errors<l_world_get_total_time>},
{"get_day_time", lua_wrap_errors<l_world_get_day_time>},
{"set_day_time", lua_wrap_errors<l_world_set_day_time>},
{"get_seed", lua_wrap_errors<l_world_get_seed>},
{"exists", lua_wrap_errors<l_world_exists>},
{"get_list", lua::wrap<l_world_get_list>},
{"get_total_time", lua::wrap<l_world_get_total_time>},
{"get_day_time", lua::wrap<l_world_get_day_time>},
{"set_day_time", lua::wrap<l_world_set_day_time>},
{"get_seed", lua::wrap<l_world_get_seed>},
{"exists", lua::wrap<l_world_exists>},
{NULL, NULL}
};

View File

@ -0,0 +1,9 @@
#include "lua_commons.hpp"
#include "../../../debug/Logger.hpp"
static debug::Logger logger("lua");
void lua::log_error(const std::string& text) {
logger.error() << text;
}

View File

@ -1,34 +1,35 @@
#ifndef LOGIC_SCRIPTING_LUA_HPP_
#define LOGIC_SCRIPTING_LUA_HPP_
#include "../../../delegates.hpp"
#include "../scripting.hpp"
#ifdef __linux__
#include <luajit-2.1/luaconf.h>
#include <luajit-2.1/lua.hpp>
#else
#include <lua.hpp>
#endif
#include <glm/glm.hpp>
#include <string>
#include <stdexcept>
#ifndef LUAJIT_VERSION
#error LuaJIT required
#endif
#include <string>
#include <exception>
namespace lua {
class luaerror : public std::runtime_error {
public:
luaerror(const std::string& message);
};
template <lua_CFunction func> int lua_wrap_errors(lua_State *L) {
int result = 0;
try {
result = func(L);
}
// transform exception with description into lua_error
catch (std::exception &e) {
luaL_error(L, e.what());
}
// Rethrow any other exception (lua error for example)
catch (...) {
throw;
}
return result;
void log_error(const std::string& text);
using State = lua_State;
using Number = lua_Number;
using Integer = lua_Integer;
}
#endif // LOGIC_SCRIPTING_LUA_HPP_

View File

@ -0,0 +1,101 @@
#include "lua_engine.hpp"
#include "api_lua.hpp"
#include "../../../debug/Logger.hpp"
#include "../../../util/stringutil.hpp"
#include <iomanip>
#include <iostream>
static debug::Logger logger("lua-state");
static lua::State* main_thread = nullptr;
using namespace lua;
luaerror::luaerror(const std::string& message) : std::runtime_error(message) {
}
static void remove_lib_funcs(lua::State* L, const char* libname, const char* funcs[]) {
if (getglobal(L, libname)) {
for (uint i = 0; funcs[i]; i++) {
pushnil(L);
setfield(L, funcs[i], -2);
}
}
}
static void create_libs(lua::State* L) {
openlib(L, "audio", audiolib);
openlib(L, "block", blocklib);
openlib(L, "console", consolelib);
openlib(L, "core", corelib);
openlib(L, "file", filelib);
openlib(L, "gui", guilib);
openlib(L, "input", inputlib);
openlib(L, "inventory", inventorylib);
openlib(L, "item", itemlib);
openlib(L, "json", jsonlib);
openlib(L, "pack", packlib);
openlib(L, "player", playerlib);
openlib(L, "time", timelib);
openlib(L, "toml", tomllib);
openlib(L, "world", worldlib);
addfunc(L, "print", lua::wrap<l_print>);
}
void lua::initialize() {
logger.info() << LUA_VERSION;
logger.info() << LUAJIT_VERSION;
auto L = luaL_newstate();
if (L == nullptr) {
throw luaerror("could not to initialize Lua");
}
main_thread = L;
// Allowed standard libraries
luaopen_base(L);
luaopen_math(L);
luaopen_string(L);
luaopen_table(L);
luaopen_debug(L);
luaopen_jit(L);
luaopen_bit(L);
luaopen_os(L);
const char* removed_os[] {
"execute",
"exit",
"remove",
"rename",
"setlocale",
"tmpname",
nullptr
};
remove_lib_funcs(L, "os", removed_os);
create_libs(L);
pushglobals(L);
setglobal(L, env_name(0));
createtable(L, 0, 0);
setglobal(L, LAMBDAS_TABLE);
}
void lua::finalize() {
lua_close(main_thread);
}
bool lua::emit_event(lua::State* L, const std::string &name, std::function<int(lua::State*)> args) {
getglobal(L, "events");
getfield(L, "emit");
pushstring(L, name);
call_nothrow(L, args(L) + 1);
bool result = toboolean(L, -1);
pop(L, 2);
return result;
}
lua::State* lua::get_main_thread() {
return main_thread;
}

View File

@ -0,0 +1,21 @@
#ifndef LOGIC_SCRIPTING_LUA_STATE_HPP_
#define LOGIC_SCRIPTING_LUA_STATE_HPP_
#include "lua_util.hpp"
#include "../scripting_functional.hpp"
#include "../../../data/dynamic.hpp"
#include "../../../delegates.hpp"
#include <string>
#include <stdexcept>
namespace lua {
void initialize();
void finalize();
bool emit_event(lua::State*, const std::string& name, std::function<int(lua::State*)> args=[](auto*){return 0;});
lua::State* get_main_thread();
}
#endif // LOGIC_SCRIPTING_LUA_STATE_HPP_

View File

@ -1,24 +1,23 @@
#include "api_lua.hpp"
#include "lua_commons.hpp"
#include <iostream>
/// @brief Modified version of luaB_print from lbaselib.c
int l_print(lua_State* L) {
int n = lua_gettop(L); /* number of arguments */
lua_getglobal(L, "tostring");
int l_print(lua::State* L) {
int n = lua::gettop(L); /* number of arguments */
lua::getglobal(L, "tostring");
for (int i=1; i<=n; i++) {
lua_pushvalue(L, -1); /* function to be called */
lua_pushvalue(L, i); /* value to print */
lua_call(L, 1, 1);
const char* s = lua_tostring(L, -1); /* get result */
lua::pushvalue(L, -1); /* function to be called */
lua::pushvalue(L, i); /* value to print */
lua::call(L, 1, 1);
const char* s = lua::tostring(L, -1); /* get result */
if (s == NULL)
return luaL_error(L, LUA_QL("tostring") " must return a string to "
LUA_QL("print"));
if (i > 1)
std::cout << "\t";
std::cout << s;
lua_pop(L, 1); /* pop result */
lua::pop(L); /* pop result */
}
std::cout << std::endl;
return 0;

View File

@ -0,0 +1,221 @@
#include "lua_util.hpp"
#include "../../../util/stringutil.hpp"
#include <iostream>
#include <iomanip>
using namespace lua;
static int nextEnvironment = 1;
std::string lua::env_name(int env) {
return "_ENV"+util::mangleid(env);
}
int lua::pushvalue(State* L, const dynamic::Value& value) {
using namespace dynamic;
if (auto* flag = std::get_if<bool>(&value)) {
pushboolean(L, *flag);
} else if (auto* num = std::get_if<integer_t>(&value)) {
pushinteger(L, *num);
} else if (auto* num = std::get_if<number_t>(&value)) {
pushnumber(L, *num);
} else if (auto* str = std::get_if<std::string>(&value)) {
pushstring(L, *str);
} else if (auto listptr = std::get_if<List_sptr>(&value)) {
auto list = *listptr;
createtable(L, list->size(), 0);
for (size_t i = 0; i < list->size(); i++) {
pushvalue(L, list->get(i));
rawseti(L, i+1);
}
} else if (auto mapptr = std::get_if<Map_sptr>(&value)) {
auto map = *mapptr;
createtable(L, 0, map->size());
for (auto& entry : map->values) {
pushvalue(L, entry.second);
setfield(L, entry.first);
}
} else {
pushnil(L);
}
return 1;
}
std::wstring lua::require_wstring(State* L, int idx) {
return util::str2wstr_utf8(require_string(L, idx));
}
int lua::pushwstring(State* L, const std::wstring& str) {
return pushstring(L, util::wstr2str_utf8(str));
}
dynamic::Value lua::tovalue(State* L, int idx) {
using namespace dynamic;
auto type = lua::type(L, idx);
switch (type) {
case LUA_TNIL:
case LUA_TNONE:
return dynamic::NONE;
case LUA_TBOOLEAN:
return toboolean(L, idx) == 1;
case LUA_TNUMBER: {
auto number = tonumber(L, idx);
auto integer = tointeger(L, idx);
if (number == static_cast<Number>(integer)) {
return integer;
} else {
return number;
}
}
case LUA_TSTRING:
return std::string(tostring(L, idx));
case LUA_TTABLE: {
int len = objlen(L, idx);
if (len) {
// array
auto list = create_list();
for (int i = 1; i <= len; i++) {
rawgeti(L, i, idx);
list->put(tovalue(L, -1));
pop(L);
}
return list;
} else {
// table
auto map = create_map();
pushvalue(L, idx);
pushnil(L);
while (next(L, -2)) {
pushvalue(L, -2);
auto key = tostring(L, -1);
map->put(key, tovalue(L, -2));
pop(L, 2);
}
pop(L);
return map;
}
}
default:
throw std::runtime_error(
"lua type "+std::string(luaL_typename(L, type))+" is not supported"
);
}
}
int lua::call(State* L, int argc, int nresults) {
if (lua_pcall(L, argc, nresults, 0)) {
throw luaerror(tostring(L, -1));
}
return 1;
}
int lua::call_nothrow(State* L, int argc) {
if (lua_pcall(L, argc, LUA_MULTRET, 0)) {
log_error(tostring(L, -1));
return 0;
}
return 1;
}
void lua::dump_stack(State* L) {
int top = gettop(L);
for (int i = 1; i <= top; i++) {
std::cout << std::setw(3) << i << std::setw(20) << luaL_typename(L, i) << std::setw(30);
switch (lua::type(L, i)) {
case LUA_TNUMBER:
std::cout << tonumber(L, i);
break;
case LUA_TSTRING:
std::cout << tostring(L, i);
break;
case LUA_TBOOLEAN:
std::cout << (toboolean(L, i) ? "true" : "false");
break;
case LUA_TNIL:
std::cout << "nil";
break;
default:
std::cout << topointer(L, i);
break;
}
std::cout << std::endl;
}
}
static std::shared_ptr<std::string> createLambdaHandler(State* L) {
auto ptr = reinterpret_cast<ptrdiff_t>(topointer(L, -1));
auto name = util::mangleid(ptr);
getglobal(L, LAMBDAS_TABLE);
pushvalue(L, -2);
setfield(L, name);
pop(L, 2);
return std::shared_ptr<std::string>(new std::string(name), [=](std::string* name) {
getglobal(L, LAMBDAS_TABLE);
pushnil(L);
setfield(L, *name);
pop(L);
delete name;
});
}
runnable lua::create_runnable(State* L) {
auto funcptr = createLambdaHandler(L);
return [=]() {
getglobal(L, LAMBDAS_TABLE);
getfield(L, *funcptr);
call_nothrow(L, 0);
};
}
scripting::common_func lua::create_lambda(State* L) {
auto funcptr = createLambdaHandler(L);
return [=](const std::vector<dynamic::Value>& args) {
getglobal(L, LAMBDAS_TABLE);
getfield(L, *funcptr);
for (const auto& arg : args) {
pushvalue(L, arg);
}
if (call(L, args.size(), 1)) {
auto result = tovalue(L, -1);
pop(L);
return result;
}
return dynamic::Value(dynamic::NONE);
};
}
int lua::createEnvironment(State* L, int parent) {
int id = nextEnvironment++;
// local env = {}
createtable(L, 0, 1);
// setmetatable(env, {__index=_G})
createtable(L, 0, 1);
if (parent == 0) {
pushglobals(L);
} else {
if (pushenv(L, parent) == 0) {
pushglobals(L);
}
}
setfield(L, "__index");
setmetatable(L);
// envname = env
setglobal(L, env_name(id));
return id;
}
void lua::removeEnvironment(State* L, int id) {
if (id == 0) {
return;
}
pushnil(L);
setglobal(L, env_name(id));
}

View File

@ -1,135 +1,374 @@
#ifndef LOGIC_SCRIPTING_LUA_UTIL_HPP_
#define LOGIC_SCRIPTING_LUA_UTIL_HPP_
#include "LuaState.hpp"
#ifdef __linux__
#include <luajit-2.1/luaconf.h>
#include <luajit-2.1/lua.hpp>
#else
#include <lua.hpp>
#endif
#include <glm/glm.hpp>
#include <stdexcept>
#include "lua_commons.hpp"
namespace lua {
inline int pushivec3(lua_State* L, lua_Integer x, lua_Integer y, lua_Integer z) {
inline std::string LAMBDAS_TABLE = "$L";
std::string env_name(int env);
template <lua_CFunction func> int wrap(lua_State *L) {
int result = 0;
try {
result = func(L);
}
// transform exception with description into lua_error
catch (std::exception &e) {
luaL_error(L, e.what());
}
// Rethrow any other exception (lua error for example)
catch (...) {
throw;
}
return result;
}
inline void pop(lua::State* L, int n=1) {
lua_pop(L, n);
}
inline int gettop(lua::State* L) {
return lua_gettop(L);
}
inline size_t objlen(lua::State* L, int idx) {
return lua_objlen(L, idx);
}
inline int next(lua::State* L, int idx) {
return lua_next(L, idx);
}
inline int type(lua::State* L, int idx) {
return lua_type(L, idx);
}
inline const char* type_name(lua::State* L, int idx) {
return lua_typename(L, idx);
}
inline int rawgeti(lua::State* L, int n, int idx=-1) {
lua_rawgeti(L, idx, n);
return 1;
}
inline void rawseti(lua::State* L, int n, int idx=-2) {
lua_rawseti(L, idx, n);
}
inline int createtable(lua::State* L, int narr, int nrec) {
lua_createtable(L, narr, nrec);
return 1;
}
inline bool isnil(lua::State* L, int idx) {
return lua_isnil(L, idx);
}
inline bool getglobal(lua::State* L, const std::string& name) {
lua_getglobal(L, name.c_str());
if (isnil(L, -1)) {
pop(L);
return false;
}
return true;
}
inline bool hasglobal(lua::State* L, const std::string& name) {
lua_getglobal(L, name.c_str());
if (isnil(L, -1)) {
pop(L);
return false;
}
pop(L);
return true;
}
// function wrappers with number of pushed values as return value
inline int pushnil(lua::State* L) {
lua_pushnil(L);
return 1;
}
inline int pushinteger(lua::State* L, lua::Integer x) {
lua_pushinteger(L, x);
lua_pushinteger(L, y);
lua_pushinteger(L, z);
return 1;
}
inline int pushnumber(lua::State* L, lua::Number x) {
lua_pushnumber(L, x);
return 1;
}
inline int pushivec3(lua::State* L, lua::Integer x, lua::Integer y, lua::Integer z) {
pushinteger(L, x);
pushinteger(L, y);
pushinteger(L, z);
return 3;
}
inline int pushivec3(lua_State* L, glm::ivec3 vec) {
lua_pushinteger(L, vec.x);
lua_pushinteger(L, vec.y);
lua_pushinteger(L, vec.z);
inline int pushivec3(lua::State* L, glm::ivec3 vec) {
pushinteger(L, vec.x);
pushinteger(L, vec.y);
pushinteger(L, vec.z);
return 3;
}
inline int pushvec3(lua_State* L, glm::vec3 vec) {
lua_pushnumber(L, vec.x);
lua_pushnumber(L, vec.y);
lua_pushnumber(L, vec.z);
inline int pushvec3(lua::State* L, glm::vec3 vec) {
pushnumber(L, vec.x);
pushnumber(L, vec.y);
pushnumber(L, vec.z);
return 3;
}
inline int pushvec4(lua_State* L, glm::vec4 vec) {
lua_pushnumber(L, vec.x);
lua_pushnumber(L, vec.y);
lua_pushnumber(L, vec.z);
lua_pushnumber(L, vec.w);
inline int pushvec4(lua::State* L, glm::vec4 vec) {
pushnumber(L, vec.x);
pushnumber(L, vec.y);
pushnumber(L, vec.z);
pushnumber(L, vec.w);
return 4;
}
inline int pushvec2_arr(lua_State* L, glm::vec2 vec) {
lua_createtable(L, 2, 0);
lua_getglobal(L, "vec2_mt");
lua_setmetatable(L, -2);
inline void setmetatable(lua::State* L, int idx=-2) {
lua_setmetatable(L, idx);
}
lua_pushnumber(L, vec.x);
lua_rawseti(L, -2, 1);
lua_pushnumber(L, vec.y);
lua_rawseti(L, -2, 2);
inline int pushvec2_arr(lua::State* L, glm::vec2 vec) {
createtable(L, 2, 0);
getglobal(L, "vec2_mt");
setmetatable(L);
pushnumber(L, vec.x);
rawseti(L, 1);
pushnumber(L, vec.y);
rawseti(L, 2);
return 1;
}
inline int pushvec3_arr(lua_State* L, glm::vec3 vec) {
lua_createtable(L, 3, 0);
lua_getglobal(L, "vec3_mt");
lua_setmetatable(L, -2);
inline int pushvec3_arr(lua::State* L, glm::vec3 vec) {
createtable(L, 3, 0);
getglobal(L, "vec3_mt");
setmetatable(L);
lua_pushnumber(L, vec.x);
lua_rawseti(L, -2, 1);
lua_pushnumber(L, vec.y);
lua_rawseti(L, -2, 2);
lua_pushnumber(L, vec.z);
lua_rawseti(L, -2, 3);
pushnumber(L, vec.x);
rawseti(L, 1);
pushnumber(L, vec.y);
rawseti(L, 2);
pushnumber(L, vec.z);
rawseti(L, 3);
return 1;
}
inline int pushvec4_arr(lua_State* L, glm::vec4 vec) {
lua_createtable(L, 4, 0);
lua_getglobal(L, "vec4_mt");
lua_setmetatable(L, -2);
inline int pushvec4_arr(lua::State* L, glm::vec4 vec) {
createtable(L, 4, 0);
getglobal(L, "vec4_mt");
setmetatable(L);
lua_pushnumber(L, vec.x);
lua_rawseti(L, -2, 1);
lua_pushnumber(L, vec.y);
lua_rawseti(L, -2, 2);
lua_pushnumber(L, vec.z);
lua_rawseti(L, -2, 3);
lua_pushnumber(L, vec.w);
lua_rawseti(L, -2, 4);
pushnumber(L, vec.x);
rawseti(L, 1);
pushnumber(L, vec.y);
rawseti(L, 2);
pushnumber(L, vec.z);
rawseti(L, 3);
pushnumber(L, vec.w);
rawseti(L, 4);
return 1;
}
inline int pushcolor_arr(lua::State* L, glm::vec4 vec) {
createtable(L, 4, 0);
getglobal(L, "color_mt");
setmetatable(L);
pushinteger(L, vec.x*255);
rawseti(L, 1);
pushinteger(L, vec.y*255);
rawseti(L, 2);
pushinteger(L, vec.z*255);
rawseti(L, 3);
pushinteger(L, vec.w*255);
rawseti(L, 4);
return 1;
}
inline int pushcfunction(lua::State* L, lua_CFunction func) {
lua_pushcfunction(L, func);
return 1;
}
inline int pushstring(lua::State* L, const std::string& str) {
lua_pushstring(L, str.c_str());
return 1;
}
inline int pushcolor_arr(lua_State* L, glm::vec4 vec) {
lua_createtable(L, 4, 0);
lua_getglobal(L, "color_mt");
lua_setmetatable(L, -2);
lua_pushinteger(L, vec.x*255);
lua_rawseti(L, -2, 1);
lua_pushinteger(L, vec.y*255);
lua_rawseti(L, -2, 2);
lua_pushinteger(L, vec.z*255);
lua_rawseti(L, -2, 3);
lua_pushinteger(L, vec.w*255);
lua_rawseti(L, -2, 4);
template<typename... Args>
inline int pushfstring(lua_State *L, const char * fmt, Args... args) {
lua_pushfstring(L, fmt, args...);
return 1;
}
inline glm::vec2 tovec2(lua_State* L, int idx) {
int pushwstring(lua::State* L, const std::wstring& str);
inline int pushboolean(lua::State* L, bool value) {
lua_pushboolean(L, value);
return 1;
}
inline int pushvalue(lua::State* L, int idx) {
lua_pushvalue(L, idx);
if (!lua_istable(L, idx) || lua_objlen(L, idx) < 2) {
return 1;
}
inline int pushglobals(lua::State* L) {
return pushvalue(L, LUA_GLOBALSINDEX);
}
inline bool isnoneornil(lua::State* L, int idx) {
return lua_isnoneornil(L, idx);
}
inline bool isboolean(lua::State* L, int idx) {
return lua_isboolean(L, idx);
}
inline bool isnumber(lua::State* L, int idx) {
return lua_isnumber(L, idx);
}
inline bool isstring(lua::State* L, int idx) {
return lua_isstring(L, idx);
}
inline bool istable(lua::State* L, int idx) {
return lua_istable(L, idx);
}
inline bool isfunction(lua::State* L, int idx) {
return lua_isfunction(L, idx);
}
inline bool toboolean(lua::State* L, int idx) {
return lua_toboolean(L, idx);
}
inline lua::Integer tointeger(lua::State* L, int idx) {
return lua_tointeger(L, idx);
}
inline lua::Number tonumber(lua::State* L, int idx) {
return lua_tonumber(L, idx);
}
inline const char* tostring(lua::State* L, int idx) {
return lua_tostring(L, idx);
}
inline const void* topointer(lua::State* L, int idx) {
return lua_topointer(L, idx);
}
inline glm::vec2 tovec2(lua::State* L, int idx) {
pushvalue(L, idx);
if (!istable(L, idx) || objlen(L, idx) < 2) {
throw std::runtime_error("value must be an array of two numbers");
}
lua_rawgeti(L, -1, 1);
lua_Number x = lua_tonumber(L, -1); lua_pop(L, 1);
lua_rawgeti(L, -1, 2);
lua_Number y = lua_tonumber(L, -1); lua_pop(L, 1);
lua_pop(L, 1);
rawgeti(L, 1);
auto x = tonumber(L, -1); pop(L);
rawgeti(L, 2);
auto y = tonumber(L, -1); pop(L);
pop(L);
return glm::vec2(x, y);
}
inline glm::vec4 tocolor(lua_State* L, int idx) {
lua_pushvalue(L, idx);
if (!lua_istable(L, -1) || lua_objlen(L, idx) < 4) {
inline glm::vec4 tocolor(lua::State* L, int idx) {
pushvalue(L, idx);
if (!istable(L, -1) || objlen(L, idx) < 4) {
throw std::runtime_error("RGBA array required");
}
lua_rawgeti(L, -1, 1);
lua_Number r = lua_tonumber(L, -1); lua_pop(L, 1);
lua_rawgeti(L, -1, 2);
lua_Number g = lua_tonumber(L, -1); lua_pop(L, 1);
lua_rawgeti(L, -1, 3);
lua_Number b = lua_tonumber(L, -1); lua_pop(L, 1);
lua_rawgeti(L, -1, 4);
lua_Number a = lua_tonumber(L, -1); lua_pop(L, 1);
lua_pop(L, 1);
rawgeti(L, 1);
auto r = tonumber(L, -1); pop(L);
rawgeti(L, 2);
auto g = tonumber(L, -1); pop(L);
rawgeti(L, 3);
auto b = tonumber(L, -1); pop(L);
rawgeti(L, 4);
auto a = tonumber(L, -1); pop(L);
pop(L);
return glm::vec4(r/255, g/255, b/255, a/255);
}
int pushvalue(lua::State*, const dynamic::Value& value);
dynamic::Value tovalue(lua::State*, int idx);
inline bool getfield(lua::State* L, const std::string& name, int idx=-1) {
lua_getfield(L, idx, name.c_str());
if (isnil(L, -1)) {
pop(L);
return false;
}
return true;
}
inline void setfield(lua::State* L, const std::string& name, int idx=-2) {
lua_setfield(L, idx, name.c_str());
}
inline void setglobal(lua::State* L, const std::string& name) {
lua_setglobal(L, name.c_str());
}
inline const char* require_string(lua::State* L, int idx) {
if (!isstring(L, idx)) {
throw luaerror("string expected at "+std::to_string(idx));
}
return tostring(L, idx);
}
std::wstring require_wstring(lua::State*, int idx);
inline bool rename(lua::State* L, const std::string& from, const std::string& to) {
getglobal(L, from);
if (isnil(L, -1)) {
pop(L, 1);
return false;
}
setglobal(L, to);
// remove previous
pushnil(L);
setglobal(L, from);
return true;
}
inline void remove(lua::State* L, const std::string& name) {
pushnil(L);
setglobal(L, name);
}
inline void loadbuffer(lua::State* L, int env, const std::string& src, const std::string& file) {
if (luaL_loadbuffer(L, src.c_str(), src.length(), file.c_str())) {
throw luaerror(tostring(L, -1));
}
if (env && getglobal(L, env_name(env))) {
lua_setfenv(L, -2);
}
}
int call(lua::State*, int argc, int nresults=-1);
int call_nothrow(lua::State*, int argc);
inline int eval(lua::State* L, int env, const std::string& src, const std::string& file="<eval>") {
auto srcText = "return "+src;
loadbuffer(L, env, srcText, file);
return call(L, 0);
}
inline int execute(lua::State* L, int env, const std::string& src, const std::string& file="<eval>") {
loadbuffer(L, env, src, file);
return call_nothrow(L, 0);
}
runnable create_runnable(lua::State*);
scripting::common_func create_lambda(lua::State* );
inline int pushenv(lua::State* L, int env) {
if (getglobal(L, env_name(env))) {
return 1;
}
return 0;
}
int createEnvironment(lua::State*, int parent);
void removeEnvironment(lua::State*, int id);
void dump_stack(lua::State*);
inline void addfunc(lua::State* L, const std::string& name, lua_CFunction func) {
pushcfunction(L, func);
setglobal(L, name);
}
inline void openlib(lua::State* L, const std::string& name, const luaL_Reg* libfuncs) {
createtable(L, 0, 0);
luaL_setfuncs(L, libfuncs, 0);
setglobal(L, name);
}
}
#endif // LOGIC_SCRIPTING_LUA_UTIL_HPP_

View File

@ -1,5 +1,7 @@
#include "scripting.hpp"
#include "lua/lua_engine.hpp"
#include "../../content/ContentPack.hpp"
#include "../../debug/Logger.hpp"
#include "../../engine.hpp"
@ -16,39 +18,32 @@
#include "../../util/timeutil.hpp"
#include "../../voxels/Block.hpp"
#include "../../world/Level.hpp"
#include "lua/LuaState.hpp"
#include <iostream>
#include <stdexcept>
using namespace scripting;
namespace scripting {
extern lua::LuaState* state;
}
static debug::Logger logger("scripting");
Engine* scripting::engine = nullptr;
lua::LuaState* scripting::state = nullptr;
Level* scripting::level = nullptr;
const Content* scripting::content = nullptr;
const ContentIndices* scripting::indices = nullptr;
BlocksController* scripting::blocks = nullptr;
LevelController* scripting::controller = nullptr;
void load_script(const fs::path& name) {
static void load_script(const fs::path& name) {
auto paths = scripting::engine->getPaths();
fs::path file = paths->getResources()/fs::path("scripts")/name;
std::string src = files::read_string(file);
state->execute(0, src, file.u8string());
lua::execute(lua::get_main_thread(), 0, src, file.u8string());
}
void scripting::initialize(Engine* engine) {
scripting::engine = engine;
state = new lua::LuaState();
lua::initialize();
load_script(fs::path("stdlib.lua"));
load_script(fs::path("stdcmd.lua"));
@ -59,46 +54,49 @@ scriptenv scripting::get_root_environment() {
}
scriptenv scripting::create_pack_environment(const ContentPack& pack) {
int id = state->createEnvironment(0);
state->pushenv(id);
state->pushvalue(-1);
state->setfield("PACK_ENV");
state->pushstring(pack.id);
state->setfield("PACK_ID");
state->pop();
auto L = lua::get_main_thread();
int id = lua::createEnvironment(L, 0);
lua::pushenv(L, id);
lua::pushvalue(L, -1);
lua::setfield(L, "PACK_ENV");
lua::pushstring(L, pack.id);
lua::setfield(L, "PACK_ID");
lua::pop(L);
return std::shared_ptr<int>(new int(id), [=](int* id) {
state->removeEnvironment(*id);
lua::removeEnvironment(L, *id);
delete id;
});
}
scriptenv scripting::create_doc_environment(const scriptenv& parent, const std::string& name) {
int id = state->createEnvironment(*parent);
state->pushenv(id);
state->pushvalue(-1);
state->setfield("DOC_ENV");
state->pushstring(name.c_str());
state->setfield("DOC_NAME");
auto L = lua::get_main_thread();
int id = lua::createEnvironment(L, *parent);
lua::pushenv(L, id);
lua::pushvalue(L, -1);
lua::setfield(L, "DOC_ENV");
lua::pushstring(L, name);
lua::setfield(L, "DOC_NAME");
if (state->getglobal("Document")) {
if (state->getfield("new")) {
state->pushstring(name.c_str());
if (state->callNoThrow(1)) {
state->setfield("document", -3);
if (lua::getglobal(L, "Document")) {
if (lua::getfield(L, "new")) {
lua::pushstring(L, name);
if (lua::call_nothrow(L, 1)) {
lua::setfield(L, "document", -3);
}
}
state->pop();
lua::pop(L);
}
state->pop();
lua::pop(L);
return std::shared_ptr<int>(new int(id), [=](int* id) {
state->removeEnvironment(*id);
lua::removeEnvironment(L, *id);
delete id;
});
}
void scripting::process_post_runnables() {
if (state->getglobal("__process_post_runnables")) {
state->callNoThrow(0);
auto L = lua::get_main_thread();
if (lua::getglobal(L, "__process_post_runnables")) {
lua::call_nothrow(L, 0);
}
}
@ -110,38 +108,42 @@ void scripting::on_world_load(LevelController* controller) {
scripting::controller = controller;
load_script("world.lua");
auto L = lua::get_main_thread();
for (auto& pack : scripting::engine->getContentPacks()) {
state->emit_event(pack.id + ".worldopen");
lua::emit_event(L, pack.id + ".worldopen");
}
}
void scripting::on_world_tick() {
auto L = lua::get_main_thread();
for (auto& pack : scripting::engine->getContentPacks()) {
state->emit_event(pack.id + ".worldtick");
lua::emit_event(L, pack.id + ".worldtick");
}
}
void scripting::on_world_save() {
auto L = lua::get_main_thread();
for (auto& pack : scripting::engine->getContentPacks()) {
state->emit_event(pack.id + ".worldsave");
lua::emit_event(L, pack.id + ".worldsave");
}
}
void scripting::on_world_quit() {
auto L = lua::get_main_thread();
for (auto& pack : scripting::engine->getContentPacks()) {
state->emit_event(pack.id + ".worldquit");
lua::emit_event(L, pack.id + ".worldquit");
}
state->getglobal("pack");
lua::getglobal(L, "pack");
for (auto& pack : scripting::engine->getContentPacks()) {
state->getfield("unload");
state->pushstring(pack.id);
state->callNoThrow(1);
lua::getfield(L, "unload");
lua::pushstring(L, pack.id);
lua::call_nothrow(L, 1);
}
state->pop();
lua::pop(L);
if (state->getglobal("__scripts_cleanup")) {
state->callNoThrow(0);
if (lua::getglobal(L, "__scripts_cleanup")) {
lua::call_nothrow(L, 0);
}
scripting::level = nullptr;
scripting::content = nullptr;
@ -152,77 +154,73 @@ void scripting::on_world_quit() {
void scripting::on_blocks_tick(const Block* block, int tps) {
std::string name = block->name + ".blockstick";
state->emit_event(name, [tps] (lua::LuaState* state) {
state->pushinteger(tps);
return 1;
lua::emit_event(lua::get_main_thread(), name, [tps] (auto L) {
return lua::pushinteger(L, tps);
});
}
void scripting::update_block(const Block* block, int x, int y, int z) {
std::string name = block->name + ".update";
state->emit_event(name, [x, y, z] (lua::LuaState* state) {
state->pushivec3(x, y, z);
return 3;
lua::emit_event(lua::get_main_thread(), name, [x, y, z] (auto L) {
return lua::pushivec3(L, x, y, z);
});
}
void scripting::random_update_block(const Block* block, int x, int y, int z) {
std::string name = block->name + ".randupdate";
state->emit_event(name, [x, y, z] (lua::LuaState* state) {
state->pushivec3(x, y, z);
return 3;
lua::emit_event(lua::get_main_thread(), name, [x, y, z] (auto L) {
return lua::pushivec3(L, x, y, z);
});
}
void scripting::on_block_placed(Player* player, const Block* block, int x, int y, int z) {
std::string name = block->name + ".placed";
state->emit_event(name, [x, y, z, player] (lua::LuaState* state) {
state->pushivec3(x, y, z);
state->pushinteger(player->getId());
return 4;
lua::emit_event(lua::get_main_thread(), name, [x, y, z, player] (auto L) {
lua::pushivec3(L, x, y, z);
lua::pushinteger(L, player->getId());
return 4;
});
}
void scripting::on_block_broken(Player* player, const Block* block, int x, int y, int z) {
std::string name = block->name + ".broken";
state->emit_event(name, [x, y, z, player] (lua::LuaState* state) {
state->pushivec3(x, y, z);
state->pushinteger(player->getId());
lua::emit_event(lua::get_main_thread(), name, [x, y, z, player] (auto L) {
lua::pushivec3(L, x, y, z);
lua::pushinteger(L, player->getId());
return 4;
});
}
bool scripting::on_block_interact(Player* player, const Block* block, glm::ivec3 pos) {
std::string name = block->name + ".interact";
return state->emit_event(name, [pos, player] (lua::LuaState* state) {
state->pushivec3(pos.x, pos.y, pos.z);
state->pushinteger(player->getId());
return lua::emit_event(lua::get_main_thread(), name, [pos, player] (auto L) {
lua::pushivec3(L, pos.x, pos.y, pos.z);
lua::pushinteger(L, player->getId());
return 4;
});
}
bool scripting::on_item_use(Player* player, const ItemDef* item) {
std::string name = item->name + ".use";
return state->emit_event(name, [player] (lua::LuaState* state) {
state->pushinteger(player->getId());
return 1;
return lua::emit_event(lua::get_main_thread(), name, [player] (lua::State* L) {
return lua::pushinteger(L, player->getId());
});
}
bool scripting::on_item_use_on_block(Player* player, const ItemDef* item, int x, int y, int z) {
std::string name = item->name + ".useon";
return state->emit_event(name, [x, y, z, player] (lua::LuaState* state) {
state->pushivec3(x, y, z);
state->pushinteger(player->getId());
return lua::emit_event(lua::get_main_thread(), name, [x, y, z, player] (auto L) {
lua::pushivec3(L, x, y, z);
lua::pushinteger(L, player->getId());
return 4;
});
}
bool scripting::on_item_break_block(Player* player, const ItemDef* item, int x, int y, int z) {
std::string name = item->name + ".blockbreakby";
return state->emit_event(name, [x, y, z, player] (lua::LuaState* state) {
state->pushivec3(x, y, z);
state->pushinteger(player->getId());
return lua::emit_event(lua::get_main_thread(), name, [x, y, z, player] (auto L) {
lua::pushivec3(L, x, y, z);
lua::pushinteger(L, player->getId());
return 4;
});
}
@ -233,9 +231,9 @@ void scripting::on_ui_open(
) {
auto argsptr = std::make_shared<std::vector<dynamic::Value>>(std::move(args));
std::string name = layout->getId() + ".open";
state->emit_event(name, [=] (lua::LuaState* state) {
lua::emit_event(lua::get_main_thread(), name, [=] (auto L) {
for (const auto& value : *argsptr) {
state->pushvalue(value);
lua::pushvalue(L, value);
}
return argsptr->size();
});
@ -243,37 +241,37 @@ void scripting::on_ui_open(
void scripting::on_ui_progress(UiDocument* layout, int workDone, int workTotal) {
std::string name = layout->getId() + ".progress";
state->emit_event(name, [=] (lua::LuaState* state) {
state->pushinteger(workDone);
state->pushinteger(workTotal);
lua::emit_event(lua::get_main_thread(), name, [=] (auto L) {
lua::pushinteger(L, workDone);
lua::pushinteger(L, workTotal);
return 2;
});
}
void scripting::on_ui_close(UiDocument* layout, Inventory* inventory) {
std::string name = layout->getId() + ".close";
state->emit_event(name, [inventory] (lua::LuaState* state) {
state->pushinteger(inventory == nullptr ? 0 : inventory->getId());
return 1;
lua::emit_event(lua::get_main_thread(), name, [inventory] (auto L) {
return lua::pushinteger(L, inventory ? inventory->getId() : 0);
});
}
bool scripting::register_event(int env, const std::string& name, const std::string& id) {
if (state->pushenv(env) == 0) {
state->pushglobals();
auto L = lua::get_main_thread();
if (lua::pushenv(L, env) == 0) {
lua::pushglobals(L);
}
if (state->getfield(name)) {
state->pop();
state->getglobal("events");
state->getfield("on");
state->pushstring(id);
state->getfield(name, -4);
state->callNoThrow(2);
state->pop();
if (lua::getfield(L, name)) {
lua::pop(L);
lua::getglobal(L, "events");
lua::getfield(L, "on");
lua::pushstring(L, id);
lua::getfield(L, name, -4);
lua::call_nothrow(L, 2);
lua::pop(L);
// remove previous name
state->pushnil();
state->setfield(name);
lua::pushnil(L);
lua::setfield(L, name);
return true;
}
return false;
@ -283,7 +281,7 @@ void scripting::load_block_script(const scriptenv& senv, const std::string& pref
int env = *senv;
std::string src = files::read_string(file);
logger.info() << "script (block) " << file.u8string();
state->execute(env, src, file.u8string());
lua::execute(lua::get_main_thread(), env, src, file.u8string());
funcsset.init = register_event(env, "init", prefix+".init");
funcsset.update = register_event(env, "on_update", prefix+".update");
funcsset.randupdate = register_event(env, "on_random_update", prefix+".randupdate");
@ -297,7 +295,7 @@ void scripting::load_item_script(const scriptenv& senv, const std::string& prefi
int env = *senv;
std::string src = files::read_string(file);
logger.info() << "script (item) " << file.u8string();
state->execute(env, src, file.u8string());
lua::execute(lua::get_main_thread(), env, src, file.u8string());
funcsset.init = register_event(env, "init", prefix+".init");
funcsset.on_use = register_event(env, "on_use", prefix+".use");
@ -310,9 +308,7 @@ void scripting::load_world_script(const scriptenv& senv, const std::string& pref
std::string src = files::read_string(file);
logger.info() << "loading world script for " << prefix;
state->loadbuffer(env, src, file.u8string());
state->callNoThrow(0);
lua::execute(lua::get_main_thread(), env, src, file.u8string());
register_event(env, "init", prefix+".init");
register_event(env, "on_world_open", prefix+".worldopen");
@ -327,17 +323,14 @@ void scripting::load_layout_script(const scriptenv& senv, const std::string& pre
std::string src = files::read_string(file);
logger.info() << "loading script " << file.u8string();
state->loadbuffer(env, src, file.u8string());
state->callNoThrow(0);
lua::execute(lua::get_main_thread(), env, src, file.u8string());
script.onopen = register_event(env, "on_open", prefix+".open");
script.onprogress = register_event(env, "on_progress", prefix+".progress");
script.onclose = register_event(env, "on_close", prefix+".close");
}
void scripting::close() {
delete state;
state = nullptr;
lua::finalize();
content = nullptr;
indices = nullptr;
level = nullptr;

View File

@ -1,42 +1,42 @@
#include "scripting_functional.hpp"
#include "lua/LuaState.hpp"
#include "lua/lua_engine.hpp"
#include "../../debug/Logger.hpp"
#include "../../util/stringutil.hpp"
namespace scripting {
extern lua::LuaState* state;
}
using namespace scripting;
static debug::Logger logger("scripting_func");
using namespace scripting;
runnable scripting::create_runnable(
const scriptenv& env,
const std::string& src,
const std::string& file
) {
auto L = lua::get_main_thread();
try {
state->loadbuffer(*env, src, file);
return state->createRunnable();
lua::loadbuffer(L, *env, src, file);
return lua::create_runnable(L);
} catch (const lua::luaerror& err) {
logger.error() << err.what();
return [](){};
}
}
static bool processCallback(
static lua::State* process_callback(
const scriptenv& env,
const std::string& src,
const std::string& file
) {
auto L = lua::get_main_thread();
try {
return state->eval(*env, src, file) != 0;
if (lua::eval(L, *env, src, file) != 0) {
return L;
}
} catch (lua::luaerror& err) {
logger.error() << err.what();
return false;
}
return nullptr;
}
wstringconsumer scripting::create_wstring_consumer(
@ -45,9 +45,9 @@ wstringconsumer scripting::create_wstring_consumer(
const std::string& file
) {
return [=](const std::wstring& x){
if (processCallback(env, src, file)) {
state->pushstring(util::wstr2str_utf8(x));
state->callNoThrow(1);
if (auto L = process_callback(env, src, file)) {
lua::pushwstring(L, x);
lua::call_nothrow(L, 1);
}
};
}
@ -58,12 +58,12 @@ wstringsupplier scripting::create_wstring_supplier(
const std::string& file
) {
return [=](){
if (processCallback(env, src, file)) {
if (state->isfunction(-1)) {
state->callNoThrow(0);
if (auto L = process_callback(env, src, file)) {
if (lua::isfunction(L, -1)) {
lua::call_nothrow(L, 0);
}
auto str = state->tostring(-1); state->pop();
return util::str2wstr_utf8(str);
auto str = lua::require_wstring(L, -1); lua::pop(L);
return str;
}
return std::wstring(L"");
};
@ -75,10 +75,10 @@ wstringchecker scripting::create_wstring_validator(
const std::string& file
) {
return [=](const std::wstring& x){
if (processCallback(env, src, file)) {
state->pushstring(util::wstr2str_utf8(x));
if (state->callNoThrow(1))
return state->toboolean(-1);
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;
};
@ -90,9 +90,9 @@ boolconsumer scripting::create_bool_consumer(
const std::string& file
) {
return [=](bool x){
if (processCallback(env, src, file)) {
state->pushboolean(x);
state->callNoThrow(1);
if (auto L = process_callback(env, src, file)) {
lua::pushboolean(L, x);
lua::call_nothrow(L, 1);
}
};
}
@ -103,11 +103,11 @@ boolsupplier scripting::create_bool_supplier(
const std::string& file
) {
return [=](){
if (processCallback(env, src, file)) {
if (state->isfunction(-1)) {
state->callNoThrow(0);
if (auto L = process_callback(env, src, file)) {
if (lua::isfunction(L, -1)) {
lua::call_nothrow(L, 0);
}
bool x = state->toboolean(-1); state->pop();
bool x = lua::toboolean(L,-1); lua::pop(L);
return x;
}
return false;
@ -120,9 +120,9 @@ doubleconsumer scripting::create_number_consumer(
const std::string& file
) {
return [=](double x){
if (processCallback(env, src, file)) {
state->pushnumber(x);
state->callNoThrow(1);
if (auto L = process_callback(env, src, file)) {
lua::pushnumber(L, x);
lua::call_nothrow(L, 1);
}
};
}
@ -133,12 +133,12 @@ doublesupplier scripting::create_number_supplier(
const std::string& file
) {
return [=](){
if (processCallback(env, src, file)) {
if (state->isfunction(-1)) {
state->callNoThrow(0);
if (auto L = process_callback(env, src, file)) {
if (lua::isfunction(L, -1)) {
lua::call_nothrow(L, 0);
}
auto x = state->tonumber(-1);
state->pop();
auto x = lua::tonumber(L, -1);
lua::pop(L);
return x;
}
return 0.0;
@ -150,12 +150,12 @@ int_array_consumer scripting::create_int_array_consumer(
const std::string& src,
const std::string& file
) {
return [=](const int arr[], size_t len){
if (processCallback(env, src, file)) {
return [=](const int arr[], size_t len) {
if (auto L = process_callback(env, src, file)) {
for (uint i = 0; i < len; i++) {
state->pushinteger(arr[i]);
lua::pushinteger(L, arr[i]);
}
state->callNoThrow(len);
lua::call_nothrow(L, len);
}
};
}
@ -165,13 +165,13 @@ vec2supplier scripting::create_vec2_supplier(
const std::string& src,
const std::string& file
) {
return [=](){
if (processCallback(env, src, file)) {
if (state->isfunction(-1)) {
state->callNoThrow(0);
return [=]() {
if (auto L = process_callback(env, src, file)) {
if (lua::isfunction(L, -1)) {
lua::call_nothrow(L, 0);
}
auto y = state->tonumber(-1); state->pop();
auto x = state->tonumber(-1); state->pop();
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);

View File

@ -2,7 +2,7 @@
#include "scripting.hpp"
#include "lua/api_lua.hpp"
#include "lua/LuaState.hpp"
#include "lua/lua_engine.hpp"
#include "../../debug/Logger.hpp"
#include "../../frontend/hud.hpp"
@ -10,9 +10,7 @@
#include "../../files/files.hpp"
#include "../../engine.hpp"
namespace scripting {
extern lua::LuaState* state;
}
using namespace scripting;
static debug::Logger logger("scripting-hud");
@ -20,21 +18,21 @@ Hud* scripting::hud = nullptr;
void scripting::on_frontend_init(Hud* hud) {
scripting::hud = hud;
scripting::state->openlib("hud", hudlib);
lua::openlib(lua::get_main_thread(), "hud", hudlib);
for (auto& pack : scripting::engine->getContentPacks()) {
state->emit_event(pack.id + ".hudopen", [&] (lua::LuaState* state) {
state->pushinteger(hud->getPlayer()->getId());
return 1;
for (auto& pack : engine->getContentPacks()) {
lua::emit_event(lua::get_main_thread(), pack.id + ".hudopen",
[&] (lua::State* L) {
return lua::pushinteger(L, hud->getPlayer()->getId());
});
}
}
void scripting::on_frontend_close() {
for (auto& pack : scripting::engine->getContentPacks()) {
state->emit_event(pack.id + ".hudclose", [&] (lua::LuaState* state) {
state->pushinteger(hud->getPlayer()->getId());
return 1;
for (auto& pack : engine->getContentPacks()) {
lua::emit_event(lua::get_main_thread(), pack.id + ".hudclose",
[&] (lua::State* L) {
return lua::pushinteger(L, hud->getPlayer()->getId());
});
}
scripting::hud = nullptr;
@ -45,8 +43,7 @@ void scripting::load_hud_script(const scriptenv& senv, const std::string& packid
std::string src = files::read_string(file);
logger.info() << "loading script " << file.u8string();
state->loadbuffer(env, src, file.u8string());
state->callNoThrow(0);
lua::execute(lua::get_main_thread(), env, src, file.u8string());
register_event(env, "init", packid+".init");
register_event(env, "on_hud_open", packid+".hudopen");

View File

@ -234,9 +234,6 @@ bool Chunks::checkReplaceability(const Block* def, blockstate state, glm::ivec3
for (int sy = 0; sy < size.y; sy++) {
for (int sz = 0; sz < size.z; sz++) {
for (int sx = 0; sx < size.x; sx++) {
blockstate segState = state;
segState.segment = segment_to_int(sx, sy, sz);
auto pos = origin;
pos += rotation.axisX * sx;
pos += rotation.axisY * sy;