}
#include "util/numeric.h"
+#include "util/serialize.h"
#include "util/string.h"
#include "common/c_converter.h"
+#include "common/c_internal.h"
#include "constants.h"
-#define CHECK_TYPE(index, name, type) do { \
+#define CHECK_TYPE(index, name, type) { \
int t = lua_type(L, (index)); \
if (t != (type)) { \
+ std::string traceback = script_get_backtrace(L); \
throw LuaError(std::string("Invalid ") + (name) + \
" (expected " + lua_typename(L, (type)) + \
- " got " + lua_typename(L, t) + ")."); \
+ " got " + lua_typename(L, t) + ").\n" + traceback); \
} \
- } while(0)
+ }
#define CHECK_POS_COORD(name) CHECK_TYPE(-1, "position coordinate '" name "'", LUA_TNUMBER)
+#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()); \
+}
#define CHECK_POS_TAB(index) CHECK_TYPE(index, "position", LUA_TTABLE)
+void push_float_string(lua_State *L, float value)
+{
+ std::stringstream ss;
+ std::string str;
+ ss << value;
+ str = ss.str();
+ lua_pushstring(L, str.c_str());
+}
+
void push_v3f(lua_State *L, v3f p)
{
lua_newtable(L);
lua_setfield(L, -2, "y");
}
-v2s16 read_v2s16(lua_State *L, int index)
+void push_v3_float_string(lua_State *L, v3f p)
{
- v2s16 p;
- CHECK_POS_TAB(index);
- lua_getfield(L, index, "x");
- 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;
+ lua_newtable(L);
+ push_float_string(L, p.X);
+ lua_setfield(L, -2, "x");
+ push_float_string(L, p.Y);
+ lua_setfield(L, -2, "y");
+ push_float_string(L, p.Z);
+ lua_setfield(L, -2, "z");
}
-v2s16 check_v2s16(lua_State *L, int index)
+void push_v2_float_string(lua_State *L, v2f p)
+{
+ lua_newtable(L);
+ push_float_string(L, p.X);
+ lua_setfield(L, -2, "x");
+ push_float_string(L, p.Y);
+ lua_setfield(L, -2, "y");
+}
+
+v2s16 read_v2s16(lua_State *L, int index)
{
v2s16 p;
CHECK_POS_TAB(index);
lua_getfield(L, index, "x");
- CHECK_POS_COORD("x");
p.X = lua_tonumber(L, -1);
lua_pop(L, 1);
lua_getfield(L, index, "y");
- CHECK_POS_COORD("y");
p.Y = lua_tonumber(L, -1);
lua_pop(L, 1);
return p;
lua_getfield(L, index, "x");
CHECK_POS_COORD("x");
pos.X = lua_tonumber(L, -1);
+ CHECK_FLOAT_RANGE(pos.X, "x")
+ lua_pop(L, 1);
+ lua_getfield(L, index, "y");
+ CHECK_POS_COORD("y");
+ pos.Y = lua_tonumber(L, -1);
+ CHECK_FLOAT_RANGE(pos.Y, "y")
+ lua_pop(L, 1);
+ lua_getfield(L, index, "z");
+ CHECK_POS_COORD("z");
+ pos.Z = lua_tonumber(L, -1);
+ CHECK_FLOAT_RANGE(pos.Z, "z")
+ lua_pop(L, 1);
+ return pos;
+}
+
+v3d read_v3d(lua_State *L, int index)
+{
+ v3d pos;
+ CHECK_POS_TAB(index);
+ 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;
+}
+
+v3d check_v3d(lua_State *L, int index)
+{
+ v3d pos;
+ CHECK_POS_TAB(index);
+ lua_getfield(L, index, "x");
+ CHECK_POS_COORD("x");
+ pos.X = lua_tonumber(L, -1);
+ CHECK_FLOAT_RANGE(pos.X, "x")
lua_pop(L, 1);
lua_getfield(L, index, "y");
CHECK_POS_COORD("y");
pos.Y = lua_tonumber(L, -1);
+ CHECK_FLOAT_RANGE(pos.Y, "y")
lua_pop(L, 1);
lua_getfield(L, index, "z");
CHECK_POS_COORD("z");
pos.Z = lua_tonumber(L, -1);
+ CHECK_FLOAT_RANGE(pos.Z, "z")
lua_pop(L, 1);
return pos;
}
v3s16 read_v3s16(lua_State *L, int index)
{
// Correct rounding at <0
- v3f pf = read_v3f(L, index);
- return floatToInt(pf, 1.0);
+ v3d pf = read_v3d(L, index);
+ return doubleToInt(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);
+ v3d pf = check_v3d(L, index);
+ return doubleToInt(pf, 1.0);
}
bool read_color(lua_State *L, int index, video::SColor *color)
return color;
}
+bool is_color_table(lua_State *L, int index)
+{
+ // Check whole table in case of missing ColorSpec keys:
+ // This check does not remove the checked value from the stack.
+ // Only update the value if we know we have a valid ColorSpec key pair.
+ if (!lua_istable(L, index))
+ return false;
+
+ bool is_color_table = false;
+ lua_getfield(L, index, "r");
+ if (!is_color_table)
+ is_color_table = lua_isnumber(L, -1);
+ lua_getfield(L, index, "g");
+ if (!is_color_table)
+ is_color_table = lua_isnumber(L, -1);
+ lua_getfield(L, index, "b");
+ if (!is_color_table)
+ is_color_table = lua_isnumber(L, -1);
+ lua_pop(L, 3); // b, g, r values
+ return is_color_table;
+}
+
aabb3f read_aabb3f(lua_State *L, int index, f32 scale)
{
aabb3f box;
box.MaxEdge.Z = lua_tonumber(L, -1) * scale;
lua_pop(L, 1);
}
+ box.repair();
return box;
}
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)){
- result = lua_tonumber(L, -1);
- got = true;
- }
- lua_pop(L, 1);
- return got;
-}
-
-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)){
- result = lua_tonumber(L, -1);
- got = true;
- }
- lua_pop(L, 1);
- return got;
-}
-
-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)){
- result = lua_tonumber(L, -1);
- 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)){
- result = lua_tonumber(L, -1);
- got = true;
- }
- lua_pop(L, 1);
- return got;
-}
-
bool getfloatfield(lua_State *L, int table,
const char *fieldname, float &result)
{
return result;
}
+v3s16 getv3s16field_default(lua_State *L, int table,
+ const char *fieldname, v3s16 default_)
+{
+ getv3intfield(L, table, fieldname, default_);
+ return default_;
+}
+
+void setstringfield(lua_State *L, int table,
+ const char *fieldname, const std::string &value)
+{
+ lua_pushlstring(L, value.c_str(), value.length());
+ if(table < 0)
+ table -= 1;
+ lua_setfield(L, table, fieldname);
+}
+
void setintfield(lua_State *L, int table,
const char *fieldname, int value)
{