aboutsummaryrefslogtreecommitdiff
path: root/src/script/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/script/common')
-rw-r--r--src/script/common/c_content.cpp179
-rw-r--r--src/script/common/c_converter.cpp9
-rw-r--r--src/script/common/c_converter.h2
-rw-r--r--src/script/common/c_internal.cpp49
-rw-r--r--src/script/common/c_internal.h25
-rw-r--r--src/script/common/c_types.h4
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) {}
};