diff options
Diffstat (limited to 'src/script/common')
-rw-r--r-- | src/script/common/CMakeLists.txt | 5 | ||||
-rw-r--r-- | src/script/common/c_content.cpp | 189 | ||||
-rw-r--r-- | src/script/common/c_content.h | 69 | ||||
-rw-r--r-- | src/script/common/c_converter.cpp | 300 | ||||
-rw-r--r-- | src/script/common/c_converter.h | 38 | ||||
-rw-r--r-- | src/script/common/c_internal.cpp | 84 | ||||
-rw-r--r-- | src/script/common/c_internal.h | 17 |
7 files changed, 561 insertions, 141 deletions
diff --git a/src/script/common/CMakeLists.txt b/src/script/common/CMakeLists.txt index 27e2fb4d5..4a8e6bab5 100644 --- a/src/script/common/CMakeLists.txt +++ b/src/script/common/CMakeLists.txt @@ -1,4 +1,3 @@ -# Used by server and client set(common_SCRIPT_COMMON_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/c_content.cpp ${CMAKE_CURRENT_SOURCE_DIR}/c_converter.cpp @@ -6,6 +5,6 @@ set(common_SCRIPT_COMMON_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/c_internal.cpp PARENT_SCOPE) -# Used by client only -set(minetest_SCRIPT_COMMON_SRCS +set(client_SCRIPT_COMMON_SRCS PARENT_SCOPE) + diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index ff9aee8ed..3754fc2ff 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -162,18 +162,13 @@ void read_object_properties(lua_State *L, int index, lua_pop(L, 1); lua_getfield(L, -1, "colors"); - if(lua_istable(L, -1)){ - prop->colors.clear(); + if (lua_istable(L, -1)) { int table = lua_gettop(L); - lua_pushnil(L); - while(lua_next(L, table) != 0){ - // key at index -2 and value at index -1 - if(lua_isstring(L, -1)) - prop->colors.push_back(readARGB8(L, -1)); - else - prop->colors.push_back(video::SColor(255, 255, 255, 255)); - // removes value, keeps key for next iteration - lua_pop(L, 1); + prop->colors.clear(); + for (lua_pushnil(L); lua_next(L, table); lua_pop(L, 1)) { + video::SColor color(255, 255, 255, 255); + read_color(L, -1, &color); + prop->colors.push_back(color); } } lua_pop(L, 1); @@ -205,17 +200,78 @@ void read_object_properties(lua_State *L, int index, } /******************************************************************************/ -TileDef read_tiledef(lua_State *L, int index) +void push_object_properties(lua_State *L, ObjectProperties *prop) +{ + lua_newtable(L); + lua_pushnumber(L, prop->hp_max); + lua_setfield(L, -2, "hp_max"); + lua_pushboolean(L, prop->physical); + lua_setfield(L, -2, "physical"); + lua_pushboolean(L, prop->collideWithObjects); + lua_setfield(L, -2, "collide_with_objects"); + lua_pushnumber(L, prop->weight); + lua_setfield(L, -2, "weight"); + push_aabb3f(L, prop->collisionbox); + lua_setfield(L, -2, "collisionbox"); + lua_pushlstring(L, prop->visual.c_str(), prop->visual.size()); + lua_setfield(L, -2, "visual"); + lua_pushlstring(L, prop->mesh.c_str(), prop->mesh.size()); + lua_setfield(L, -2, "mesh"); + push_v2f(L, prop->visual_size); + lua_setfield(L, -2, "visual_size"); + + lua_newtable(L); + u16 i = 1; + for (std::vector<std::string>::iterator it = prop->textures.begin(); + it != prop->textures.end(); ++it) { + lua_pushlstring(L, it->c_str(), it->size()); + lua_rawseti(L, -2, i); + } + lua_setfield(L, -2, "textures"); + + lua_newtable(L); + i = 1; + for (std::vector<video::SColor>::iterator it = prop->colors.begin(); + it != prop->colors.end(); ++it) { + push_ARGB8(L, *it); + lua_rawseti(L, -2, i); + } + lua_setfield(L, -2, "colors"); + + push_v2s16(L, prop->spritediv); + lua_setfield(L, -2, "spritediv"); + push_v2s16(L, prop->initial_sprite_basepos); + lua_setfield(L, -2, "initial_sprite_basepos"); + lua_pushboolean(L, prop->is_visible); + lua_setfield(L, -2, "is_visible"); + lua_pushboolean(L, prop->makes_footstep_sound); + lua_setfield(L, -2, "makes_footstep_sound"); + lua_pushnumber(L, prop->automatic_rotate); + lua_setfield(L, -2, "automatic_rotate"); + lua_pushnumber(L, prop->stepheight / BS); + lua_setfield(L, -2, "stepheight"); + if (prop->automatic_face_movement_dir) + lua_pushnumber(L, prop->automatic_face_movement_dir_offset); + else + lua_pushboolean(L, false); + lua_setfield(L, -2, "automatic_face_movement_dir"); +} + +/******************************************************************************/ +TileDef read_tiledef(lua_State *L, int index, u8 drawtype) { if(index < 0) index = lua_gettop(L) + 1 + index; TileDef tiledef; - + bool default_tiling = (drawtype == NDT_PLANTLIKE || drawtype == NDT_FIRELIKE) + ? false : true; // key at index -2 and value at index if(lua_isstring(L, index)){ // "default_lava.png" tiledef.name = lua_tostring(L, index); + tiledef.tileable_vertical = default_tiling; + tiledef.tileable_horizontal = default_tiling; } else if(lua_istable(L, index)) { @@ -224,20 +280,24 @@ TileDef read_tiledef(lua_State *L, int index) getstringfield(L, index, "name", tiledef.name); getstringfield(L, index, "image", tiledef.name); // MaterialSpec compat. tiledef.backface_culling = getboolfield_default( - L, index, "backface_culling", true); + L, index, "backface_culling", true); + tiledef.tileable_horizontal = getboolfield_default( + L, index, "tileable_horizontal", default_tiling); + tiledef.tileable_vertical = getboolfield_default( + L, index, "tileable_vertical", default_tiling); // animation = {} lua_getfield(L, index, "animation"); if(lua_istable(L, -1)){ // {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0} tiledef.animation.type = (TileAnimationType) - getenumfield(L, -1, "type", es_TileAnimationType, - TAT_NONE); + getenumfield(L, -1, "type", es_TileAnimationType, + TAT_NONE); tiledef.animation.aspect_w = - getintfield_default(L, -1, "aspect_w", 16); + getintfield_default(L, -1, "aspect_w", 16); tiledef.animation.aspect_h = - getintfield_default(L, -1, "aspect_h", 16); + getintfield_default(L, -1, "aspect_h", 16); tiledef.animation.length = - getfloatfield_default(L, -1, "length", 1.0); + getfloatfield_default(L, -1, "length", 1.0); } lua_pop(L, 1); } @@ -300,7 +360,7 @@ ContentFeatures read_content_features(lua_State *L, int index) int i = 0; while(lua_next(L, table) != 0){ // Read tiledef from value - f.tiledef[i] = read_tiledef(L, -1); + f.tiledef[i] = read_tiledef(L, -1, f.drawtype); // removes value, keeps key for next iteration lua_pop(L, 1); i++; @@ -335,7 +395,7 @@ ContentFeatures read_content_features(lua_State *L, int index) int i = 0; while(lua_next(L, table) != 0){ // Read tiledef from value - f.tiledef_special[i] = read_tiledef(L, -1); + f.tiledef_special[i] = read_tiledef(L, -1, f.drawtype); // removes value, keeps key for next iteration lua_pop(L, 1); i++; @@ -357,8 +417,7 @@ ContentFeatures read_content_features(lua_State *L, int index) /* Other stuff */ lua_getfield(L, index, "post_effect_color"); - if(!lua_isnil(L, -1)) - f.post_effect_color = readARGB8(L, -1); + read_color(L, -1, &f.post_effect_color); lua_pop(L, 1); f.param_type = (ContentParamType)getenumfield(L, index, "paramtype", @@ -546,22 +605,23 @@ NodeBox read_nodebox(lua_State *L, int index) MapNode readnode(lua_State *L, int index, INodeDefManager *ndef) { lua_getfield(L, index, "name"); - const char *name = luaL_checkstring(L, -1); + if (!lua_isstring(L, -1)) + throw LuaError("Node name is not set or is not a string!"); + const char *name = lua_tostring(L, -1); lua_pop(L, 1); - u8 param1; + + u8 param1 = 0; lua_getfield(L, index, "param1"); - if(lua_isnil(L, -1)) - param1 = 0; - else + if (!lua_isnil(L, -1)) param1 = lua_tonumber(L, -1); lua_pop(L, 1); - u8 param2; + + u8 param2 = 0; lua_getfield(L, index, "param2"); - if(lua_isnil(L, -1)) - param2 = 0; - else + if (!lua_isnil(L, -1)) param2 = lua_tonumber(L, -1); lua_pop(L, 1); + return MapNode(ndef, name, param1, param2); } @@ -901,6 +961,12 @@ u32 read_flags_table(lua_State *L, int table, FlagDesc *flagdesc, u32 *flagmask) return flags; } +void push_flags_string(lua_State *L, FlagDesc *flagdesc, u32 flags, u32 flagmask) +{ + std::string flagstring = writeFlagString(flags, flagdesc, flagmask); + lua_pushlstring(L, flagstring.c_str(), flagstring.size()); +} + /******************************************************************************/ /* Lua Stored data! */ /******************************************************************************/ @@ -926,14 +992,23 @@ void read_groups(lua_State *L, int index, } /******************************************************************************/ +void push_groups(lua_State *L, const std::map<std::string, int> &groups) +{ + lua_newtable(L); + std::map<std::string, int>::const_iterator it; + for (it = groups.begin(); it != groups.end(); ++it) { + lua_pushnumber(L, it->second); + lua_setfield(L, -2, it->first.c_str()); + } +} + +/******************************************************************************/ void push_items(lua_State *L, const std::vector<ItemStack> &items) { - // Create and fill table lua_createtable(L, items.size(), 0); - std::vector<ItemStack>::const_iterator iter = items.begin(); - for (u32 i = 0; iter != items.end(); iter++) { - LuaItemStack::create(L, *iter); - lua_rawseti(L, -2, ++i); + for (u32 i = 0; i != items.size(); i++) { + LuaItemStack::create(L, items[i]); + lua_rawseti(L, -2, i + 1); } } @@ -982,14 +1057,16 @@ bool read_noiseparams(lua_State *L, int index, NoiseParams *np) if (!lua_istable(L, index)) return false; - np->offset = getfloatfield_default(L, index, "offset", 0.0); - np->scale = getfloatfield_default(L, index, "scale", 0.0); - np->persist = getfloatfield_default(L, index, "persist", 0.0); - np->lacunarity = getfloatfield_default(L, index, "lacunarity", 2.0); - np->seed = getintfield_default(L, index, "seed", 0); - np->octaves = getintfield_default(L, index, "octaves", 0); + getfloatfield(L, index, "offset", np->offset); + getfloatfield(L, index, "scale", np->scale); + getfloatfield(L, index, "persist", np->persist); + getfloatfield(L, index, "persistence", np->persist); + getfloatfield(L, index, "lacunarity", np->lacunarity); + getintfield(L, index, "seed", np->seed); + getintfield(L, index, "octaves", np->octaves); - u32 flags = 0, flagmask = 0; + u32 flags = 0; + u32 flagmask = 0; np->flags = getflagsfield(L, index, "flags", flagdesc_noiseparams, &flags, &flagmask) ? flags : NOISE_FLAG_DEFAULTS; @@ -1000,6 +1077,30 @@ bool read_noiseparams(lua_State *L, int index, NoiseParams *np) return true; } +void push_noiseparams(lua_State *L, NoiseParams *np) +{ + lua_newtable(L); + lua_pushnumber(L, np->offset); + lua_setfield(L, -2, "offset"); + lua_pushnumber(L, np->scale); + lua_setfield(L, -2, "scale"); + lua_pushnumber(L, np->persist); + lua_setfield(L, -2, "persistence"); + lua_pushnumber(L, np->lacunarity); + lua_setfield(L, -2, "lacunarity"); + lua_pushnumber(L, np->seed); + lua_setfield(L, -2, "seed"); + lua_pushnumber(L, np->octaves); + lua_setfield(L, -2, "octaves"); + + push_flags_string(L, flagdesc_noiseparams, np->flags, + np->flags); + lua_setfield(L, -2, "flags"); + + push_v3f(L, np->spread); + lua_setfield(L, -2, "spread"); +} + /******************************************************************************/ // Returns depth of json value tree static int push_json_value_getdepth(const Json::Value &value) diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h index 241b1ca76..46416ad8e 100644 --- a/src/script/common/c_content.h +++ b/src/script/common/c_content.h @@ -62,59 +62,57 @@ struct NoiseParams; class Schematic; -ContentFeatures read_content_features (lua_State *L, int index); -TileDef read_tiledef (lua_State *L, int index); -void read_soundspec (lua_State *L, int index, - SimpleSoundSpec &spec); -NodeBox read_nodebox (lua_State *L, int index); +ContentFeatures read_content_features (lua_State *L, int index); +TileDef read_tiledef (lua_State *L, int index, + u8 drawtype); +void read_soundspec (lua_State *L, int index, + SimpleSoundSpec &spec); +NodeBox read_nodebox (lua_State *L, int index); -void read_server_sound_params (lua_State *L, int index, - ServerSoundParams ¶ms); +void read_server_sound_params (lua_State *L, int index, + ServerSoundParams ¶ms); -void push_dig_params (lua_State *L,const DigParams ¶ms); -void push_hit_params (lua_State *L,const HitParams ¶ms); +void push_dig_params (lua_State *L, + const DigParams ¶ms); +void push_hit_params (lua_State *L, + const HitParams ¶ms); -ItemStack read_item (lua_State *L, int index, Server* srv); +ItemStack read_item (lua_State *L, int index, Server *srv); -ToolCapabilities read_tool_capabilities (lua_State *L, - int table); +ToolCapabilities read_tool_capabilities (lua_State *L, int table); void push_tool_capabilities (lua_State *L, const ToolCapabilities &prop); -ItemDefinition read_item_definition (lua_State *L, - int index, +ItemDefinition read_item_definition (lua_State *L, int index, ItemDefinition default_def); -void read_object_properties (lua_State *L, - int index, +void read_object_properties (lua_State *L, int index, + ObjectProperties *prop); +void push_object_properties (lua_State *L, ObjectProperties *prop); void push_inventory_list (lua_State *L, Inventory *inv, const char *name); -void read_inventory_list (lua_State *L, - int tableindex, - Inventory *inv, - const char *name, - Server* srv, - int forcesize=-1); +void read_inventory_list (lua_State *L, int tableindex, + Inventory *inv, const char *name, + Server *srv, int forcesize=-1); -MapNode readnode (lua_State *L, - int index, +MapNode readnode (lua_State *L, int index, INodeDefManager *ndef); -void pushnode (lua_State *L, - const MapNode &n, +void pushnode (lua_State *L, const MapNode &n, INodeDefManager *ndef); NodeBox read_nodebox (lua_State *L, int index); -void read_groups (lua_State *L, - int index, +void read_groups (lua_State *L, int index, std::map<std::string, int> &result); +void push_groups (lua_State *L, + const std::map<std::string, int> &groups); + //TODO rename to "read_enum_field" -int getenumfield (lua_State *L, - int table, +int getenumfield (lua_State *L, int table, const char *fieldname, const EnumString *spec, int default_); @@ -128,6 +126,9 @@ bool read_flags (lua_State *L, int index, FlagDesc *flagdesc, u32 *flags, u32 *flagmask); +void push_flags_string (lua_State *L, FlagDesc *flagdesc, + u32 flags, u32 flagmask); + u32 read_flags_table (lua_State *L, int table, FlagDesc *flagdesc, u32 *flagmask); @@ -142,23 +143,21 @@ void read_soundspec (lua_State *L, int index, SimpleSoundSpec &spec); - bool string_to_enum (const EnumString *spec, int &result, const std::string &str); bool read_noiseparams (lua_State *L, int index, NoiseParams *np); +void push_noiseparams (lua_State *L, NoiseParams *np); void luaentity_get (lua_State *L,u16 id); bool push_json_value (lua_State *L, const Json::Value &value, int nullindex); -void read_json_value (lua_State *L, - Json::Value &root, - int index, - u8 recursion = 0); +void read_json_value (lua_State *L, Json::Value &root, + int index, u8 recursion = 0); extern struct EnumString es_TileAnimationType[]; diff --git a/src/script/common/c_converter.cpp b/src/script/common/c_converter.cpp index 66eeec68e..f1d3cc421 100644 --- a/src/script/common/c_converter.cpp +++ b/src/script/common/c_converter.cpp @@ -23,9 +23,23 @@ extern "C" { } #include "util/numeric.h" +#include "util/string.h" #include "common/c_converter.h" #include "constants.h" + +#define CHECK_TYPE(index, name, type) do { \ + 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) +#define CHECK_POS_COORD(name) CHECK_TYPE(-1, "position coordinate '" name "'", LUA_TNUMBER) +#define CHECK_POS_TAB(index) CHECK_TYPE(index, "position", LUA_TTABLE) + + void push_v3f(lua_State *L, v3f p) { lua_newtable(L); @@ -49,7 +63,7 @@ void push_v2f(lua_State *L, v2f p) v2s16 read_v2s16(lua_State *L, int index) { v2s16 p; - luaL_checktype(L, index, LUA_TTABLE); + CHECK_POS_TAB(index); lua_getfield(L, index, "x"); p.X = lua_tonumber(L, -1); lua_pop(L, 1); @@ -59,10 +73,43 @@ v2s16 read_v2s16(lua_State *L, int index) return p; } +v2s16 check_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; +} + +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"); +} + v2s32 read_v2s32(lua_State *L, int index) { v2s32 p; - luaL_checktype(L, index, LUA_TTABLE); + CHECK_POS_TAB(index); lua_getfield(L, index, "x"); p.X = lua_tonumber(L, -1); lua_pop(L, 1); @@ -75,11 +122,26 @@ v2s32 read_v2s32(lua_State *L, int index) v2f read_v2f(lua_State *L, int index) { v2f p; - luaL_checktype(L, index, LUA_TTABLE); + 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; +} + +v2f check_v2f(lua_State *L, int index) +{ + v2f 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; @@ -88,7 +150,7 @@ v2f read_v2f(lua_State *L, int index) v3f read_v3f(lua_State *L, int index) { v3f pos; - luaL_checktype(L, index, LUA_TTABLE); + CHECK_POS_TAB(index); lua_getfield(L, index, "x"); pos.X = lua_tonumber(L, -1); lua_pop(L, 1); @@ -104,19 +166,35 @@ v3f read_v3f(lua_State *L, int index) v3f check_v3f(lua_State *L, int index) { v3f pos; - luaL_checktype(L, index, LUA_TTABLE); + CHECK_POS_TAB(index); lua_getfield(L, index, "x"); - pos.X = luaL_checknumber(L, -1); + CHECK_POS_COORD("x"); + pos.X = lua_tonumber(L, -1); lua_pop(L, 1); lua_getfield(L, index, "y"); - pos.Y = luaL_checknumber(L, -1); + CHECK_POS_COORD("y"); + pos.Y = lua_tonumber(L, -1); lua_pop(L, 1); lua_getfield(L, index, "z"); - pos.Z = luaL_checknumber(L, -1); + CHECK_POS_COORD("z"); + pos.Z = lua_tonumber(L, -1); lua_pop(L, 1); return pos; } +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"); +} + void pushFloatPos(lua_State *L, v3f p) { p /= BS; @@ -153,13 +231,31 @@ v3s16 check_v3s16(lua_State *L, int index) return floatToInt(pf, 1.0); } -video::SColor readARGB8(lua_State *L, int index) +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) { video::SColor color(0); - luaL_checktype(L, index, LUA_TTABLE); + CHECK_TYPE(index, "ARGB color", LUA_TTABLE); lua_getfield(L, index, "a"); - if(lua_isnumber(L, -1)) - color.setAlpha(lua_tonumber(L, -1)); + color.setAlpha(lua_isnumber(L, -1) ? lua_tonumber(L, -1) : 0xFF); lua_pop(L, 1); lua_getfield(L, index, "r"); color.setRed(lua_tonumber(L, -1)); @@ -199,6 +295,23 @@ aabb3f read_aabb3f(lua_State *L, int index, f32 scale) return box; } +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); +} + std::vector<aabb3f> read_aabb3f_vector(lua_State *L, int index, f32 scale) { std::vector<aabb3f> boxes; @@ -227,24 +340,28 @@ std::vector<aabb3f> read_aabb3f_vector(lua_State *L, int index, f32 scale) return boxes; } -bool read_stringlist(lua_State *L, int index, std::vector<const char *> &result) +size_t read_stringlist(lua_State *L, int index, std::vector<std::string> *result) { if (index < 0) index = lua_gettop(L) + 1 + index; + size_t num_strings = 0; + if (lua_istable(L, index)) { lua_pushnil(L); while (lua_next(L, index)) { - if (lua_isstring(L, -1)) - result.push_back(lua_tostring(L, -1)); + if (lua_isstring(L, -1)) { + result->push_back(lua_tostring(L, -1)); + num_strings++; + } lua_pop(L, 1); } } else if (lua_isstring(L, index)) { - result.push_back(lua_tostring(L, index)); - } else { - return false; + result->push_back(lua_tostring(L, index)); + num_strings++; } - return true; + + return num_strings; } /* @@ -281,6 +398,45 @@ bool getintfield(lua_State *L, int table, 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) { @@ -307,24 +463,26 @@ bool getboolfield(lua_State *L, int table, return got; } -bool getstringlistfield(lua_State *L, int table, const char *fieldname, - std::vector<const char *> &result) +size_t getstringlistfield(lua_State *L, int table, const char *fieldname, + std::vector<std::string> *result) { lua_getfield(L, table, fieldname); - bool got = read_stringlist(L, -1, result); + size_t num_strings_read = read_stringlist(L, -1, result); lua_pop(L, 1); - return got; + return num_strings_read; } std::string checkstringfield(lua_State *L, int table, const char *fieldname) { lua_getfield(L, table, fieldname); - std::string s = luaL_checkstring(L, -1); + CHECK_TYPE(-1, std::string("field \"") + fieldname + '"', LUA_TSTRING); + size_t len; + const char *s = lua_tolstring(L, -1, &len); lua_pop(L, 1); - return s; + return std::string(s, len); } std::string getstringfield_default(lua_State *L, int table, @@ -387,3 +545,95 @@ void setboolfield(lua_State *L, int table, } +//// +//// 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; +} diff --git a/src/script/common/c_converter.h b/src/script/common/c_converter.h index 3b7eb6f7d..18a045d2a 100644 --- a/src/script/common/c_converter.h +++ b/src/script/common/c_converter.h @@ -48,11 +48,17 @@ int getintfield_default (lua_State *L, int table, bool getstringfield(lua_State *L, int table, const char *fieldname, std::string &result); -bool getstringlistfield(lua_State *L, int table, +size_t getstringlistfield(lua_State *L, int table, const char *fieldname, - std::vector<const char *> &result); + std::vector<std::string> *result); bool getintfield(lua_State *L, int table, const char *fieldname, int &result); +bool getintfield(lua_State *L, int table, + const char *fieldname, u8 &result); +bool getintfield(lua_State *L, int table, + const char *fieldname, u16 &result); +bool getintfield(lua_State *L, int table, + const char *fieldname, u32 &result); void read_groups(lua_State *L, int index, std::map<std::string, int> &result); bool getboolfield(lua_State *L, int table, @@ -70,8 +76,9 @@ void setfloatfield(lua_State *L, int table, void setboolfield(lua_State *L, int table, const char *fieldname, bool value); - v3f checkFloatPos (lua_State *L, int index); +v2f check_v2f (lua_State *L, int index); +v2s16 check_v2s16 (lua_State *L, int index); v3f check_v3f (lua_State *L, int index); v3s16 check_v3s16 (lua_State *L, int index); @@ -79,23 +86,32 @@ v3f read_v3f (lua_State *L, int index); v2f read_v2f (lua_State *L, int index); v2s16 read_v2s16 (lua_State *L, int index); v2s32 read_v2s32 (lua_State *L, int index); -video::SColor readARGB8 (lua_State *L, int index); +video::SColor read_ARGB8 (lua_State *L, int index); +bool read_color (lua_State *L, int index, + video::SColor *color); + aabb3f read_aabb3f (lua_State *L, int index, f32 scale); v3s16 read_v3s16 (lua_State *L, int index); std::vector<aabb3f> read_aabb3f_vector (lua_State *L, int index, f32 scale); -bool read_stringlist (lua_State *L, int index, - std::vector<const char *> &result); +size_t read_stringlist (lua_State *L, int index, + std::vector<std::string> *result); +void push_v2s16 (lua_State *L, v2s16 p); +void push_v2s32 (lua_State *L, v2s32 p); void push_v3s16 (lua_State *L, v3s16 p); +void push_aabb3f (lua_State *L, aabb3f box); +void push_ARGB8 (lua_State *L, video::SColor color); void pushFloatPos (lua_State *L, v3f p); void push_v3f (lua_State *L, v3f p); void push_v2f (lua_State *L, v2f p); +void warn_if_field_exists(lua_State *L, int table, + const char *fieldname, + const std::string &message); - -void warn_if_field_exists (lua_State *L, - int table, - const char *fieldname, - const std::string &message); +size_t write_array_slice_float(lua_State *L, int table_index, float *data, + v3u16 data_size, v3u16 slice_offset, v3u16 slice_size); +size_t write_array_slice_u16(lua_State *L, int table_index, u16 *data, + v3u16 data_size, v3u16 slice_offset, v3u16 slice_size); #endif /* C_CONVERTER_H_ */ diff --git a/src/script/common/c_internal.cpp b/src/script/common/c_internal.cpp index f811dd5d3..2a10ce0f2 100644 --- a/src/script/common/c_internal.cpp +++ b/src/script/common/c_internal.cpp @@ -20,7 +20,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common/c_internal.h" #include "debug.h" #include "log.h" -#include "main.h" #include "settings.h" std::string script_get_backtrace(lua_State *L) @@ -64,19 +63,65 @@ int script_exception_wrapper(lua_State *L, lua_CFunction f) return f(L); // Call wrapped function and return result. } catch (const char *s) { // Catch and convert exceptions. lua_pushstring(L, s); - } catch (std::exception& e) { + } catch (std::exception &e) { lua_pushstring(L, e.what()); - } catch (...) { - lua_pushliteral(L, "caught (...)"); } return lua_error(L); // Rethrow as a Lua error. } -void script_error(lua_State *L) +/* + * Note that we can't get tracebacks for LUA_ERRMEM or LUA_ERRERR (without + * hacking Lua internals). For LUA_ERRMEM, this is because memory errors will + * not execute the the error handler, and by the time lua_pcall returns the + * execution stack will have already been unwound. For LUA_ERRERR, there was + * another error while trying to generate a backtrace from a LUA_ERRRUN. It is + * presumed there is an error with the internal Lua state and thus not possible + * to gather a coherent backtrace. Realistically, the best we can do here is + * print which C function performed the failing pcall. + */ +void script_error(lua_State *L, int pcall_result, const char *mod, const char *fxn) { - const char *s = lua_tostring(L, -1); - std::string str(s ? s : ""); - throw LuaError(str); + if (pcall_result == 0) + return; + + const char *err_type; + switch (pcall_result) { + case LUA_ERRRUN: + err_type = "Runtime"; + break; + case LUA_ERRMEM: + err_type = "OOM"; + break; + case LUA_ERRERR: + err_type = "Double fault"; + break; + default: + err_type = "Unknown"; + } + + if (!mod) + mod = "??"; + + if (!fxn) + fxn = "??"; + + const char *err_descr = lua_tostring(L, -1); + if (!err_descr) + err_descr = "<no description>"; + + char buf[256]; + snprintf(buf, sizeof(buf), "%s error from mod '%s' in callback %s(): ", + err_type, mod, fxn); + + std::string err_msg(buf); + err_msg += err_descr; + + if (pcall_result == LUA_ERRMEM) { + err_msg += "\nCurrent Lua memory usage: " + + itos(lua_gc(L, LUA_GCCOUNT, 0) >> 10) + " MB"; + } + + throw LuaError(err_msg); } // Push the list of callbacks (a lua table). @@ -85,9 +130,10 @@ void script_error(lua_State *L) // - runs the callbacks // - replaces the table and arguments with the return value, // computed depending on mode -void script_run_callbacks(lua_State *L, int nargs, RunCallbacksMode mode) +void script_run_callbacks_f(lua_State *L, int nargs, + RunCallbacksMode mode, const char *fxn) { - assert(lua_gettop(L) >= nargs + 1); + FATAL_ERROR_IF(lua_gettop(L) < nargs + 1, "Not enough arguments"); // Insert error handler lua_pushcfunction(L, script_error_handler); @@ -107,14 +153,14 @@ void script_run_callbacks(lua_State *L, int nargs, RunCallbacksMode mode) // Stack now looks like this: // ... <error handler> <run_callbacks> <table> <mode> <arg#1> <arg#2> ... <arg#n> - if (lua_pcall(L, nargs + 2, 1, errorhandler)) { - script_error(L); - } + int result = lua_pcall(L, nargs + 2, 1, errorhandler); + if (result != 0) + script_error(L, result, NULL, fxn); lua_remove(L, -2); // Remove error handler } -void log_deprecated(lua_State *L, std::string message) +void log_deprecated(lua_State *L, const std::string &message) { static bool configured = false; static bool dolog = false; @@ -125,8 +171,7 @@ void log_deprecated(lua_State *L, std::string message) std::string value = g_settings->get("deprecated_lua_api_handling"); if (value == "log") { dolog = true; - } - if (value == "error") { + } else if (value == "error") { dolog = true; doerror = true; } @@ -134,11 +179,10 @@ void log_deprecated(lua_State *L, std::string message) if (doerror) { if (L != NULL) { - script_error(L); + script_error(L, LUA_ERRRUN, NULL, NULL); } else { - /* As of april 2014 assert is not optimized to nop in release builds - * therefore this is correct. */ - assert("Can't do a scripterror for this deprecated message, so exit completely!"); + FATAL_ERROR("Can't do a scripterror for this deprecated message, " + "so exit completely!"); } } diff --git a/src/script/common/c_internal.h b/src/script/common/c_internal.h index eb9181b09..ecb514c8f 100644 --- a/src/script/common/c_internal.h +++ b/src/script/common/c_internal.h @@ -34,6 +34,16 @@ extern "C" { #include "common/c_types.h" +#define PCALL_RESL(L, RES) do { \ + int result_ = (RES); \ + if (result_ != 0) { \ + script_error((L), result_, NULL, __FUNCTION__); \ + } \ +} while (0) + +#define script_run_callbacks(L, nargs, mode) \ + script_run_callbacks_f((L), (nargs), (mode), __FUNCTION__) + // What script_run_callbacks does with the return values of callbacks. // Regardless of the mode, if only one callback is defined, // its return value is the total return value. @@ -67,8 +77,9 @@ enum RunCallbacksMode std::string script_get_backtrace(lua_State *L); int script_error_handler(lua_State *L); int script_exception_wrapper(lua_State *L, lua_CFunction f); -void script_error(lua_State *L); -void script_run_callbacks(lua_State *L, int nargs, RunCallbacksMode mode); -void log_deprecated(lua_State *L, std::string message); +void script_error(lua_State *L, int pcall_result, const char *mod, const char *fxn); +void script_run_callbacks_f(lua_State *L, int nargs, + RunCallbacksMode mode, const char *fxn); +void log_deprecated(lua_State *L, const std::string &message); #endif /* C_INTERNAL_H_ */ |