2013-02-23 19:06:57 +01:00
|
|
|
/*
|
|
|
|
Minetest
|
|
|
|
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2.1 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public License along
|
|
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
extern "C" {
|
2013-05-25 00:51:02 +02:00
|
|
|
#include "lua.h"
|
|
|
|
#include "lauxlib.h"
|
2013-02-23 19:06:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#include "util/numeric.h"
|
2016-10-23 19:45:25 +02:00
|
|
|
#include "util/serialize.h"
|
2015-05-16 18:26:57 +02:00
|
|
|
#include "util/string.h"
|
2013-05-25 00:51:02 +02:00
|
|
|
#include "common/c_converter.h"
|
|
|
|
#include "constants.h"
|
2013-02-23 19:06:57 +01:00
|
|
|
|
2015-05-06 21:33:36 +02:00
|
|
|
|
|
|
|
#define CHECK_TYPE(index, name, type) do { \
|
2015-05-16 18:26:57 +02:00
|
|
|
int t = lua_type(L, (index)); \
|
|
|
|
if (t != (type)) { \
|
|
|
|
throw LuaError(std::string("Invalid ") + (name) + \
|
|
|
|
" (expected " + lua_typename(L, (type)) + \
|
|
|
|
" got " + lua_typename(L, t) + ")."); \
|
|
|
|
} \
|
|
|
|
} while(0)
|
2015-05-06 21:33:36 +02:00
|
|
|
#define CHECK_POS_COORD(name) CHECK_TYPE(-1, "position coordinate '" name "'", LUA_TNUMBER)
|
2016-10-23 19:45:25 +02:00
|
|
|
#define CHECK_FLOAT_RANGE(value, name) \
|
|
|
|
if (value < F1000_MIN || value > F1000_MAX) { \
|
|
|
|
std::ostringstream error_text; \
|
|
|
|
error_text << "Invalid float vector dimension range '" name "' " << \
|
|
|
|
"(expected " << F1000_MIN << " < " name " < " << F1000_MAX << \
|
|
|
|
" got " << value << ")." << std::endl; \
|
|
|
|
throw LuaError(error_text.str()); \
|
|
|
|
}
|
2015-05-06 21:33:36 +02:00
|
|
|
#define CHECK_POS_TAB(index) CHECK_TYPE(index, "position", LUA_TTABLE)
|
|
|
|
|
|
|
|
|
2013-02-23 19:06:57 +01:00
|
|
|
void push_v3f(lua_State *L, v3f p)
|
|
|
|
{
|
|
|
|
lua_newtable(L);
|
|
|
|
lua_pushnumber(L, p.X);
|
|
|
|
lua_setfield(L, -2, "x");
|
|
|
|
lua_pushnumber(L, p.Y);
|
|
|
|
lua_setfield(L, -2, "y");
|
|
|
|
lua_pushnumber(L, p.Z);
|
|
|
|
lua_setfield(L, -2, "z");
|
|
|
|
}
|
|
|
|
|
2013-04-11 20:23:38 +02:00
|
|
|
void push_v2f(lua_State *L, v2f p)
|
|
|
|
{
|
|
|
|
lua_newtable(L);
|
|
|
|
lua_pushnumber(L, p.X);
|
|
|
|
lua_setfield(L, -2, "x");
|
|
|
|
lua_pushnumber(L, p.Y);
|
|
|
|
lua_setfield(L, -2, "y");
|
|
|
|
}
|
|
|
|
|
2013-02-23 19:06:57 +01:00
|
|
|
v2s16 read_v2s16(lua_State *L, int index)
|
|
|
|
{
|
|
|
|
v2s16 p;
|
2015-05-06 21:33:36 +02:00
|
|
|
CHECK_POS_TAB(index);
|
2013-02-23 19:06:57 +01:00
|
|
|
lua_getfield(L, index, "x");
|
|
|
|
p.X = lua_tonumber(L, -1);
|
2014-04-12 13:50:22 +02:00
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_getfield(L, index, "y");
|
|
|
|
p.Y = lua_tonumber(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2015-04-20 03:42:40 +02:00
|
|
|
v2s16 check_v2s16(lua_State *L, int index)
|
|
|
|
{
|
|
|
|
v2s16 p;
|
2015-05-06 21:33:36 +02:00
|
|
|
CHECK_POS_TAB(index);
|
2015-04-20 03:42:40 +02:00
|
|
|
lua_getfield(L, index, "x");
|
2015-05-06 21:33:36 +02:00
|
|
|
CHECK_POS_COORD("x");
|
|
|
|
p.X = lua_tonumber(L, -1);
|
2015-04-20 03:42:40 +02:00
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_getfield(L, index, "y");
|
2015-05-06 21:33:36 +02:00
|
|
|
CHECK_POS_COORD("y");
|
|
|
|
p.Y = lua_tonumber(L, -1);
|
2015-04-20 03:42:40 +02:00
|
|
|
lua_pop(L, 1);
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2015-05-26 14:10:08 +02:00
|
|
|
void push_v2s16(lua_State *L, v2s16 p)
|
|
|
|
{
|
|
|
|
lua_newtable(L);
|
|
|
|
lua_pushnumber(L, p.X);
|
|
|
|
lua_setfield(L, -2, "x");
|
|
|
|
lua_pushnumber(L, p.Y);
|
|
|
|
lua_setfield(L, -2, "y");
|
|
|
|
}
|
|
|
|
|
|
|
|
void push_v2s32(lua_State *L, v2s32 p)
|
|
|
|
{
|
|
|
|
lua_newtable(L);
|
|
|
|
lua_pushnumber(L, p.X);
|
|
|
|
lua_setfield(L, -2, "x");
|
|
|
|
lua_pushnumber(L, p.Y);
|
|
|
|
lua_setfield(L, -2, "y");
|
|
|
|
}
|
|
|
|
|
2014-04-12 13:50:22 +02:00
|
|
|
v2s32 read_v2s32(lua_State *L, int index)
|
|
|
|
{
|
|
|
|
v2s32 p;
|
2015-05-06 21:33:36 +02:00
|
|
|
CHECK_POS_TAB(index);
|
2014-04-12 13:50:22 +02:00
|
|
|
lua_getfield(L, index, "x");
|
|
|
|
p.X = lua_tonumber(L, -1);
|
2013-02-23 19:06:57 +01:00
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_getfield(L, index, "y");
|
|
|
|
p.Y = lua_tonumber(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
v2f read_v2f(lua_State *L, int index)
|
|
|
|
{
|
|
|
|
v2f p;
|
2015-05-06 21:33:36 +02:00
|
|
|
CHECK_POS_TAB(index);
|
|
|
|
lua_getfield(L, index, "x");
|
2013-02-23 19:06:57 +01:00
|
|
|
p.X = lua_tonumber(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_getfield(L, index, "y");
|
|
|
|
p.Y = lua_tonumber(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2015-04-20 03:42:40 +02:00
|
|
|
v2f check_v2f(lua_State *L, int index)
|
|
|
|
{
|
|
|
|
v2f p;
|
2015-05-06 21:33:36 +02:00
|
|
|
CHECK_POS_TAB(index);
|
2015-04-20 03:42:40 +02:00
|
|
|
lua_getfield(L, index, "x");
|
2015-05-06 21:33:36 +02:00
|
|
|
CHECK_POS_COORD("x");
|
|
|
|
p.X = lua_tonumber(L, -1);
|
2015-04-20 03:42:40 +02:00
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_getfield(L, index, "y");
|
2015-05-06 21:33:36 +02:00
|
|
|
CHECK_POS_COORD("y");
|
|
|
|
p.Y = lua_tonumber(L, -1);
|
2015-04-20 03:42:40 +02:00
|
|
|
lua_pop(L, 1);
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2013-02-23 19:06:57 +01:00
|
|
|
v3f read_v3f(lua_State *L, int index)
|
|
|
|
{
|
|
|
|
v3f pos;
|
2015-05-06 21:33:36 +02:00
|
|
|
CHECK_POS_TAB(index);
|
2013-02-23 19:06:57 +01:00
|
|
|
lua_getfield(L, index, "x");
|
|
|
|
pos.X = lua_tonumber(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_getfield(L, index, "y");
|
|
|
|
pos.Y = lua_tonumber(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_getfield(L, index, "z");
|
|
|
|
pos.Z = lua_tonumber(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
v3f check_v3f(lua_State *L, int index)
|
|
|
|
{
|
|
|
|
v3f pos;
|
2015-05-06 21:33:36 +02:00
|
|
|
CHECK_POS_TAB(index);
|
2013-02-23 19:06:57 +01:00
|
|
|
lua_getfield(L, index, "x");
|
2015-05-06 21:33:36 +02:00
|
|
|
CHECK_POS_COORD("x");
|
|
|
|
pos.X = lua_tonumber(L, -1);
|
2016-10-23 19:45:25 +02:00
|
|
|
CHECK_FLOAT_RANGE(pos.X, "x")
|
2013-02-23 19:06:57 +01:00
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_getfield(L, index, "y");
|
2015-05-06 21:33:36 +02:00
|
|
|
CHECK_POS_COORD("y");
|
2015-05-08 06:03:41 +02:00
|
|
|
pos.Y = lua_tonumber(L, -1);
|
2016-10-23 19:45:25 +02:00
|
|
|
CHECK_FLOAT_RANGE(pos.Y, "y")
|
2013-02-23 19:06:57 +01:00
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_getfield(L, index, "z");
|
2015-05-06 21:33:36 +02:00
|
|
|
CHECK_POS_COORD("z");
|
|
|
|
pos.Z = lua_tonumber(L, -1);
|
2016-10-23 19:45:25 +02:00
|
|
|
CHECK_FLOAT_RANGE(pos.Z, "z")
|
2013-02-23 19:06:57 +01:00
|
|
|
lua_pop(L, 1);
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
2015-05-16 18:26:57 +02:00
|
|
|
void push_ARGB8(lua_State *L, video::SColor color)
|
|
|
|
{
|
|
|
|
lua_newtable(L);
|
|
|
|
lua_pushnumber(L, color.getAlpha());
|
|
|
|
lua_setfield(L, -2, "a");
|
|
|
|
lua_pushnumber(L, color.getRed());
|
|
|
|
lua_setfield(L, -2, "r");
|
|
|
|
lua_pushnumber(L, color.getGreen());
|
|
|
|
lua_setfield(L, -2, "g");
|
|
|
|
lua_pushnumber(L, color.getBlue());
|
|
|
|
lua_setfield(L, -2, "b");
|
|
|
|
}
|
|
|
|
|
2013-02-23 19:06:57 +01:00
|
|
|
void pushFloatPos(lua_State *L, v3f p)
|
|
|
|
{
|
|
|
|
p /= BS;
|
|
|
|
push_v3f(L, p);
|
|
|
|
}
|
|
|
|
|
|
|
|
v3f checkFloatPos(lua_State *L, int index)
|
|
|
|
{
|
|
|
|
return check_v3f(L, index) * BS;
|
|
|
|
}
|
|
|
|
|
|
|
|
void push_v3s16(lua_State *L, v3s16 p)
|
|
|
|
{
|
|
|
|
lua_newtable(L);
|
|
|
|
lua_pushnumber(L, p.X);
|
|
|
|
lua_setfield(L, -2, "x");
|
|
|
|
lua_pushnumber(L, p.Y);
|
|
|
|
lua_setfield(L, -2, "y");
|
|
|
|
lua_pushnumber(L, p.Z);
|
|
|
|
lua_setfield(L, -2, "z");
|
|
|
|
}
|
|
|
|
|
|
|
|
v3s16 read_v3s16(lua_State *L, int index)
|
|
|
|
{
|
|
|
|
// Correct rounding at <0
|
|
|
|
v3f pf = read_v3f(L, index);
|
|
|
|
return floatToInt(pf, 1.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
v3s16 check_v3s16(lua_State *L, int index)
|
|
|
|
{
|
|
|
|
// Correct rounding at <0
|
|
|
|
v3f pf = check_v3f(L, index);
|
|
|
|
return floatToInt(pf, 1.0);
|
|
|
|
}
|
|
|
|
|
2015-05-16 18:26:57 +02:00
|
|
|
bool read_color(lua_State *L, int index, video::SColor *color)
|
|
|
|
{
|
|
|
|
if (lua_istable(L, index)) {
|
|
|
|
*color = read_ARGB8(L, index);
|
|
|
|
} else if (lua_isnumber(L, index)) {
|
|
|
|
color->set(lua_tonumber(L, index));
|
|
|
|
} else if (lua_isstring(L, index)) {
|
|
|
|
video::SColor parsed_color;
|
|
|
|
if (!parseColorString(lua_tostring(L, index), parsed_color, true))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
*color = parsed_color;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
video::SColor read_ARGB8(lua_State *L, int index)
|
2013-02-23 19:06:57 +01:00
|
|
|
{
|
2013-05-20 03:26:08 +02:00
|
|
|
video::SColor color(0);
|
2015-05-06 21:33:36 +02:00
|
|
|
CHECK_TYPE(index, "ARGB color", LUA_TTABLE);
|
2013-02-23 19:06:57 +01:00
|
|
|
lua_getfield(L, index, "a");
|
2015-05-16 18:26:57 +02:00
|
|
|
color.setAlpha(lua_isnumber(L, -1) ? lua_tonumber(L, -1) : 0xFF);
|
2013-02-23 19:06:57 +01:00
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_getfield(L, index, "r");
|
|
|
|
color.setRed(lua_tonumber(L, -1));
|
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_getfield(L, index, "g");
|
|
|
|
color.setGreen(lua_tonumber(L, -1));
|
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_getfield(L, index, "b");
|
|
|
|
color.setBlue(lua_tonumber(L, -1));
|
|
|
|
lua_pop(L, 1);
|
|
|
|
return color;
|
|
|
|
}
|
|
|
|
|
|
|
|
aabb3f read_aabb3f(lua_State *L, int index, f32 scale)
|
|
|
|
{
|
|
|
|
aabb3f box;
|
|
|
|
if(lua_istable(L, index)){
|
|
|
|
lua_rawgeti(L, index, 1);
|
|
|
|
box.MinEdge.X = lua_tonumber(L, -1) * scale;
|
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_rawgeti(L, index, 2);
|
|
|
|
box.MinEdge.Y = lua_tonumber(L, -1) * scale;
|
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_rawgeti(L, index, 3);
|
|
|
|
box.MinEdge.Z = lua_tonumber(L, -1) * scale;
|
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_rawgeti(L, index, 4);
|
|
|
|
box.MaxEdge.X = lua_tonumber(L, -1) * scale;
|
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_rawgeti(L, index, 5);
|
|
|
|
box.MaxEdge.Y = lua_tonumber(L, -1) * scale;
|
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_rawgeti(L, index, 6);
|
|
|
|
box.MaxEdge.Z = lua_tonumber(L, -1) * scale;
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
return box;
|
|
|
|
}
|
|
|
|
|
2015-05-26 14:10:08 +02:00
|
|
|
void push_aabb3f(lua_State *L, aabb3f box)
|
|
|
|
{
|
|
|
|
lua_newtable(L);
|
|
|
|
lua_pushnumber(L, box.MinEdge.X);
|
|
|
|
lua_rawseti(L, -2, 1);
|
|
|
|
lua_pushnumber(L, box.MinEdge.Y);
|
|
|
|
lua_rawseti(L, -2, 2);
|
|
|
|
lua_pushnumber(L, box.MinEdge.Z);
|
|
|
|
lua_rawseti(L, -2, 3);
|
|
|
|
lua_pushnumber(L, box.MaxEdge.X);
|
|
|
|
lua_rawseti(L, -2, 4);
|
|
|
|
lua_pushnumber(L, box.MaxEdge.Y);
|
|
|
|
lua_rawseti(L, -2, 5);
|
|
|
|
lua_pushnumber(L, box.MaxEdge.Z);
|
|
|
|
lua_rawseti(L, -2, 6);
|
|
|
|
}
|
|
|
|
|
2013-02-23 19:06:57 +01:00
|
|
|
std::vector<aabb3f> read_aabb3f_vector(lua_State *L, int index, f32 scale)
|
|
|
|
{
|
|
|
|
std::vector<aabb3f> boxes;
|
|
|
|
if(lua_istable(L, index)){
|
|
|
|
int n = lua_objlen(L, index);
|
|
|
|
// Check if it's a single box or a list of boxes
|
|
|
|
bool possibly_single_box = (n == 6);
|
|
|
|
for(int i = 1; i <= n && possibly_single_box; i++){
|
|
|
|
lua_rawgeti(L, index, i);
|
|
|
|
if(!lua_isnumber(L, -1))
|
|
|
|
possibly_single_box = false;
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
if(possibly_single_box){
|
|
|
|
// Read a single box
|
|
|
|
boxes.push_back(read_aabb3f(L, index, scale));
|
|
|
|
} else {
|
|
|
|
// Read a list of boxes
|
|
|
|
for(int i = 1; i <= n; i++){
|
|
|
|
lua_rawgeti(L, index, i);
|
|
|
|
boxes.push_back(read_aabb3f(L, -1, scale));
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return boxes;
|
|
|
|
}
|
|
|
|
|
2015-04-16 10:12:26 +02:00
|
|
|
size_t read_stringlist(lua_State *L, int index, std::vector<std::string> *result)
|
2014-10-08 21:28:14 +02:00
|
|
|
{
|
|
|
|
if (index < 0)
|
|
|
|
index = lua_gettop(L) + 1 + index;
|
|
|
|
|
2015-04-16 10:12:26 +02:00
|
|
|
size_t num_strings = 0;
|
|
|
|
|
2014-10-08 21:28:14 +02:00
|
|
|
if (lua_istable(L, index)) {
|
|
|
|
lua_pushnil(L);
|
|
|
|
while (lua_next(L, index)) {
|
2015-04-16 10:12:26 +02:00
|
|
|
if (lua_isstring(L, -1)) {
|
|
|
|
result->push_back(lua_tostring(L, -1));
|
|
|
|
num_strings++;
|
|
|
|
}
|
2014-10-08 21:28:14 +02:00
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
} else if (lua_isstring(L, index)) {
|
2015-04-16 10:12:26 +02:00
|
|
|
result->push_back(lua_tostring(L, index));
|
|
|
|
num_strings++;
|
2014-10-08 21:28:14 +02:00
|
|
|
}
|
2015-04-16 10:12:26 +02:00
|
|
|
|
|
|
|
return num_strings;
|
2014-10-08 21:28:14 +02:00
|
|
|
}
|
|
|
|
|
2013-02-23 19:06:57 +01:00
|
|
|
/*
|
|
|
|
Table field getters
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool getstringfield(lua_State *L, int table,
|
|
|
|
const char *fieldname, std::string &result)
|
|
|
|
{
|
|
|
|
lua_getfield(L, table, fieldname);
|
|
|
|
bool got = false;
|
|
|
|
if(lua_isstring(L, -1)){
|
|
|
|
size_t len = 0;
|
|
|
|
const char *ptr = lua_tolstring(L, -1, &len);
|
2013-06-23 16:09:02 +02:00
|
|
|
if (ptr) {
|
|
|
|
result.assign(ptr, len);
|
|
|
|
got = true;
|
|
|
|
}
|
2013-02-23 19:06:57 +01:00
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
return got;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool getintfield(lua_State *L, int table,
|
|
|
|
const char *fieldname, int &result)
|
|
|
|
{
|
|
|
|
lua_getfield(L, table, fieldname);
|
|
|
|
bool got = false;
|
|
|
|
if(lua_isnumber(L, -1)){
|
2016-08-10 12:17:48 +02:00
|
|
|
result = lua_tointeger(L, -1);
|
2013-02-23 19:06:57 +01:00
|
|
|
got = true;
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
return got;
|
|
|
|
}
|
|
|
|
|
2015-05-09 07:38:20 +02:00
|
|
|
bool getintfield(lua_State *L, int table,
|
|
|
|
const char *fieldname, u8 &result)
|
|
|
|
{
|
|
|
|
lua_getfield(L, table, fieldname);
|
|
|
|
bool got = false;
|
|
|
|
if(lua_isnumber(L, -1)){
|
2016-08-10 12:17:48 +02:00
|
|
|
result = lua_tointeger(L, -1);
|
2015-05-09 07:38:20 +02:00
|
|
|
got = true;
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
return got;
|
|
|
|
}
|
|
|
|
|
2015-04-20 03:42:40 +02:00
|
|
|
bool getintfield(lua_State *L, int table,
|
|
|
|
const char *fieldname, u16 &result)
|
|
|
|
{
|
|
|
|
lua_getfield(L, table, fieldname);
|
|
|
|
bool got = false;
|
|
|
|
if(lua_isnumber(L, -1)){
|
2016-08-10 12:17:48 +02:00
|
|
|
result = lua_tointeger(L, -1);
|
2015-04-20 03:42:40 +02:00
|
|
|
got = true;
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
return got;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool getintfield(lua_State *L, int table,
|
|
|
|
const char *fieldname, u32 &result)
|
|
|
|
{
|
|
|
|
lua_getfield(L, table, fieldname);
|
|
|
|
bool got = false;
|
|
|
|
if(lua_isnumber(L, -1)){
|
2016-08-10 12:17:48 +02:00
|
|
|
result = lua_tointeger(L, -1);
|
2015-04-20 03:42:40 +02:00
|
|
|
got = true;
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
return got;
|
|
|
|
}
|
|
|
|
|
2013-02-23 19:06:57 +01:00
|
|
|
bool getfloatfield(lua_State *L, int table,
|
|
|
|
const char *fieldname, float &result)
|
|
|
|
{
|
|
|
|
lua_getfield(L, table, fieldname);
|
|
|
|
bool got = false;
|
|
|
|
if(lua_isnumber(L, -1)){
|
|
|
|
result = lua_tonumber(L, -1);
|
|
|
|
got = true;
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
return got;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool getboolfield(lua_State *L, int table,
|
|
|
|
const char *fieldname, bool &result)
|
|
|
|
{
|
|
|
|
lua_getfield(L, table, fieldname);
|
|
|
|
bool got = false;
|
|
|
|
if(lua_isboolean(L, -1)){
|
|
|
|
result = lua_toboolean(L, -1);
|
|
|
|
got = true;
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
return got;
|
|
|
|
}
|
|
|
|
|
2015-04-16 10:12:26 +02:00
|
|
|
size_t getstringlistfield(lua_State *L, int table, const char *fieldname,
|
|
|
|
std::vector<std::string> *result)
|
2014-10-08 21:28:14 +02:00
|
|
|
{
|
|
|
|
lua_getfield(L, table, fieldname);
|
|
|
|
|
2015-04-16 10:12:26 +02:00
|
|
|
size_t num_strings_read = read_stringlist(L, -1, result);
|
2014-10-08 21:28:14 +02:00
|
|
|
|
|
|
|
lua_pop(L, 1);
|
2015-04-16 10:12:26 +02:00
|
|
|
return num_strings_read;
|
2014-10-08 21:28:14 +02:00
|
|
|
}
|
|
|
|
|
2013-02-23 19:06:57 +01:00
|
|
|
std::string checkstringfield(lua_State *L, int table,
|
|
|
|
const char *fieldname)
|
|
|
|
{
|
|
|
|
lua_getfield(L, table, fieldname);
|
2015-05-06 21:33:36 +02:00
|
|
|
CHECK_TYPE(-1, std::string("field \"") + fieldname + '"', LUA_TSTRING);
|
|
|
|
size_t len;
|
|
|
|
const char *s = lua_tolstring(L, -1, &len);
|
2013-02-23 19:06:57 +01:00
|
|
|
lua_pop(L, 1);
|
2015-05-06 21:33:36 +02:00
|
|
|
return std::string(s, len);
|
2013-02-23 19:06:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string getstringfield_default(lua_State *L, int table,
|
|
|
|
const char *fieldname, const std::string &default_)
|
|
|
|
{
|
|
|
|
std::string result = default_;
|
|
|
|
getstringfield(L, table, fieldname, result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
int getintfield_default(lua_State *L, int table,
|
|
|
|
const char *fieldname, int default_)
|
|
|
|
{
|
|
|
|
int result = default_;
|
|
|
|
getintfield(L, table, fieldname, result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
float getfloatfield_default(lua_State *L, int table,
|
|
|
|
const char *fieldname, float default_)
|
|
|
|
{
|
|
|
|
float result = default_;
|
|
|
|
getfloatfield(L, table, fieldname, result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool getboolfield_default(lua_State *L, int table,
|
|
|
|
const char *fieldname, bool default_)
|
|
|
|
{
|
|
|
|
bool result = default_;
|
|
|
|
getboolfield(L, table, fieldname, result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2016-02-18 11:38:47 +01:00
|
|
|
void setstringfield(lua_State *L, int table,
|
|
|
|
const char *fieldname, const char *value)
|
|
|
|
{
|
|
|
|
lua_pushstring(L, value);
|
|
|
|
if(table < 0)
|
|
|
|
table -= 1;
|
|
|
|
lua_setfield(L, table, fieldname);
|
|
|
|
}
|
|
|
|
|
2013-02-23 19:06:57 +01:00
|
|
|
void setintfield(lua_State *L, int table,
|
|
|
|
const char *fieldname, int value)
|
|
|
|
{
|
|
|
|
lua_pushinteger(L, value);
|
|
|
|
if(table < 0)
|
|
|
|
table -= 1;
|
|
|
|
lua_setfield(L, table, fieldname);
|
|
|
|
}
|
|
|
|
|
|
|
|
void setfloatfield(lua_State *L, int table,
|
|
|
|
const char *fieldname, float value)
|
|
|
|
{
|
|
|
|
lua_pushnumber(L, value);
|
|
|
|
if(table < 0)
|
|
|
|
table -= 1;
|
|
|
|
lua_setfield(L, table, fieldname);
|
|
|
|
}
|
|
|
|
|
|
|
|
void setboolfield(lua_State *L, int table,
|
|
|
|
const char *fieldname, bool value)
|
|
|
|
{
|
|
|
|
lua_pushboolean(L, value);
|
|
|
|
if(table < 0)
|
|
|
|
table -= 1;
|
|
|
|
lua_setfield(L, table, fieldname);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-17 09:38:39 +02:00
|
|
|
////
|
|
|
|
//// Array table slices
|
|
|
|
////
|
|
|
|
|
|
|
|
size_t write_array_slice_float(
|
|
|
|
lua_State *L,
|
|
|
|
int table_index,
|
|
|
|
float *data,
|
|
|
|
v3u16 data_size,
|
|
|
|
v3u16 slice_offset,
|
|
|
|
v3u16 slice_size)
|
|
|
|
{
|
|
|
|
v3u16 pmin, pmax(data_size);
|
|
|
|
|
|
|
|
if (slice_offset.X > 0) {
|
|
|
|
slice_offset.X--;
|
|
|
|
pmin.X = slice_offset.X;
|
|
|
|
pmax.X = MYMIN(slice_offset.X + slice_size.X, data_size.X);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (slice_offset.Y > 0) {
|
|
|
|
slice_offset.Y--;
|
|
|
|
pmin.Y = slice_offset.Y;
|
|
|
|
pmax.Y = MYMIN(slice_offset.Y + slice_size.Y, data_size.Y);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (slice_offset.Z > 0) {
|
|
|
|
slice_offset.Z--;
|
|
|
|
pmin.Z = slice_offset.Z;
|
|
|
|
pmax.Z = MYMIN(slice_offset.Z + slice_size.Z, data_size.Z);
|
|
|
|
}
|
|
|
|
|
|
|
|
const u32 ystride = data_size.X;
|
|
|
|
const u32 zstride = data_size.X * data_size.Y;
|
|
|
|
|
|
|
|
u32 elem_index = 1;
|
|
|
|
for (u32 z = pmin.Z; z != pmax.Z; z++)
|
|
|
|
for (u32 y = pmin.Y; y != pmax.Y; y++)
|
|
|
|
for (u32 x = pmin.X; x != pmax.X; x++) {
|
|
|
|
u32 i = z * zstride + y * ystride + x;
|
|
|
|
lua_pushnumber(L, data[i]);
|
|
|
|
lua_rawseti(L, table_index, elem_index);
|
|
|
|
elem_index++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return elem_index - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
size_t write_array_slice_u16(
|
|
|
|
lua_State *L,
|
|
|
|
int table_index,
|
|
|
|
u16 *data,
|
|
|
|
v3u16 data_size,
|
|
|
|
v3u16 slice_offset,
|
|
|
|
v3u16 slice_size)
|
|
|
|
{
|
|
|
|
v3u16 pmin, pmax(data_size);
|
|
|
|
|
|
|
|
if (slice_offset.X > 0) {
|
|
|
|
slice_offset.X--;
|
|
|
|
pmin.X = slice_offset.X;
|
|
|
|
pmax.X = MYMIN(slice_offset.X + slice_size.X, data_size.X);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (slice_offset.Y > 0) {
|
|
|
|
slice_offset.Y--;
|
|
|
|
pmin.Y = slice_offset.Y;
|
|
|
|
pmax.Y = MYMIN(slice_offset.Y + slice_size.Y, data_size.Y);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (slice_offset.Z > 0) {
|
|
|
|
slice_offset.Z--;
|
|
|
|
pmin.Z = slice_offset.Z;
|
|
|
|
pmax.Z = MYMIN(slice_offset.Z + slice_size.Z, data_size.Z);
|
|
|
|
}
|
|
|
|
|
|
|
|
const u32 ystride = data_size.X;
|
|
|
|
const u32 zstride = data_size.X * data_size.Y;
|
|
|
|
|
|
|
|
u32 elem_index = 1;
|
|
|
|
for (u32 z = pmin.Z; z != pmax.Z; z++)
|
|
|
|
for (u32 y = pmin.Y; y != pmax.Y; y++)
|
|
|
|
for (u32 x = pmin.X; x != pmax.X; x++) {
|
|
|
|
u32 i = z * zstride + y * ystride + x;
|
|
|
|
lua_pushinteger(L, data[i]);
|
|
|
|
lua_rawseti(L, table_index, elem_index);
|
|
|
|
elem_index++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return elem_index - 1;
|
|
|
|
}
|