refactor
This commit is contained in:
parent
3cd648e10c
commit
b38afe9e34
@ -32,6 +32,77 @@ bool Attribute::asBool() const {
|
||||
return text == "true" || text == "1";
|
||||
}
|
||||
|
||||
/* Read 2d vector formatted `x,y`*/
|
||||
glm::vec2 Attribute::asVec2() const {
|
||||
size_t pos = text.find(',');
|
||||
if (pos == std::string::npos) {
|
||||
throw std::runtime_error("invalid vec2 value "+escape_string(text));
|
||||
}
|
||||
return glm::vec2(
|
||||
util::parse_double(text, 0, pos),
|
||||
util::parse_double(text, pos+1, text.length()-pos-1)
|
||||
);
|
||||
}
|
||||
|
||||
/* Read 3d vector formatted `x,y,z`*/
|
||||
glm::vec3 Attribute::asVec3() const {
|
||||
size_t pos1 = text.find(',');
|
||||
if (pos1 == std::string::npos) {
|
||||
throw std::runtime_error("invalid vec3 value "+escape_string(text));
|
||||
}
|
||||
size_t pos2 = text.find(',', pos1+1);
|
||||
if (pos2 == std::string::npos) {
|
||||
throw std::runtime_error("invalid vec3 value "+escape_string(text));
|
||||
}
|
||||
return glm::vec3(
|
||||
util::parse_double(text, 0, pos1),
|
||||
util::parse_double(text, pos1+1, pos2),
|
||||
util::parse_double(text, pos2+1, text.length()-pos2-1)
|
||||
);
|
||||
}
|
||||
|
||||
/* Read 4d vector formatted `x,y,z,w`*/
|
||||
glm::vec4 Attribute::asVec4() const {
|
||||
size_t pos1 = text.find(',');
|
||||
if (pos1 == std::string::npos) {
|
||||
throw std::runtime_error("invalid vec4 value "+escape_string(text));
|
||||
}
|
||||
size_t pos2 = text.find(',', pos1+1);
|
||||
if (pos2 == std::string::npos) {
|
||||
throw std::runtime_error("invalid vec4 value "+escape_string(text));
|
||||
}
|
||||
size_t pos3 = text.find(',', pos2+1);
|
||||
if (pos3 == std::string::npos) {
|
||||
throw std::runtime_error("invalid vec4 value "+escape_string(text));
|
||||
}
|
||||
return glm::vec4(
|
||||
util::parse_double(text, 0, pos1),
|
||||
util::parse_double(text, pos1+1, pos2-pos1-1),
|
||||
util::parse_double(text, pos2+1, pos3-pos2-1),
|
||||
util::parse_double(text, pos3+1, text.length()-pos3-1)
|
||||
);
|
||||
}
|
||||
|
||||
/* Read RGBA color. Supported formats:
|
||||
- "#RRGGBB" or "#RRGGBBAA" hex color */
|
||||
glm::vec4 Attribute::asColor() const {
|
||||
if (text[0] == '#') {
|
||||
if (text.length() != 7 && text.length() != 9) {
|
||||
throw std::runtime_error("#RRGGBB or #RRGGBBAA required");
|
||||
}
|
||||
int a = 255;
|
||||
int r = (hexchar2int(text[1]) << 4) | hexchar2int(text[2]);
|
||||
int g = (hexchar2int(text[3]) << 4) | hexchar2int(text[4]);
|
||||
int b = (hexchar2int(text[5]) << 4) | hexchar2int(text[6]);
|
||||
if (text.length() == 9) {
|
||||
a = (hexchar2int(text[7]) << 4) | hexchar2int(text[8]);
|
||||
}
|
||||
return glm::vec4(r / 255.f, g / 255.f, b / 255.f, a / 255.f);
|
||||
} else {
|
||||
throw std::runtime_error("hex colors are only supported");
|
||||
}
|
||||
}
|
||||
|
||||
Node::Node(std::string tag) : tag(tag) {
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <glm/glm.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "commons.h"
|
||||
@ -30,6 +31,10 @@ namespace xml {
|
||||
int64_t asInt() const;
|
||||
double asFloat() const;
|
||||
bool asBool() const;
|
||||
glm::vec2 asVec2() const;
|
||||
glm::vec3 asVec3() const;
|
||||
glm::vec4 asVec4() const;
|
||||
glm::vec4 asColor() const;
|
||||
};
|
||||
|
||||
/* XML element class. Text element has tag 'text' and attribute 'text' */
|
||||
|
||||
@ -4,7 +4,8 @@
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
typedef std::function<void()> runnable;
|
||||
typedef std::function<void(const std::string&)> stringconsumer;
|
||||
using runnable = std::function<void()>;
|
||||
using stringconsumer = std::function<void(const std::string&)>;
|
||||
using wstringconsumer = std::function<void(const std::wstring&)>;
|
||||
|
||||
#endif // DELEGATES_H_
|
||||
|
||||
@ -12,92 +12,6 @@
|
||||
|
||||
using namespace gui;
|
||||
|
||||
static double readDouble(const std::string& str, size_t offset, size_t len) {
|
||||
double value;
|
||||
auto res = std::from_chars(str.data()+offset, str.data()+offset+len, value);
|
||||
if (res.ptr != str.data()+offset+len) {
|
||||
throw std::runtime_error("invalid number format "+escape_string(str));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Read 2d vector formatted `x,y`*/
|
||||
static glm::vec2 readVec2(const std::string& str) {
|
||||
size_t pos = str.find(',');
|
||||
if (pos == std::string::npos) {
|
||||
throw std::runtime_error("invalid vec2 value "+escape_string(str));
|
||||
}
|
||||
return glm::vec2(
|
||||
readDouble(str, 0, pos),
|
||||
readDouble(str, pos+1, str.length()-pos-1)
|
||||
);
|
||||
}
|
||||
|
||||
/* Read 3d vector formatted `x,y,z`*/
|
||||
[[maybe_unused]]
|
||||
static glm::vec3 readVec3(const std::string& str) {
|
||||
size_t pos1 = str.find(',');
|
||||
if (pos1 == std::string::npos) {
|
||||
throw std::runtime_error("invalid vec3 value "+escape_string(str));
|
||||
}
|
||||
size_t pos2 = str.find(',', pos1+1);
|
||||
if (pos2 == std::string::npos) {
|
||||
throw std::runtime_error("invalid vec3 value "+escape_string(str));
|
||||
}
|
||||
return glm::vec3(
|
||||
readDouble(str, 0, pos1),
|
||||
readDouble(str, pos1+1, pos2),
|
||||
readDouble(str, pos2+1, str.length()-pos2-1)
|
||||
);
|
||||
}
|
||||
|
||||
/* Read 4d vector formatted `x,y,z,w`*/
|
||||
static glm::vec4 readVec4(const std::string& str) {
|
||||
size_t pos1 = str.find(',');
|
||||
if (pos1 == std::string::npos) {
|
||||
throw std::runtime_error("invalid vec4 value "+escape_string(str));
|
||||
}
|
||||
size_t pos2 = str.find(',', pos1+1);
|
||||
if (pos2 == std::string::npos) {
|
||||
throw std::runtime_error("invalid vec4 value "+escape_string(str));
|
||||
}
|
||||
size_t pos3 = str.find(',', pos2+1);
|
||||
if (pos3 == std::string::npos) {
|
||||
throw std::runtime_error("invalid vec4 value "+escape_string(str));
|
||||
}
|
||||
return glm::vec4(
|
||||
readDouble(str, 0, pos1),
|
||||
readDouble(str, pos1+1, pos2-pos1-1),
|
||||
readDouble(str, pos2+1, pos3-pos2-1),
|
||||
readDouble(str, pos3+1, str.length()-pos3-1)
|
||||
);
|
||||
}
|
||||
|
||||
/* Read RGBA color. Supported formats:
|
||||
- "#RRGGBB" or "#RRGGBBAA" hex color */
|
||||
static glm::vec4 readColor(const std::string& str) {
|
||||
if (str[0] == '#') {
|
||||
if (str.length() != 7 && str.length() != 9) {
|
||||
throw std::runtime_error("#RRGGBB or #RRGGBBAA required");
|
||||
}
|
||||
int a = 255;
|
||||
int r = (hexchar2int(str[1]) << 4) | hexchar2int(str[2]);
|
||||
int g = (hexchar2int(str[3]) << 4) | hexchar2int(str[4]);
|
||||
int b = (hexchar2int(str[5]) << 4) | hexchar2int(str[6]);
|
||||
if (str.length() == 9) {
|
||||
a = (hexchar2int(str[7]) << 4) | hexchar2int(str[8]);
|
||||
}
|
||||
return glm::vec4(
|
||||
r / 255.f,
|
||||
g / 255.f,
|
||||
b / 255.f,
|
||||
a / 255.f
|
||||
);
|
||||
} else {
|
||||
throw std::runtime_error("hex colors are only supported");
|
||||
}
|
||||
}
|
||||
|
||||
static Align align_from_string(const std::string& str, Align def) {
|
||||
if (str == "left") return Align::left;
|
||||
if (str == "center") return Align::center;
|
||||
@ -108,16 +22,16 @@ static Align align_from_string(const std::string& str, Align def) {
|
||||
/* Read basic UINode properties */
|
||||
static void readUINode(xml::xmlelement element, UINode& node) {
|
||||
if (element->has("coord")) {
|
||||
node.setCoord(readVec2(element->attr("coord").getText()));
|
||||
node.setCoord(element->attr("coord").asVec2());
|
||||
}
|
||||
if (element->has("size")) {
|
||||
node.setSize(readVec2(element->attr("size").getText()));
|
||||
node.setSize(element->attr("size").asVec2());
|
||||
}
|
||||
if (element->has("color")) {
|
||||
node.setColor(readColor(element->attr("color").getText()));
|
||||
node.setColor(element->attr("color").asColor());
|
||||
}
|
||||
if (element->has("margin")) {
|
||||
node.setMargin(readVec4(element->attr("margin").getText()));
|
||||
node.setMargin(element->attr("margin").asVec4());
|
||||
}
|
||||
|
||||
std::string alignName = element->attr("align", "").getText();
|
||||
@ -138,7 +52,7 @@ static void _readPanel(UiXmlReader& reader, xml::xmlelement element, Panel& pane
|
||||
readUINode(element, panel);
|
||||
|
||||
if (element->has("padding")) {
|
||||
panel.setPadding(readVec4(element->attr("padding").getText()));
|
||||
panel.setPadding(element->attr("padding").asVec4());
|
||||
}
|
||||
|
||||
if (element->has("size")) {
|
||||
@ -185,7 +99,7 @@ static std::shared_ptr<UINode> readButton(UiXmlReader& reader, xml::xmlelement e
|
||||
_readPanel(reader, element, *button);
|
||||
|
||||
if (element->has("onclick")) {
|
||||
runnable callback = scripting::create_runnable("<onclick>", element->attr("onclick").getText());
|
||||
auto callback = scripting::create_runnable("<onclick>", element->attr("onclick").getText());
|
||||
button->listenAction([callback](GUI*) {
|
||||
callback();
|
||||
});
|
||||
@ -202,6 +116,14 @@ static std::shared_ptr<UINode> readTextBox(UiXmlReader& reader, xml::xmlelement
|
||||
auto textbox = std::make_shared<TextBox>(placeholder, glm::vec4(0.0f));
|
||||
_readPanel(reader, element, *textbox);
|
||||
textbox->setText(text);
|
||||
|
||||
if (element->has("consumer")) {
|
||||
auto consumer = scripting::create_wstring_consumer(
|
||||
element->attr("consumer").getText(),
|
||||
reader.getFilename()
|
||||
);
|
||||
textbox->textConsumer(consumer);
|
||||
}
|
||||
return textbox;
|
||||
}
|
||||
|
||||
@ -230,7 +152,12 @@ std::shared_ptr<UINode> UiXmlReader::readXML(
|
||||
const std::string& filename,
|
||||
const std::string& source
|
||||
) {
|
||||
this->filename = filename;
|
||||
auto document = xml::parse(filename, source);
|
||||
auto root = document->getRoot();
|
||||
return readUINode(root);
|
||||
}
|
||||
|
||||
const std::string& UiXmlReader::getFilename() const {
|
||||
return filename;
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ namespace gui {
|
||||
|
||||
class UiXmlReader {
|
||||
std::unordered_map<std::string, uinode_reader> readers;
|
||||
std::string filename;
|
||||
public:
|
||||
UiXmlReader();
|
||||
|
||||
@ -25,6 +26,8 @@ namespace gui {
|
||||
const std::string& filename,
|
||||
const std::string& source
|
||||
);
|
||||
|
||||
const std::string& getFilename() const;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
168
src/logic/scripting/LuaState.cpp
Normal file
168
src/logic/scripting/LuaState.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
#include "LuaState.h"
|
||||
|
||||
#include "api_lua.h"
|
||||
|
||||
void lua::LuaState::addfunc(const std::string& name, lua_CFunction func) {
|
||||
lua_pushcfunction(L, func);
|
||||
lua_setglobal(L, name.c_str());
|
||||
}
|
||||
|
||||
bool lua::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;
|
||||
}
|
||||
|
||||
void lua::LuaState::setglobal(const std::string& name) {
|
||||
lua_setglobal(L, name.c_str());
|
||||
}
|
||||
|
||||
bool lua::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 lua::LuaState::remove(const std::string& name) {
|
||||
lua_pushnil(L);
|
||||
lua_setglobal(L, name.c_str());
|
||||
}
|
||||
|
||||
void lua::LuaState::createFuncs() {
|
||||
openlib("pack", packlib, 0);
|
||||
openlib("world", worldlib, 0);
|
||||
openlib("player", playerlib, 0);
|
||||
openlib("time", timelib, 0);
|
||||
openlib("file", filelib, 0);
|
||||
|
||||
addfunc("print", l_print);
|
||||
|
||||
addfunc("block_index", l_block_index);
|
||||
addfunc("block_name", l_block_name);
|
||||
addfunc("blocks_count", l_blocks_count);
|
||||
addfunc("is_solid_at", l_is_solid_at);
|
||||
addfunc("is_replaceable_at", l_is_replaceable_at);
|
||||
addfunc("set_block", l_set_block);
|
||||
addfunc("get_block", l_get_block);
|
||||
addfunc("get_block_X", l_get_block_x);
|
||||
addfunc("get_block_Y", l_get_block_y);
|
||||
addfunc("get_block_Z", l_get_block_z);
|
||||
addfunc("get_block_states", l_get_block_states);
|
||||
addfunc("get_block_user_bits", l_get_block_user_bits);
|
||||
addfunc("set_block_user_bits", l_set_block_user_bits);
|
||||
}
|
||||
|
||||
lua::luaerror::luaerror(const std::string& message) : std::runtime_error(message) {
|
||||
}
|
||||
|
||||
lua::LuaState::LuaState() {
|
||||
L = luaL_newstate();
|
||||
if (L == nullptr) {
|
||||
throw lua::luaerror("could not to initialize Lua");
|
||||
}
|
||||
// Allowed standard libraries
|
||||
luaopen_base(L);
|
||||
luaopen_math(L);
|
||||
luaopen_string(L);
|
||||
luaopen_table(L);
|
||||
|
||||
std::cout << LUA_VERSION << std::endl;
|
||||
# ifdef LUAJIT_VERSION
|
||||
luaopen_jit(L);
|
||||
std::cout << LUAJIT_VERSION << std::endl;
|
||||
# endif // LUAJIT_VERSION
|
||||
|
||||
createFuncs();
|
||||
}
|
||||
|
||||
lua::LuaState::~LuaState() {
|
||||
lua_close(L);
|
||||
}
|
||||
|
||||
void lua::LuaState::logError(const std::string& text) {
|
||||
std::cerr << text << std::endl;
|
||||
}
|
||||
|
||||
void lua::LuaState::loadbuffer(const std::string& src, const std::string& file) {
|
||||
if (luaL_loadbuffer(L, src.c_str(), src.length(), file.c_str())) {
|
||||
throw lua::luaerror(lua_tostring(L, -1));
|
||||
}
|
||||
}
|
||||
|
||||
int lua::LuaState::call(int argc) {
|
||||
if (lua_pcall(L, argc, LUA_MULTRET, 0)) {
|
||||
throw lua::luaerror(lua_tostring(L, -1));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua::LuaState::callNoThrow(int argc) {
|
||||
if (lua_pcall(L, argc, LUA_MULTRET, 0)) {
|
||||
logError(lua_tostring(L, -1));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua::LuaState::eval(const std::string& src, const std::string& file) {
|
||||
auto srcText = "return ("+src+")";
|
||||
loadbuffer(srcText, file);
|
||||
return call(0);
|
||||
}
|
||||
|
||||
int lua::LuaState::gettop() const {
|
||||
return lua_gettop(L);
|
||||
}
|
||||
|
||||
int lua::LuaState::pushinteger(luaint x) {
|
||||
lua_pushinteger(L, x);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua::LuaState::pushnumber(luanumber x) {
|
||||
lua_pushnumber(L, x);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua::LuaState::pushivec3(luaint x, luaint y, luaint z) {
|
||||
lua::pushivec3(L, x, y, z);
|
||||
return 3;
|
||||
}
|
||||
|
||||
int lua::LuaState::pushstring(const std::string& str) {
|
||||
lua_pushstring(L, str.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool lua::LuaState::toboolean(int index) {
|
||||
return lua_toboolean(L, index);
|
||||
}
|
||||
|
||||
lua::luaint lua::LuaState::tointeger(int index) {
|
||||
return lua_tointeger(L, index);
|
||||
}
|
||||
|
||||
void lua::LuaState::openlib(const std::string& name, const luaL_Reg* libfuncs, int nup) {
|
||||
lua_newtable(L);
|
||||
luaL_setfuncs(L, libfuncs, nup);
|
||||
lua_setglobal(L, name.c_str());
|
||||
}
|
||||
|
||||
const std::string lua::LuaState::storeAnonymous() {
|
||||
auto funcId = uintptr_t(lua_topointer(L, lua_gettop(L)));
|
||||
auto funcName = "F$"+std::to_string(funcId);
|
||||
lua_setglobal(L, funcName.c_str());
|
||||
return funcName;
|
||||
}
|
||||
48
src/logic/scripting/LuaState.h
Normal file
48
src/logic/scripting/LuaState.h
Normal file
@ -0,0 +1,48 @@
|
||||
#ifndef LOGIC_SCRIPTING_LUA_STATE_H_
|
||||
#define LOGIC_SCRIPTING_LUA_STATE_H_
|
||||
|
||||
#include <lua.hpp>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace lua {
|
||||
using luaint = lua_Integer;
|
||||
using luanumber = lua_Number;
|
||||
|
||||
class luaerror : public std::runtime_error {
|
||||
public:
|
||||
luaerror(const std::string& message);
|
||||
};
|
||||
|
||||
class LuaState {
|
||||
lua_State* L;
|
||||
|
||||
void logError(const std::string& text);
|
||||
public:
|
||||
LuaState();
|
||||
~LuaState();
|
||||
|
||||
void loadbuffer(const std::string& src, const std::string& file);
|
||||
int gettop() const;
|
||||
int pushivec3(luaint x, luaint y, luaint z);
|
||||
int pushinteger(luaint x);
|
||||
int pushnumber(luanumber x);
|
||||
int pushstring(const std::string& str);
|
||||
bool toboolean(int index);
|
||||
luaint tointeger(int index);
|
||||
int call(int argc);
|
||||
int callNoThrow(int argc);
|
||||
int eval(const std::string& src, const std::string& file="<eval>");
|
||||
void openlib(const std::string& name, const luaL_Reg* libfuncs, int nup);
|
||||
void addfunc(const std::string& name, lua_CFunction func);
|
||||
bool getglobal(const std::string& name);
|
||||
void setglobal(const std::string& name);
|
||||
bool rename(const std::string& from, const std::string& to);
|
||||
void remove(const std::string& name);;
|
||||
void createFuncs();
|
||||
|
||||
const std::string storeAnonymous();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // LOGIC_SCRIPTING_LUA_STATE_H_
|
||||
@ -1,432 +0,0 @@
|
||||
#include "api_lua.h"
|
||||
#include "scripting.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#include "../../files/files.h"
|
||||
#include "../../physics/Hitbox.h"
|
||||
#include "../../objects/Player.h"
|
||||
#include "../../world/Level.h"
|
||||
#include "../../world/World.h"
|
||||
#include "../../content/Content.h"
|
||||
#include "../../voxels/Block.h"
|
||||
#include "../../voxels/Chunks.h"
|
||||
#include "../../voxels/voxel.h"
|
||||
#include "../../lighting/Lighting.h"
|
||||
#include "../../logic/BlocksController.h"
|
||||
#include "../../window/Window.h"
|
||||
#include "../../engine.h"
|
||||
|
||||
inline int lua_pushivec3(lua_State* L, int x, int y, int z) {
|
||||
lua_pushinteger(L, x);
|
||||
lua_pushinteger(L, y);
|
||||
lua_pushinteger(L, z);
|
||||
return 3;
|
||||
}
|
||||
|
||||
inline void openlib(lua_State* L, const char* name, const luaL_Reg* libfuncs, int nup) {
|
||||
lua_newtable(L);
|
||||
luaL_setfuncs(L, libfuncs, nup);
|
||||
lua_setglobal(L, name);
|
||||
}
|
||||
|
||||
/* == file library == */
|
||||
static int l_file_resolve(lua_State* L) {
|
||||
std::string path = lua_tostring(L, 1);
|
||||
fs::path resolved = scripting::engine->getPaths()->resolve(path);
|
||||
lua_pushstring(L, resolved.u8string().c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_file_read(lua_State* L) {
|
||||
auto paths = scripting::engine->getPaths();
|
||||
fs::path path = paths->resolve(lua_tostring(L, 1));
|
||||
if (fs::is_regular_file(path)) {
|
||||
lua_pushstring(L, files::read_string(path).c_str());
|
||||
return 1;
|
||||
}
|
||||
return luaL_error(L, "file does not exists '%s'", path.u8string().c_str());
|
||||
}
|
||||
|
||||
static int l_file_write(lua_State* L) {
|
||||
auto paths = scripting::engine->getPaths();
|
||||
fs::path path = paths->resolve(lua_tostring(L, 1));
|
||||
const char* text = lua_tostring(L, 2);
|
||||
files::write_string(path, text);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_file_exists(lua_State* L) {
|
||||
auto paths = scripting::engine->getPaths();
|
||||
fs::path path = paths->resolve(lua_tostring(L, 1));
|
||||
lua_pushboolean(L, fs::exists(path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_file_isfile(lua_State* L) {
|
||||
auto paths = scripting::engine->getPaths();
|
||||
fs::path path = paths->resolve(lua_tostring(L, 1));
|
||||
lua_pushboolean(L, fs::is_regular_file(path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_file_isdir(lua_State* L) {
|
||||
auto paths = scripting::engine->getPaths();
|
||||
fs::path path = paths->resolve(lua_tostring(L, 1));
|
||||
lua_pushboolean(L, fs::is_directory(path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_file_length(lua_State* L) {
|
||||
auto paths = scripting::engine->getPaths();
|
||||
fs::path path = paths->resolve(lua_tostring(L, 1));
|
||||
if (fs::exists(path)){
|
||||
lua_pushinteger(L, fs::file_size(path));
|
||||
} else {
|
||||
lua_pushinteger(L, -1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_file_mkdir(lua_State* L) {
|
||||
auto paths = scripting::engine->getPaths();
|
||||
fs::path path = paths->resolve(lua_tostring(L, 1));
|
||||
lua_pushboolean(L, fs::create_directory(path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg filelib [] = {
|
||||
{"resolve", l_file_resolve},
|
||||
{"read", l_file_read},
|
||||
{"write", l_file_write},
|
||||
{"exists", l_file_exists},
|
||||
{"isfile", l_file_isfile},
|
||||
{"isdir", l_file_isdir},
|
||||
{"length", l_file_length},
|
||||
{"mkdir", l_file_mkdir},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* == time library == */
|
||||
static int l_time_uptime(lua_State* L) {
|
||||
lua_pushnumber(L, Window::time());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg timelib [] = {
|
||||
{"uptime", l_time_uptime},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* == pack library == */
|
||||
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;
|
||||
}
|
||||
for (auto& pack : scripting::engine->getContentPacks()) {
|
||||
if (pack.id == packName) {
|
||||
lua_pushstring(L, (pack.folder.u8string()+"/").c_str());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
lua_pushstring(L, "");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg packlib [] = {
|
||||
{"get_folder", l_pack_get_folder},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* == world library == */
|
||||
static int l_world_get_total_time(lua_State* L) {
|
||||
lua_pushnumber(L, scripting::level->world->totalTime);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_world_get_day_time(lua_State* L) {
|
||||
lua_pushnumber(L, scripting::level->world->daytime);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_world_set_day_time(lua_State* L) {
|
||||
double value = lua_tonumber(L, 1);
|
||||
scripting::level->world->daytime = fmod(value, 1.0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_world_get_seed(lua_State* L) {
|
||||
lua_pushinteger(L, scripting::level->world->getSeed());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg worldlib [] = {
|
||||
{"get_total_time", l_world_get_total_time},
|
||||
{"get_day_time", l_world_get_day_time},
|
||||
{"set_day_time", l_world_set_day_time},
|
||||
{"get_seed", l_world_get_seed},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* == player library ==*/
|
||||
static int l_player_get_pos(lua_State* L) {
|
||||
int playerid = lua_tointeger(L, 1);
|
||||
if (playerid != 1)
|
||||
return 0;
|
||||
glm::vec3 pos = scripting::level->player->hitbox->position;
|
||||
lua_pushnumber(L, pos.x);
|
||||
lua_pushnumber(L, pos.y);
|
||||
lua_pushnumber(L, pos.z);
|
||||
return 3;
|
||||
}
|
||||
|
||||
static int l_player_get_rot(lua_State* L) {
|
||||
int playerid = lua_tointeger(L, 1);
|
||||
if (playerid != 1)
|
||||
return 0;
|
||||
glm::vec2 rot = scripting::level->player->cam;
|
||||
lua_pushnumber(L, rot.x);
|
||||
lua_pushnumber(L, rot.y);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int l_player_set_rot(lua_State* L) {
|
||||
int playerid = lua_tointeger(L, 1);
|
||||
if (playerid != 1)
|
||||
return 0;
|
||||
double x = lua_tonumber(L, 2);
|
||||
double y = lua_tonumber(L, 3);
|
||||
glm::vec2& cam = scripting::level->player->cam;
|
||||
cam.x = x;
|
||||
cam.y = y;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_player_set_pos(lua_State* L) {
|
||||
int playerid = lua_tointeger(L, 1);
|
||||
if (playerid != 1)
|
||||
return 0;
|
||||
double x = lua_tonumber(L, 2);
|
||||
double y = lua_tonumber(L, 3);
|
||||
double z = lua_tonumber(L, 4);
|
||||
scripting::level->player->hitbox->position = glm::vec3(x, y, z);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_Reg playerlib [] = {
|
||||
{"get_pos", l_player_get_pos},
|
||||
{"set_pos", l_player_set_pos},
|
||||
{"get_rot", l_player_get_rot},
|
||||
{"set_rot", l_player_set_rot},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* == blocks-related functions == */
|
||||
static int l_block_name(lua_State* L) {
|
||||
int id = lua_tointeger(L, 1);
|
||||
auto def = scripting::content->getIndices()->getBlockDef(id);
|
||||
lua_pushstring(L, def->name.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_is_solid_at(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
|
||||
lua_pushboolean(L, scripting::level->chunks->isSolidBlock(x, y, z));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_blocks_count(lua_State* L) {
|
||||
lua_pushinteger(L, scripting::content->getIndices()->countBlockDefs());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_block_index(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
lua_pushinteger(L, scripting::content->requireBlock(name)->rt.id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_set_block(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
int id = lua_tointeger(L, 4);
|
||||
int states = lua_tointeger(L, 5);
|
||||
bool noupdate = lua_toboolean(L, 6);
|
||||
scripting::level->chunks->set(x, y, z, id, states);
|
||||
scripting::level->lighting->onBlockSet(x,y,z, id);
|
||||
if (!noupdate)
|
||||
scripting::blocks->updateSides(x, y, z);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_get_block(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
int id = vox == nullptr ? -1 : vox->id;
|
||||
lua_pushinteger(L, id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_get_block_x(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
voxel* vox = scripting::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);
|
||||
if (!def->rotatable) {
|
||||
return lua_pushivec3(L, 1, 0, 0);
|
||||
} else {
|
||||
const CoordSystem& rot = def->rotations.variants[vox->rotation()];
|
||||
return lua_pushivec3(L, rot.axisX.x, rot.axisX.y, rot.axisX.z);
|
||||
}
|
||||
}
|
||||
|
||||
static int l_get_block_y(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
voxel* vox = scripting::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);
|
||||
if (!def->rotatable) {
|
||||
return lua_pushivec3(L, 0, 1, 0);
|
||||
} else {
|
||||
const CoordSystem& rot = def->rotations.variants[vox->rotation()];
|
||||
return lua_pushivec3(L, rot.axisY.x, rot.axisY.y, rot.axisY.z);
|
||||
}
|
||||
}
|
||||
|
||||
static int l_get_block_z(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
voxel* vox = scripting::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);
|
||||
if (!def->rotatable) {
|
||||
return lua_pushivec3(L, 0, 0, 1);
|
||||
} else {
|
||||
const CoordSystem& rot = def->rotations.variants[vox->rotation()];
|
||||
return lua_pushivec3(L, rot.axisZ.x, rot.axisZ.y, rot.axisZ.z);
|
||||
}
|
||||
}
|
||||
|
||||
static int l_get_block_states(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
int states = vox == nullptr ? 0 : vox->states;
|
||||
lua_pushinteger(L, states);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_get_block_user_bits(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
int offset = lua_tointeger(L, 4) + VOXEL_USER_BITS_OFFSET;
|
||||
int bits = lua_tointeger(L, 5);
|
||||
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
if (vox == nullptr) {
|
||||
lua_pushinteger(L, 0);
|
||||
return 1;
|
||||
}
|
||||
uint mask = ((1 << bits) - 1) << offset;
|
||||
uint data = (vox->states & mask) >> offset;
|
||||
lua_pushinteger(L, data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_set_block_user_bits(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
int offset = lua_tointeger(L, 4) + VOXEL_USER_BITS_OFFSET;
|
||||
int bits = lua_tointeger(L, 5);
|
||||
|
||||
uint mask = ((1 << bits) - 1) << offset;
|
||||
int value = (lua_tointeger(L, 6) << offset) & mask;
|
||||
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
if (vox == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
vox->states = (vox->states & (~mask)) | value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_is_replaceable_at(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
|
||||
lua_pushboolean(L, scripting::level->chunks->isReplaceableBlock(x, y, z));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Modified version of luaB_print from lbaselib.c
|
||||
static 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 */
|
||||
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 */
|
||||
}
|
||||
std::cout << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define lua_addfunc(L, FUNC, NAME) (lua_pushcfunction(L, FUNC),\
|
||||
lua_setglobal(L, NAME))
|
||||
|
||||
void apilua::create_funcs(lua_State* L) {
|
||||
openlib(L, "pack", packlib, 0);
|
||||
openlib(L, "world", worldlib, 0);
|
||||
openlib(L, "player", playerlib, 0);
|
||||
openlib(L, "time", timelib, 0);
|
||||
openlib(L, "file", filelib, 0);
|
||||
|
||||
lua_addfunc(L, l_print, "print");
|
||||
lua_addfunc(L, l_block_index, "block_index");
|
||||
lua_addfunc(L, l_block_name, "block_name");
|
||||
lua_addfunc(L, l_blocks_count, "blocks_count");
|
||||
lua_addfunc(L, l_is_solid_at, "is_solid_at");
|
||||
lua_addfunc(L, l_is_replaceable_at, "is_replaceable_at");
|
||||
lua_addfunc(L, l_set_block, "set_block");
|
||||
lua_addfunc(L, l_get_block, "get_block");
|
||||
lua_addfunc(L, l_get_block_x, "get_block_X");
|
||||
lua_addfunc(L, l_get_block_y, "get_block_Y");
|
||||
lua_addfunc(L, l_get_block_z, "get_block_Z");
|
||||
lua_addfunc(L, l_get_block_states, "get_block_states");
|
||||
lua_addfunc(L, l_get_block_user_bits, "get_block_user_bits");
|
||||
lua_addfunc(L, l_set_block_user_bits, "set_block_user_bits");
|
||||
}
|
||||
@ -1,14 +1,398 @@
|
||||
#ifndef LOGIC_SCRIPTING_API_LUA_H_
|
||||
#define LOGIC_SCRIPTING_API_LUA_H_
|
||||
|
||||
#include <lua.hpp>
|
||||
#include "scripting.h"
|
||||
#include "lua_util.h"
|
||||
|
||||
#ifndef LUAJIT_VERSION
|
||||
#pragma message("better use LuaJIT instead of plain Lua")
|
||||
#endif // LUAJIT_VERSION
|
||||
#include <glm/glm.hpp>
|
||||
#include <iostream>
|
||||
|
||||
namespace apilua {
|
||||
extern void create_funcs(lua_State* L);
|
||||
#include "../../files/files.h"
|
||||
#include "../../physics/Hitbox.h"
|
||||
#include "../../objects/Player.h"
|
||||
#include "../../world/Level.h"
|
||||
#include "../../world/World.h"
|
||||
#include "../../content/Content.h"
|
||||
#include "../../voxels/Block.h"
|
||||
#include "../../voxels/Chunks.h"
|
||||
#include "../../voxels/voxel.h"
|
||||
#include "../../lighting/Lighting.h"
|
||||
#include "../../logic/BlocksController.h"
|
||||
#include "../../window/Window.h"
|
||||
#include "../../engine.h"
|
||||
|
||||
/* == file library == */
|
||||
static int l_file_resolve(lua_State* L) {
|
||||
std::string path = lua_tostring(L, 1);
|
||||
fs::path resolved = scripting::engine->getPaths()->resolve(path);
|
||||
lua_pushstring(L, resolved.u8string().c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_file_read(lua_State* L) {
|
||||
auto paths = scripting::engine->getPaths();
|
||||
fs::path path = paths->resolve(lua_tostring(L, 1));
|
||||
if (fs::is_regular_file(path)) {
|
||||
lua_pushstring(L, files::read_string(path).c_str());
|
||||
return 1;
|
||||
}
|
||||
return luaL_error(L, "file does not exists '%s'", path.u8string().c_str());
|
||||
}
|
||||
|
||||
static int l_file_write(lua_State* L) {
|
||||
auto paths = scripting::engine->getPaths();
|
||||
fs::path path = paths->resolve(lua_tostring(L, 1));
|
||||
const char* text = lua_tostring(L, 2);
|
||||
files::write_string(path, text);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_file_exists(lua_State* L) {
|
||||
auto paths = scripting::engine->getPaths();
|
||||
fs::path path = paths->resolve(lua_tostring(L, 1));
|
||||
lua_pushboolean(L, fs::exists(path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_file_isfile(lua_State* L) {
|
||||
auto paths = scripting::engine->getPaths();
|
||||
fs::path path = paths->resolve(lua_tostring(L, 1));
|
||||
lua_pushboolean(L, fs::is_regular_file(path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_file_isdir(lua_State* L) {
|
||||
auto paths = scripting::engine->getPaths();
|
||||
fs::path path = paths->resolve(lua_tostring(L, 1));
|
||||
lua_pushboolean(L, fs::is_directory(path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_file_length(lua_State* L) {
|
||||
auto paths = scripting::engine->getPaths();
|
||||
fs::path path = paths->resolve(lua_tostring(L, 1));
|
||||
if (fs::exists(path)){
|
||||
lua_pushinteger(L, fs::file_size(path));
|
||||
} else {
|
||||
lua_pushinteger(L, -1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_file_mkdir(lua_State* L) {
|
||||
auto paths = scripting::engine->getPaths();
|
||||
fs::path path = paths->resolve(lua_tostring(L, 1));
|
||||
lua_pushboolean(L, fs::create_directory(path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg filelib [] = {
|
||||
{"resolve", l_file_resolve},
|
||||
{"read", l_file_read},
|
||||
{"write", l_file_write},
|
||||
{"exists", l_file_exists},
|
||||
{"isfile", l_file_isfile},
|
||||
{"isdir", l_file_isdir},
|
||||
{"length", l_file_length},
|
||||
{"mkdir", l_file_mkdir},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* == time library == */
|
||||
static int l_time_uptime(lua_State* L) {
|
||||
lua_pushnumber(L, Window::time());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg timelib [] = {
|
||||
{"uptime", l_time_uptime},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* == pack library == */
|
||||
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;
|
||||
}
|
||||
for (auto& pack : scripting::engine->getContentPacks()) {
|
||||
if (pack.id == packName) {
|
||||
lua_pushstring(L, (pack.folder.u8string()+"/").c_str());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
lua_pushstring(L, "");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg packlib [] = {
|
||||
{"get_folder", l_pack_get_folder},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* == world library == */
|
||||
static int l_world_get_total_time(lua_State* L) {
|
||||
lua_pushnumber(L, scripting::level->world->totalTime);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_world_get_day_time(lua_State* L) {
|
||||
lua_pushnumber(L, scripting::level->world->daytime);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_world_set_day_time(lua_State* L) {
|
||||
double value = lua_tonumber(L, 1);
|
||||
scripting::level->world->daytime = fmod(value, 1.0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_world_get_seed(lua_State* L) {
|
||||
lua_pushinteger(L, scripting::level->world->getSeed());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg worldlib [] = {
|
||||
{"get_total_time", l_world_get_total_time},
|
||||
{"get_day_time", l_world_get_day_time},
|
||||
{"set_day_time", l_world_set_day_time},
|
||||
{"get_seed", l_world_get_seed},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* == player library ==*/
|
||||
static int l_player_get_pos(lua_State* L) {
|
||||
int playerid = lua_tointeger(L, 1);
|
||||
if (playerid != 1)
|
||||
return 0;
|
||||
glm::vec3 pos = scripting::level->player->hitbox->position;
|
||||
lua_pushnumber(L, pos.x);
|
||||
lua_pushnumber(L, pos.y);
|
||||
lua_pushnumber(L, pos.z);
|
||||
return 3;
|
||||
}
|
||||
|
||||
static int l_player_get_rot(lua_State* L) {
|
||||
int playerid = lua_tointeger(L, 1);
|
||||
if (playerid != 1)
|
||||
return 0;
|
||||
glm::vec2 rot = scripting::level->player->cam;
|
||||
lua_pushnumber(L, rot.x);
|
||||
lua_pushnumber(L, rot.y);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int l_player_set_rot(lua_State* L) {
|
||||
int playerid = lua_tointeger(L, 1);
|
||||
if (playerid != 1)
|
||||
return 0;
|
||||
double x = lua_tonumber(L, 2);
|
||||
double y = lua_tonumber(L, 3);
|
||||
glm::vec2& cam = scripting::level->player->cam;
|
||||
cam.x = x;
|
||||
cam.y = y;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_player_set_pos(lua_State* L) {
|
||||
int playerid = lua_tointeger(L, 1);
|
||||
if (playerid != 1)
|
||||
return 0;
|
||||
double x = lua_tonumber(L, 2);
|
||||
double y = lua_tonumber(L, 3);
|
||||
double z = lua_tonumber(L, 4);
|
||||
scripting::level->player->hitbox->position = glm::vec3(x, y, z);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_Reg playerlib [] = {
|
||||
{"get_pos", l_player_get_pos},
|
||||
{"set_pos", l_player_set_pos},
|
||||
{"get_rot", l_player_get_rot},
|
||||
{"set_rot", l_player_set_rot},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* == blocks-related functions == */
|
||||
static int l_block_name(lua_State* L) {
|
||||
int id = lua_tointeger(L, 1);
|
||||
auto def = scripting::content->getIndices()->getBlockDef(id);
|
||||
lua_pushstring(L, def->name.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_is_solid_at(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
|
||||
lua_pushboolean(L, scripting::level->chunks->isSolidBlock(x, y, z));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_blocks_count(lua_State* L) {
|
||||
lua_pushinteger(L, scripting::content->getIndices()->countBlockDefs());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_block_index(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
lua_pushinteger(L, scripting::content->requireBlock(name)->rt.id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_set_block(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
int id = lua_tointeger(L, 4);
|
||||
int states = lua_tointeger(L, 5);
|
||||
bool noupdate = lua_toboolean(L, 6);
|
||||
scripting::level->chunks->set(x, y, z, id, states);
|
||||
scripting::level->lighting->onBlockSet(x,y,z, id);
|
||||
if (!noupdate)
|
||||
scripting::blocks->updateSides(x, y, z);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_get_block(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
int id = vox == nullptr ? -1 : vox->id;
|
||||
lua_pushinteger(L, id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_get_block_x(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
voxel* vox = scripting::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);
|
||||
if (!def->rotatable) {
|
||||
return lua::pushivec3(L, 1, 0, 0);
|
||||
} else {
|
||||
const CoordSystem& rot = def->rotations.variants[vox->rotation()];
|
||||
return lua::pushivec3(L, rot.axisX.x, rot.axisX.y, rot.axisX.z);
|
||||
}
|
||||
}
|
||||
|
||||
static int l_get_block_y(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
voxel* vox = scripting::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);
|
||||
if (!def->rotatable) {
|
||||
return lua::pushivec3(L, 0, 1, 0);
|
||||
} else {
|
||||
const CoordSystem& rot = def->rotations.variants[vox->rotation()];
|
||||
return lua::pushivec3(L, rot.axisY.x, rot.axisY.y, rot.axisY.z);
|
||||
}
|
||||
}
|
||||
|
||||
static int l_get_block_z(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
voxel* vox = scripting::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);
|
||||
if (!def->rotatable) {
|
||||
return lua::pushivec3(L, 0, 0, 1);
|
||||
} else {
|
||||
const CoordSystem& rot = def->rotations.variants[vox->rotation()];
|
||||
return lua::pushivec3(L, rot.axisZ.x, rot.axisZ.y, rot.axisZ.z);
|
||||
}
|
||||
}
|
||||
|
||||
static int l_get_block_states(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
int states = vox == nullptr ? 0 : vox->states;
|
||||
lua_pushinteger(L, states);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_get_block_user_bits(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
int offset = lua_tointeger(L, 4) + VOXEL_USER_BITS_OFFSET;
|
||||
int bits = lua_tointeger(L, 5);
|
||||
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
if (vox == nullptr) {
|
||||
lua_pushinteger(L, 0);
|
||||
return 1;
|
||||
}
|
||||
uint mask = ((1 << bits) - 1) << offset;
|
||||
uint data = (vox->states & mask) >> offset;
|
||||
lua_pushinteger(L, data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_set_block_user_bits(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
int offset = lua_tointeger(L, 4) + VOXEL_USER_BITS_OFFSET;
|
||||
int bits = lua_tointeger(L, 5);
|
||||
|
||||
uint mask = ((1 << bits) - 1) << offset;
|
||||
int value = (lua_tointeger(L, 6) << offset) & mask;
|
||||
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
if (vox == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
vox->states = (vox->states & (~mask)) | value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_is_replaceable_at(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
|
||||
lua_pushboolean(L, scripting::level->chunks->isReplaceableBlock(x, y, z));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Modified version of luaB_print from lbaselib.c
|
||||
static 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 */
|
||||
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 */
|
||||
}
|
||||
std::cout << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // LOGIC_SCRIPTING_API_LUA_H_
|
||||
|
||||
15
src/logic/scripting/lua_util.h
Normal file
15
src/logic/scripting/lua_util.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef LOGIC_SCRIPTING_LUA_UTIL_H_
|
||||
#define LOGIC_SCRIPTING_LUA_UTIL_H_
|
||||
|
||||
#include <lua.hpp>
|
||||
|
||||
namespace lua {
|
||||
inline int pushivec3(lua_State* L, luaint x, luaint y, luaint z) {
|
||||
lua_pushinteger(L, x);
|
||||
lua_pushinteger(L, y);
|
||||
lua_pushinteger(L, z);
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // LOGIC_SCRIPTING_LUA_UTIL_H_
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <lua.hpp>
|
||||
|
||||
#include "../../content/ContentPack.h"
|
||||
#include "../../files/engine_paths.h"
|
||||
@ -13,105 +12,68 @@
|
||||
#include "../../items/ItemDef.h"
|
||||
#include "../../logic/BlocksController.h"
|
||||
#include "../../engine.h"
|
||||
#include "api_lua.h"
|
||||
#include "LuaState.h"
|
||||
#include "../../util/stringutil.h"
|
||||
|
||||
using namespace scripting;
|
||||
|
||||
namespace scripting {
|
||||
extern lua_State* L;
|
||||
extern lua::LuaState* state;
|
||||
}
|
||||
|
||||
Engine* scripting::engine = nullptr;
|
||||
lua_State* scripting::L = nullptr;
|
||||
lua::LuaState* scripting::state = nullptr;
|
||||
Level* scripting::level = nullptr;
|
||||
const Content* scripting::content = nullptr;
|
||||
BlocksController* scripting::blocks = nullptr;
|
||||
|
||||
static void handleError(lua_State* L) {
|
||||
std::cerr << "lua error: " << lua_tostring(L,-1) << std::endl;
|
||||
}
|
||||
|
||||
inline int lua_pushivec3(lua_State* L, int x, int y, int z) {
|
||||
lua_pushinteger(L, x);
|
||||
lua_pushinteger(L, y);
|
||||
lua_pushinteger(L, z);
|
||||
return 3;
|
||||
}
|
||||
|
||||
void delete_global(lua_State* L, const char* name) {
|
||||
lua_pushnil(L);
|
||||
lua_setglobal(L, name);
|
||||
}
|
||||
|
||||
bool rename_global(lua_State* L, const char* src, const char* dst) {
|
||||
lua_getglobal(L, src);
|
||||
if (lua_isnil(L, lua_gettop(L))) {
|
||||
lua_pop(L, lua_gettop(L));
|
||||
return false;
|
||||
}
|
||||
lua_setglobal(L, dst);
|
||||
delete_global(L, src);
|
||||
return true;
|
||||
}
|
||||
|
||||
int call_func(lua_State* L, int argc, const std::string& name) {
|
||||
if (lua_pcall(L, argc, LUA_MULTRET, 0)) {
|
||||
handleError(L);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void load_script(fs::path name) {
|
||||
auto paths = scripting::engine->getPaths();
|
||||
fs::path file = paths->getResources()/fs::path("scripts")/name;
|
||||
|
||||
std::string src = files::read_string(file);
|
||||
if (luaL_loadbuffer(L, src.c_str(), src.length(), file.u8string().c_str())) {
|
||||
handleError(L);
|
||||
return;
|
||||
}
|
||||
call_func(L, 0, file.u8string());
|
||||
|
||||
state->loadbuffer(src, file.u8string());
|
||||
state->callNoThrow(0);
|
||||
}
|
||||
|
||||
void scripting::initialize(Engine* engine) {
|
||||
scripting::engine = engine;
|
||||
|
||||
L = luaL_newstate();
|
||||
if (L == nullptr) {
|
||||
throw std::runtime_error("could not to initialize Lua");
|
||||
}
|
||||
|
||||
// Allowed standard libraries
|
||||
luaopen_base(L);
|
||||
luaopen_math(L);
|
||||
luaopen_string(L);
|
||||
luaopen_table(L);
|
||||
|
||||
// io-manipulations will be implemented via api functions
|
||||
|
||||
std::cout << LUA_VERSION << std::endl;
|
||||
# ifdef LUAJIT_VERSION
|
||||
luaopen_jit(L);
|
||||
std::cout << LUAJIT_VERSION << std::endl;
|
||||
# endif // LUAJIT_VERSION
|
||||
|
||||
apilua::create_funcs(L);
|
||||
state = new lua::LuaState();
|
||||
|
||||
load_script(fs::path("stdlib.lua"));
|
||||
}
|
||||
|
||||
// todo: luaL state check
|
||||
runnable scripting::create_runnable(
|
||||
const std::string& filename,
|
||||
const std::string& file,
|
||||
const std::string& src
|
||||
) {
|
||||
return [=](){
|
||||
if (luaL_loadbuffer(L, src.c_str(), src.length(), filename.c_str())) {
|
||||
handleError(L);
|
||||
return;
|
||||
state->loadbuffer(src, file);
|
||||
state->callNoThrow(0);
|
||||
};
|
||||
}
|
||||
|
||||
wstringconsumer scripting::create_wstring_consumer(
|
||||
const std::string& src,
|
||||
const std::string& file
|
||||
) {
|
||||
try {
|
||||
if (state->eval(src, file) == 0)
|
||||
return [](const std::wstring& _) {};
|
||||
} catch (const lua::luaerror& err) {
|
||||
std::cerr << err.what() << std::endl;
|
||||
return [](const std::wstring& _) {};
|
||||
}
|
||||
|
||||
auto funcName = state->storeAnonymous();
|
||||
return [=](const std::wstring& x){
|
||||
if (state->getglobal(funcName)) {
|
||||
state->pushstring(util::wstr2str_utf8(x));
|
||||
state->callNoThrow(1);
|
||||
}
|
||||
call_func(L, 0, filename);
|
||||
};
|
||||
}
|
||||
|
||||
@ -122,37 +84,25 @@ void scripting::on_world_load(Level* level, BlocksController* blocks) {
|
||||
load_script("world.lua");
|
||||
|
||||
for (auto& pack : scripting::engine->getContentPacks()) {
|
||||
std::string name = pack.id+".worldopen";
|
||||
lua_getglobal(L, name.c_str());
|
||||
if (lua_isnil(L, lua_gettop(L))) {
|
||||
lua_pop(L, lua_gettop(L));
|
||||
continue;
|
||||
if (state->getglobal(pack.id+".worldopen")) {
|
||||
state->callNoThrow(0);
|
||||
}
|
||||
call_func(L, 0, name);
|
||||
}
|
||||
}
|
||||
|
||||
void scripting::on_world_save() {
|
||||
for (auto& pack : scripting::engine->getContentPacks()) {
|
||||
std::string name = pack.id+".worldsave";
|
||||
lua_getglobal(L, name.c_str());
|
||||
if (lua_isnil(L, lua_gettop(L))) {
|
||||
lua_pop(L, lua_gettop(L));
|
||||
continue;
|
||||
if (state->getglobal(pack.id+".worldsave")) {
|
||||
state->callNoThrow(0);
|
||||
}
|
||||
call_func(L, 0, name);
|
||||
}
|
||||
}
|
||||
|
||||
void scripting::on_world_quit() {
|
||||
for (auto& pack : scripting::engine->getContentPacks()) {
|
||||
std::string name = pack.id+".worldquit";
|
||||
lua_getglobal(L, name.c_str());
|
||||
if (lua_isnil(L, lua_gettop(L))) {
|
||||
lua_pop(L, lua_gettop(L));
|
||||
continue;
|
||||
if (state->getglobal(pack.id+".worldquit")) {
|
||||
state->callNoThrow(0);
|
||||
}
|
||||
call_func(L, 0, name);
|
||||
}
|
||||
scripting::level = nullptr;
|
||||
scripting::content = nullptr;
|
||||
@ -160,124 +110,125 @@ void scripting::on_world_quit() {
|
||||
|
||||
void scripting::on_blocks_tick(const Block* block, int tps) {
|
||||
std::string name = block->name+".blockstick";
|
||||
lua_getglobal(L, name.c_str());
|
||||
lua_pushinteger(L, tps);
|
||||
call_func(L, 1, name);
|
||||
if (state->getglobal(name)) {
|
||||
state->pushinteger(tps);
|
||||
state->callNoThrow(1);
|
||||
}
|
||||
}
|
||||
|
||||
void scripting::update_block(const Block* block, int x, int y, int z) {
|
||||
std::string name = block->name+".update";
|
||||
lua_getglobal(L, name.c_str());
|
||||
lua_pushivec3(L, x, y, z);
|
||||
call_func(L, 3, name);
|
||||
if (state->getglobal(name)) {
|
||||
state->pushivec3(x, y, z);
|
||||
state->callNoThrow(3);
|
||||
}
|
||||
}
|
||||
|
||||
void scripting::random_update_block(const Block* block, int x, int y, int z) {
|
||||
std::string name = block->name+".randupdate";
|
||||
lua_getglobal(L, name.c_str());
|
||||
lua_pushivec3(L, x, y, z);
|
||||
call_func(L, 3, name);
|
||||
if (state->getglobal(name)) {
|
||||
state->pushivec3(x, y, z);
|
||||
state->callNoThrow(3);
|
||||
}
|
||||
}
|
||||
|
||||
void scripting::on_block_placed(Player* player, const Block* block, int x, int y, int z) {
|
||||
std::string name = block->name+".placed";
|
||||
lua_getglobal(L, name.c_str());
|
||||
lua_pushivec3(L, x, y, z);
|
||||
lua_pushinteger(L, 1); // player id placeholder
|
||||
call_func(L, 4, name);
|
||||
if (state->getglobal(name)) {
|
||||
state->pushivec3(x, y, z);
|
||||
state->pushinteger(1); // playerid placeholder
|
||||
state->callNoThrow(4);
|
||||
}
|
||||
}
|
||||
|
||||
void scripting::on_block_broken(Player* player, const Block* block, int x, int y, int z) {
|
||||
std::string name = block->name+".broken";
|
||||
lua_getglobal(L, name.c_str());
|
||||
lua_pushivec3(L, x, y, z);
|
||||
lua_pushinteger(L, 1); // player id placeholder
|
||||
call_func(L, 4, name);
|
||||
if (state->getglobal(name)) {
|
||||
state->pushivec3(x, y, z);
|
||||
state->pushinteger(1); // playerid placeholder
|
||||
state->callNoThrow(4);
|
||||
}
|
||||
}
|
||||
|
||||
bool scripting::on_block_interact(Player* player, const Block* block, int x, int y, int z) {
|
||||
std::string name = block->name+".oninteract";
|
||||
lua_getglobal(L, name.c_str());
|
||||
lua_pushivec3(L, x, y, z);
|
||||
lua_pushinteger(L, 1);
|
||||
if (call_func(L, 4, name)) {
|
||||
return lua_toboolean(L, -1);
|
||||
if (state->getglobal(name)) {
|
||||
state->pushivec3(x, y, z);
|
||||
state->pushinteger(1); // playerid placeholder
|
||||
if (state->callNoThrow(4)) {
|
||||
return state->toboolean(-1);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool scripting::on_item_use_on_block(Player* player, const ItemDef* item, int x, int y, int z) {
|
||||
std::string name = item->name+".useon";
|
||||
lua_getglobal(L, name.c_str());
|
||||
lua_pushivec3(L, x, y, z);
|
||||
lua_pushinteger(L, 1); // player id placeholder
|
||||
if (call_func(L, 4, name)) {
|
||||
return lua_toboolean(L, -1);
|
||||
if (state->getglobal(name)) {
|
||||
state->pushivec3(x, y, z);
|
||||
state->pushinteger(1); // playerid placeholder
|
||||
if (state->callNoThrow(4)) {
|
||||
return state->toboolean(-1);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool scripting::on_item_break_block(Player* player, const ItemDef* item, int x, int y, int z) {
|
||||
std::string name = item->name+".blockbreakby";
|
||||
lua_getglobal(L, name.c_str());
|
||||
lua_pushivec3(L, x, y, z);
|
||||
lua_pushinteger(L, 1); // player id placeholder
|
||||
if (call_func(L, 4, name)) {
|
||||
return lua_toboolean(L, -1);
|
||||
if (state->getglobal(name)) {
|
||||
state->pushivec3(x, y, z);
|
||||
state->pushinteger(1); // playerid placeholder
|
||||
if (state->callNoThrow(4)) {
|
||||
return state->toboolean(-1);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// todo: refactor
|
||||
|
||||
void scripting::load_block_script(std::string prefix, fs::path file, block_funcs_set* funcsset) {
|
||||
std::string src = files::read_string(file);
|
||||
std::cout << "loading script " << file.u8string() << std::endl;
|
||||
if (luaL_loadbuffer(L, src.c_str(), src.size(), file.string().c_str())) {
|
||||
handleError(L);
|
||||
return;
|
||||
}
|
||||
call_func(L, 0, "<script>");
|
||||
funcsset->init=rename_global(L, "init", (prefix+".init").c_str());
|
||||
funcsset->update=rename_global(L, "on_update", (prefix+".update").c_str());
|
||||
funcsset->randupdate=rename_global(L, "on_random_update", (prefix+".randupdate").c_str());
|
||||
funcsset->onbroken=rename_global(L, "on_broken", (prefix+".broken").c_str());
|
||||
funcsset->onplaced=rename_global(L, "on_placed", (prefix+".placed").c_str());
|
||||
funcsset->oninteract=rename_global(L, "on_interact", (prefix+".oninteract").c_str());
|
||||
funcsset->onblockstick=rename_global(L, "on_blocks_tick", (prefix+".blockstick").c_str());
|
||||
|
||||
state->loadbuffer(src, file.u8string());
|
||||
state->callNoThrow(0);
|
||||
|
||||
funcsset->init=state->rename("init", prefix+".init");
|
||||
funcsset->update=state->rename("on_update", prefix+".update");
|
||||
funcsset->randupdate=state->rename("on_random_update", prefix+".randupdate");
|
||||
funcsset->onbroken=state->rename("on_broken", prefix+".broken");
|
||||
funcsset->onplaced=state->rename("on_placed", prefix+".placed");
|
||||
funcsset->oninteract=state->rename("on_interact", prefix+".oninteract");
|
||||
funcsset->onblockstick=state->rename("on_blocks_tick", prefix+".blockstick");
|
||||
}
|
||||
|
||||
void scripting::load_item_script(std::string prefix, fs::path file, item_funcs_set* funcsset) {
|
||||
std::string src = files::read_string(file);
|
||||
std::cout << "loading script " << file.u8string() << std::endl;
|
||||
if (luaL_loadbuffer(L, src.c_str(), src.size(), file.string().c_str())) {
|
||||
handleError(L);
|
||||
return;
|
||||
}
|
||||
call_func(L, 0, "<script>");
|
||||
funcsset->init=rename_global(L, "init", (prefix+".init").c_str());
|
||||
funcsset->on_use_on_block=rename_global(L, "on_use_on_block", (prefix+".useon").c_str());
|
||||
funcsset->on_block_break_by=rename_global(L, "on_block_break_by", (prefix+".blockbreakby").c_str());
|
||||
state->loadbuffer(src, file.u8string());
|
||||
state->callNoThrow(0);
|
||||
funcsset->init=state->rename("init", prefix+".init");
|
||||
funcsset->on_use_on_block=state->rename("on_use_on_block", prefix+".useon");
|
||||
funcsset->on_block_break_by=state->rename("on_block_break_by", prefix+".blockbreakby");
|
||||
}
|
||||
|
||||
void scripting::load_world_script(std::string prefix, fs::path file) {
|
||||
std::string src = files::read_string(file);
|
||||
std::cout << "loading script " << file.u8string() << std::endl;
|
||||
if (luaL_loadbuffer(L, src.c_str(), src.size(), file.string().c_str())) {
|
||||
handleError(L);
|
||||
return;
|
||||
}
|
||||
call_func(L, 0, "<script>");
|
||||
rename_global(L, "init", (prefix+".init").c_str());
|
||||
rename_global(L, "on_world_open", (prefix+".worldopen").c_str());
|
||||
rename_global(L, "on_world_save", (prefix+".worldsave").c_str());
|
||||
rename_global(L, "on_world_quit", (prefix+".worldquit").c_str());
|
||||
|
||||
state->loadbuffer(src, file.u8string());
|
||||
state->callNoThrow(0);
|
||||
|
||||
state->rename("init", prefix+".init");
|
||||
state->rename("on_world_open", prefix+".worldopen");
|
||||
state->rename("on_world_save", prefix+".worldsave");
|
||||
state->rename("on_world_quit", prefix+".worldquit");
|
||||
}
|
||||
|
||||
void scripting::close() {
|
||||
lua_close(L);
|
||||
delete state;
|
||||
|
||||
L = nullptr;
|
||||
state = nullptr;
|
||||
content = nullptr;
|
||||
level = nullptr;
|
||||
}
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
class LuaState;
|
||||
|
||||
class Engine;
|
||||
class Content;
|
||||
class Level;
|
||||
@ -27,6 +29,11 @@ namespace scripting {
|
||||
const std::string& filename,
|
||||
const std::string& source
|
||||
);
|
||||
|
||||
wstringconsumer create_wstring_consumer(
|
||||
const std::string& src,
|
||||
const std::string& file="<string>"
|
||||
);
|
||||
|
||||
void on_world_load(Level* level, BlocksController* blocks);
|
||||
void on_world_save();
|
||||
|
||||
@ -279,3 +279,7 @@ double util::parse_double(const std::string& str) {
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
double util::parse_double(const std::string& str, size_t offset, size_t len) {
|
||||
return parse_double(str.substr(offset, len));
|
||||
}
|
||||
|
||||
@ -30,6 +30,7 @@ namespace util {
|
||||
extern int replaceAll(std::string& str, const std::string& from, const std::string& to);
|
||||
|
||||
extern double parse_double(const std::string& str);
|
||||
extern double parse_double(const std::string& str, size_t offset, size_t len);
|
||||
}
|
||||
|
||||
#endif // UTIL_STRINGUTIL_H_
|
||||
Loading…
x
Reference in New Issue
Block a user