diff options
Diffstat (limited to 'src/script/common')
-rw-r--r-- | src/script/common/c_content.cpp | 179 | ||||
-rw-r--r-- | src/script/common/c_converter.cpp | 9 | ||||
-rw-r--r-- | src/script/common/c_converter.h | 2 | ||||
-rw-r--r-- | src/script/common/c_internal.cpp | 49 | ||||
-rw-r--r-- | src/script/common/c_internal.h | 25 | ||||
-rw-r--r-- | src/script/common/c_types.h | 4 |
6 files changed, 196 insertions, 72 deletions
diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 3754fc2ff..06e20c2a0 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -76,7 +76,7 @@ ItemDefinition read_item_definition(lua_State* L,int index, getboolfield(L, index, "liquids_pointable", def.liquids_pointable); warn_if_field_exists(L, index, "tool_digging_properties", - "deprecated: use tool_capabilities"); + "Deprecated; use tool_capabilities"); lua_getfield(L, index, "tool_capabilities"); if(lua_istable(L, -1)){ @@ -100,6 +100,9 @@ ItemDefinition read_item_definition(lua_State* L,int index, lua_getfield(L, -1, "place"); read_soundspec(L, -1, def.sound_place); lua_pop(L, 1); + lua_getfield(L, -1, "place_failed"); + read_soundspec(L, -1, def.sound_place_failed); + lua_pop(L, 1); } lua_pop(L, 1); @@ -197,6 +200,23 @@ void read_object_properties(lua_State *L, int index, prop->automatic_face_movement_dir_offset = 0.0; } lua_pop(L, 1); + getboolfield(L, -1, "backface_culling", prop->backface_culling); + + getstringfield(L, -1, "nametag", prop->nametag); + lua_getfield(L, -1, "nametag_color"); + if (!lua_isnil(L, -1)) { + video::SColor color = prop->nametag_color; + if (read_color(L, -1, &color)) + prop->nametag_color = color; + } + lua_pop(L, 1); + + lua_getfield(L, -1, "automatic_face_movement_max_rotation_per_sec"); + if (lua_isnumber(L, -1)) { + prop->automatic_face_movement_max_rotation_per_sec = luaL_checknumber(L, -1); + } + lua_pop(L, 1); + getstringfield(L, -1, "infotext", prop->infotext); } /******************************************************************************/ @@ -255,6 +275,16 @@ void push_object_properties(lua_State *L, ObjectProperties *prop) else lua_pushboolean(L, false); lua_setfield(L, -2, "automatic_face_movement_dir"); + lua_pushboolean(L, prop->backface_culling); + lua_setfield(L, -2, "backface_culling"); + lua_pushlstring(L, prop->nametag.c_str(), prop->nametag.size()); + lua_setfield(L, -2, "nametag"); + push_ARGB8(L, prop->nametag_color); + lua_setfield(L, -2, "nametag_color"); + lua_pushnumber(L, prop->automatic_face_movement_max_rotation_per_sec); + lua_setfield(L, -2, "automatic_face_movement_max_rotation_per_sec"); + lua_pushlstring(L, prop->infotext.c_str(), prop->infotext.size()); + lua_setfield(L, -2, "infotext"); } /******************************************************************************/ @@ -264,14 +294,31 @@ TileDef read_tiledef(lua_State *L, int index, u8 drawtype) index = lua_gettop(L) + 1 + index; TileDef tiledef; - bool default_tiling = (drawtype == NDT_PLANTLIKE || drawtype == NDT_FIRELIKE) - ? false : true; + + bool default_tiling = true; + bool default_culling = true; + switch (drawtype) { + case NDT_PLANTLIKE: + case NDT_FIRELIKE: + default_tiling = false; + // "break" is omitted here intentionaly, as PLANTLIKE + // FIRELIKE drawtype both should default to having + // backface_culling to false. + case NDT_MESH: + case NDT_LIQUID: + default_culling = false; + break; + default: + break; + } + // 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; + tiledef.backface_culling = default_culling; } else if(lua_istable(L, index)) { @@ -280,7 +327,7 @@ TileDef read_tiledef(lua_State *L, int index, u8 drawtype) 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", default_culling); tiledef.tileable_horizontal = getboolfield_default( L, index, "tileable_horizontal", default_tiling); tiledef.tileable_vertical = getboolfield_default( @@ -427,17 +474,17 @@ ContentFeatures read_content_features(lua_State *L, int index) // Warn about some deprecated fields warn_if_field_exists(L, index, "wall_mounted", - "deprecated: use paramtype2 = 'wallmounted'"); + "Deprecated; use paramtype2 = 'wallmounted'"); warn_if_field_exists(L, index, "light_propagates", - "deprecated: determined from paramtype"); + "Deprecated; determined from paramtype"); warn_if_field_exists(L, index, "dug_item", - "deprecated: use 'drop' field"); + "Deprecated; use 'drop' field"); warn_if_field_exists(L, index, "extra_dug_item", - "deprecated: use 'drop' field"); + "Deprecated; use 'drop' field"); warn_if_field_exists(L, index, "extra_dug_item_rarity", - "deprecated: use 'drop' field"); + "Deprecated; use 'drop' field"); warn_if_field_exists(L, index, "metadata_name", - "deprecated: use on_add and metadata callbacks"); + "Deprecated; use on_add and metadata callbacks"); // True for all ground-like things like stone and mud, false for eg. trees getboolfield(L, index, "is_ground_content", f.is_ground_content); @@ -454,6 +501,8 @@ ContentFeatures read_content_features(lua_State *L, int index) getboolfield(L, index, "climbable", f.climbable); // Player can build on these getboolfield(L, index, "buildable_to", f.buildable_to); + // Liquids flow into and replace node + getboolfield(L, index, "floodable", f.floodable); // Whether the node is non-liquid, source liquid or flowing liquid f.liquid_type = (LiquidType)getenumfield(L, index, "liquidtype", ScriptApiNode::es_LiquidType, LIQUID_NONE); @@ -486,6 +535,46 @@ ContentFeatures read_content_features(lua_State *L, int index) f.node_box = read_nodebox(L, -1); lua_pop(L, 1); + lua_getfield(L, index, "connects_to"); + if (lua_istable(L, -1)) { + int table = lua_gettop(L); + lua_pushnil(L); + while (lua_next(L, table) != 0) { + // Value at -1 + f.connects_to.push_back(lua_tostring(L, -1)); + lua_pop(L, 1); + } + } + lua_pop(L, 1); + + lua_getfield(L, index, "connect_sides"); + if (lua_istable(L, -1)) { + int table = lua_gettop(L); + lua_pushnil(L); + while (lua_next(L, table) != 0) { + // Value at -1 + std::string side(lua_tostring(L, -1)); + // Note faces are flipped to make checking easier + if (side == "top") + f.connect_sides |= 2; + else if (side == "bottom") + f.connect_sides |= 1; + else if (side == "front") + f.connect_sides |= 16; + else if (side == "left") + f.connect_sides |= 32; + else if (side == "back") + f.connect_sides |= 4; + else if (side == "right") + f.connect_sides |= 8; + else + warningstream << "Unknown value for \"connect_sides\": " + << side << std::endl; + lua_pop(L, 1); + } + } + lua_pop(L, 1); + lua_getfield(L, index, "selection_box"); if(lua_istable(L, -1)) f.selection_box = read_nodebox(L, -1); @@ -578,25 +667,31 @@ NodeBox read_nodebox(lua_State *L, int index) nodebox.type = (NodeBoxType)getenumfield(L, index, "type", ScriptApiNode::es_NodeBoxType, NODEBOX_REGULAR); - lua_getfield(L, index, "fixed"); - if(lua_istable(L, -1)) - nodebox.fixed = read_aabb3f_vector(L, -1, BS); - lua_pop(L, 1); - - lua_getfield(L, index, "wall_top"); - if(lua_istable(L, -1)) - nodebox.wall_top = read_aabb3f(L, -1, BS); - lua_pop(L, 1); - - lua_getfield(L, index, "wall_bottom"); - if(lua_istable(L, -1)) - nodebox.wall_bottom = read_aabb3f(L, -1, BS); - lua_pop(L, 1); - - lua_getfield(L, index, "wall_side"); - if(lua_istable(L, -1)) - nodebox.wall_side = read_aabb3f(L, -1, BS); - lua_pop(L, 1); +#define NODEBOXREAD(n, s) \ + do { \ + lua_getfield(L, index, (s)); \ + if (lua_istable(L, -1)) \ + (n) = read_aabb3f(L, -1, BS); \ + lua_pop(L, 1); \ + } while (0) + +#define NODEBOXREADVEC(n, s) \ + do { \ + lua_getfield(L, index, (s)); \ + if (lua_istable(L, -1)) \ + (n) = read_aabb3f_vector(L, -1, BS); \ + lua_pop(L, 1); \ + } while (0) + NODEBOXREADVEC(nodebox.fixed, "fixed"); + NODEBOXREAD(nodebox.wall_top, "wall_top"); + NODEBOXREAD(nodebox.wall_bottom, "wall_bottom"); + NODEBOXREAD(nodebox.wall_side, "wall_side"); + NODEBOXREADVEC(nodebox.connect_top, "connect_top"); + NODEBOXREADVEC(nodebox.connect_bottom, "connect_bottom"); + NODEBOXREADVEC(nodebox.connect_front, "connect_front"); + NODEBOXREADVEC(nodebox.connect_left, "connect_left"); + NODEBOXREADVEC(nodebox.connect_back, "connect_back"); + NODEBOXREADVEC(nodebox.connect_right, "connect_right"); } return nodebox; } @@ -639,14 +734,13 @@ void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef) /******************************************************************************/ void warn_if_field_exists(lua_State *L, int table, - const char *fieldname, const std::string &message) + const char *name, const std::string &message) { - lua_getfield(L, table, fieldname); - if(!lua_isnil(L, -1)){ -//TODO find way to access backtrace fct from here - // infostream<<script_get_backtrace(L)<<std::endl; - infostream<<"WARNING: field \""<<fieldname<<"\": " - <<message<<std::endl; + lua_getfield(L, table, name); + if (!lua_isnil(L, -1)) { + warningstream << "Field \"" << name << "\": " + << message << std::endl; + infostream << script_get_backtrace(L) << std::endl; } lua_pop(L, 1); } @@ -705,7 +799,7 @@ ItemStack read_item(lua_State* L, int index,Server* srv) } catch(SerializationError &e) { - infostream<<"WARNING: unable to create item from itemstring" + warningstream<<"unable to create item from itemstring" <<": "<<itemstring<<std::endl; return ItemStack(); } @@ -840,14 +934,14 @@ ToolCapabilities read_tool_capabilities( getintfield(L, table_groupcap, "uses", groupcap.uses); // DEPRECATED: maxwear float maxwear = 0; - if(getfloatfield(L, table_groupcap, "maxwear", maxwear)){ - if(maxwear != 0) + if (getfloatfield(L, table_groupcap, "maxwear", maxwear)){ + if (maxwear != 0) groupcap.uses = 1.0/maxwear; else groupcap.uses = 0; - infostream<<script_get_backtrace(L)<<std::endl; - infostream<<"WARNING: field \"maxwear\" is deprecated; " - <<"should replace with uses=1/maxwear"<<std::endl; + warningstream << "Field \"maxwear\" is deprecated; " + << "replace with uses=1/maxwear" << std::endl; + infostream << script_get_backtrace(L) << std::endl; } // Read "times" table lua_getfield(L, table_groupcap, "times"); @@ -1232,4 +1326,3 @@ void read_json_value(lua_State *L, Json::Value &root, int index, u8 recursion) } lua_pop(L, 1); // Pop value } - diff --git a/src/script/common/c_converter.cpp b/src/script/common/c_converter.cpp index f1d3cc421..55c4a5f5a 100644 --- a/src/script/common/c_converter.cpp +++ b/src/script/common/c_converter.cpp @@ -517,6 +517,15 @@ bool getboolfield_default(lua_State *L, int table, return result; } +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); +} + void setintfield(lua_State *L, int table, const char *fieldname, int value) { diff --git a/src/script/common/c_converter.h b/src/script/common/c_converter.h index 18a045d2a..eefac0ed7 100644 --- a/src/script/common/c_converter.h +++ b/src/script/common/c_converter.h @@ -69,6 +69,8 @@ bool getfloatfield(lua_State *L, int table, std::string checkstringfield(lua_State *L, int table, const char *fieldname); +void setstringfield(lua_State *L, int table, + const char *fieldname, const char *value); void setintfield(lua_State *L, int table, const char *fieldname, int value); void setfloatfield(lua_State *L, int table, diff --git a/src/script/common/c_internal.cpp b/src/script/common/c_internal.cpp index 2a10ce0f2..b349f9dd1 100644 --- a/src/script/common/c_internal.cpp +++ b/src/script/common/c_internal.cpp @@ -136,61 +136,56 @@ void script_run_callbacks_f(lua_State *L, int nargs, FATAL_ERROR_IF(lua_gettop(L) < nargs + 1, "Not enough arguments"); // Insert error handler - lua_pushcfunction(L, script_error_handler); - int errorhandler = lua_gettop(L) - nargs - 1; - lua_insert(L, errorhandler); + PUSH_ERROR_HANDLER(L); + int error_handler = lua_gettop(L) - nargs - 1; + lua_insert(L, error_handler); // Insert run_callbacks between error handler and table lua_getglobal(L, "core"); lua_getfield(L, -1, "run_callbacks"); lua_remove(L, -2); - lua_insert(L, errorhandler + 1); + lua_insert(L, error_handler + 1); // Insert mode after table lua_pushnumber(L, (int) mode); - lua_insert(L, errorhandler + 3); + lua_insert(L, error_handler + 3); // Stack now looks like this: // ... <error handler> <run_callbacks> <table> <mode> <arg#1> <arg#2> ... <arg#n> - int result = lua_pcall(L, nargs + 2, 1, errorhandler); + int result = lua_pcall(L, nargs + 2, 1, error_handler); if (result != 0) script_error(L, result, NULL, fxn); - lua_remove(L, -2); // Remove error handler + lua_remove(L, error_handler); } void log_deprecated(lua_State *L, const std::string &message) { static bool configured = false; - static bool dolog = false; - static bool doerror = false; + static bool do_log = false; + static bool do_error = false; - // performance optimization to not have to read and compare setting for every logline + // Only read settings on first call if (!configured) { std::string value = g_settings->get("deprecated_lua_api_handling"); if (value == "log") { - dolog = true; + do_log = true; } else if (value == "error") { - dolog = true; - doerror = true; + do_log = true; + do_error = true; } } - if (doerror) { - if (L != NULL) { - script_error(L, LUA_ERRRUN, NULL, NULL); - } else { - FATAL_ERROR("Can't do a scripterror for this deprecated message, " - "so exit completely!"); - } - } - - if (dolog) { - /* abusing actionstream because of lack of file-only-logged loglevel */ - actionstream << message << std::endl; - if (L != NULL) { - actionstream << script_get_backtrace(L) << std::endl; + if (do_log) { + warningstream << message << std::endl; + // L can be NULL if we get called by log_deprecated(const std::string &msg) + // from scripting_game.cpp. + if (L) { + if (do_error) + script_error(L, LUA_ERRRUN, NULL, NULL); + else + infostream << script_get_backtrace(L) << std::endl; } } } diff --git a/src/script/common/c_internal.h b/src/script/common/c_internal.h index ecb514c8f..fc59b0e2e 100644 --- a/src/script/common/c_internal.h +++ b/src/script/common/c_internal.h @@ -34,6 +34,31 @@ extern "C" { #include "common/c_types.h" + +/* + Define our custom indices into the Lua registry table. + + Lua 5.2 and above define the LUA_RIDX_LAST macro. Only numbers above that + may be used for custom indices, anything else is reserved. + + Lua 5.1 / LuaJIT do not use any numeric indices (only string indices), + so we can use numeric indices freely. +*/ +#ifdef LUA_RIDX_LAST +#define CUSTOM_RIDX_BASE ((LUA_RIDX_LAST)+1) +#else +#define CUSTOM_RIDX_BASE 1 +#endif + +#define CUSTOM_RIDX_SCRIPTAPI (CUSTOM_RIDX_BASE) +#define CUSTOM_RIDX_GLOBALS_BACKUP (CUSTOM_RIDX_BASE + 1) +#define CUSTOM_RIDX_CURRENT_MOD_NAME (CUSTOM_RIDX_BASE + 2) +#define CUSTOM_RIDX_ERROR_HANDLER (CUSTOM_RIDX_BASE + 3) + +// Pushes the error handler onto the stack and returns its index +#define PUSH_ERROR_HANDLER(L) \ + (lua_rawgeti((L), LUA_REGISTRYINDEX, CUSTOM_RIDX_ERROR_HANDLER), lua_gettop((L))) + #define PCALL_RESL(L, RES) do { \ int result_ = (RES); \ if (result_ != 0) { \ diff --git a/src/script/common/c_types.h b/src/script/common/c_types.h index 706470737..056f30251 100644 --- a/src/script/common/c_types.h +++ b/src/script/common/c_types.h @@ -52,10 +52,10 @@ public: } }; -class LuaError : public ServerError +class LuaError : public ModError { public: - LuaError(const std::string &s) : ServerError(s) {} + LuaError(const std::string &s) : ModError(s) {} }; |