]> git.lizzy.rs Git - minetest.git/blobdiff - src/script/common/c_content.cpp
Add particle animation, glow
[minetest.git] / src / script / common / c_content.cpp
index f9370c4dc6984ca9e6acacf5172658886912b985..84af4583b9de7d2962d1b2d18eccfc88f18a6302 100644 (file)
@@ -33,12 +33,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "porting.h"
 #include "mg_schematic.h"
 #include "noise.h"
-#include "json/json.h"
+#include <json/json.h>
 
 struct EnumString es_TileAnimationType[] =
 {
        {TAT_NONE, "none"},
        {TAT_VERTICAL_FRAMES, "vertical_frames"},
+       {TAT_SHEET_2D, "sheet_2d"},
        {0, NULL},
 };
 
@@ -65,9 +66,8 @@ ItemDefinition read_item_definition(lua_State* L,int index,
        }
        lua_pop(L, 1);
 
-       def.stack_max = getintfield_default(L, index, "stack_max", def.stack_max);
-       if(def.stack_max == 0)
-               def.stack_max = 1;
+       int stack_max = getintfield_default(L, index, "stack_max", def.stack_max);
+       def.stack_max = rangelim(stack_max, 1, U16_MAX);
 
        lua_getfield(L, index, "on_use");
        def.usable = lua_isfunction(L, -1);
@@ -209,12 +209,14 @@ void read_object_properties(lua_State *L, int index,
                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);
 }
 
 /******************************************************************************/
@@ -277,9 +279,12 @@ void push_object_properties(lua_State *L, ObjectProperties *prop)
        lua_setfield(L, -2, "backface_culling");
        lua_pushlstring(L, prop->nametag.c_str(), prop->nametag.size());
        lua_setfield(L, -2, "nametag");
-       lua_newtable(L);
        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");
 }
 
 /******************************************************************************/
@@ -289,41 +294,47 @@ 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))
        {
-               // {name="default_lava.png", animation={}}
+               // name="default_lava.png"
                tiledef.name = "";
                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(
                        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);
-                       tiledef.animation.aspect_w =
-                               getintfield_default(L, -1, "aspect_w", 16);
-                       tiledef.animation.aspect_h =
-                               getintfield_default(L, -1, "aspect_h", 16);
-                       tiledef.animation.length =
-                               getfloatfield_default(L, -1, "length", 1.0);
-               }
+               tiledef.animation = read_animation_definition(L, -1);
                lua_pop(L, 1);
        }
 
@@ -479,6 +490,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);
@@ -503,6 +516,12 @@ ContentFeatures read_content_features(lua_State *L, int index)
        // Amount of light the node emits
        f.light_source = getintfield_default(L, index,
                        "light_source", f.light_source);
+       if (f.light_source > LIGHT_MAX) {
+               warningstream << "Node " << f.name.c_str()
+                       << " had greater light_source than " << LIGHT_MAX
+                       << ", it was reduced." << std::endl;
+               f.light_source = LIGHT_MAX;
+       }
        f.damage_per_second = getintfield_default(L, index,
                        "damage_per_second", f.damage_per_second);
 
@@ -511,6 +530,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);
@@ -603,25 +662,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;
 }
@@ -760,20 +825,18 @@ void push_tool_capabilities(lua_State *L,
                // Create groupcaps table
                lua_newtable(L);
                // For each groupcap
-               for(std::map<std::string, ToolGroupCap>::const_iterator
-                               i = toolcap.groupcaps.begin(); i != toolcap.groupcaps.end(); i++){
+               for (ToolGCMap::const_iterator i = toolcap.groupcaps.begin();
+                       i != toolcap.groupcaps.end(); i++) {
                        // Create groupcap table
                        lua_newtable(L);
                        const std::string &name = i->first;
                        const ToolGroupCap &groupcap = i->second;
                        // Create subtable "times"
                        lua_newtable(L);
-                       for(std::map<int, float>::const_iterator
-                                       i = groupcap.times.begin(); i != groupcap.times.end(); i++){
-                               int rating = i->first;
-                               float time = i->second;
-                               lua_pushinteger(L, rating);
-                               lua_pushnumber(L, time);
+                       for (UNORDERED_MAP<int, float>::const_iterator
+                                       i = groupcap.times.begin(); i != groupcap.times.end(); i++) {
+                               lua_pushinteger(L, i->first);
+                               lua_pushnumber(L, i->second);
                                lua_settable(L, -3);
                        }
                        // Set subtable "times"
@@ -789,8 +852,8 @@ void push_tool_capabilities(lua_State *L,
                //Create damage_groups table
                lua_newtable(L);
                // For each damage group
-               for(std::map<std::string, s16>::const_iterator
-                               i = toolcap.damageGroups.begin(); i != toolcap.damageGroups.end(); i++){
+               for (DamageGroup::const_iterator i = toolcap.damageGroups.begin();
+                       i != toolcap.damageGroups.end(); i++) {
                        // Create damage group table
                        lua_pushinteger(L, i->second);
                        lua_setfield(L, -2, i->first.c_str());
@@ -841,6 +904,41 @@ void read_inventory_list(lua_State *L, int tableindex,
        }
 }
 
+/******************************************************************************/
+struct TileAnimationParams read_animation_definition(lua_State *L, int index)
+{
+       if(index < 0)
+               index = lua_gettop(L) + 1 + index;
+
+       struct TileAnimationParams anim;
+       anim.type = TAT_NONE;
+       if (!lua_istable(L, index))
+               return anim;
+
+       anim.type = (TileAnimationType)
+               getenumfield(L, index, "type", es_TileAnimationType,
+               TAT_NONE);
+       if (anim.type == TAT_VERTICAL_FRAMES) {
+               // {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}
+               anim.vertical_frames.aspect_w =
+                       getintfield_default(L, index, "aspect_w", 16);
+               anim.vertical_frames.aspect_h =
+                       getintfield_default(L, index, "aspect_h", 16);
+               anim.vertical_frames.length =
+                       getfloatfield_default(L, index, "length", 1.0);
+       } else if (anim.type == TAT_SHEET_2D) {
+               // {type="sheet_2d", frames_w=5, frames_h=3, frame_length=0.5}
+               getintfield(L, index, "frames_w",
+                       anim.sheet_2d.frames_w);
+               getintfield(L, index, "frames_h",
+                       anim.sheet_2d.frames_h);
+               getfloatfield(L, index, "frame_length",
+                       anim.sheet_2d.frame_length);
+       }
+
+       return anim;
+}
+
 /******************************************************************************/
 ToolCapabilities read_tool_capabilities(
                lua_State *L, int table)
@@ -996,8 +1094,7 @@ void push_flags_string(lua_State *L, FlagDesc *flagdesc, u32 flags, u32 flagmask
 /******************************************************************************/
 
 /******************************************************************************/
-void read_groups(lua_State *L, int index,
-               std::map<std::string, int> &result)
+void read_groups(lua_State *L, int index, ItemGroupList &result)
 {
        if (!lua_istable(L,index))
                return;
@@ -1016,11 +1113,10 @@ void read_groups(lua_State *L, int index,
 }
 
 /******************************************************************************/
-void push_groups(lua_State *L, const std::map<std::string, int> &groups)
+void push_groups(lua_State *L, const ItemGroupList &groups)
 {
        lua_newtable(L);
-       std::map<std::string, int>::const_iterator it;
-       for (it = groups.begin(); it != groups.end(); ++it) {
+       for (ItemGroupList::const_iterator it = groups.begin(); it != groups.end(); ++it) {
                lua_pushnumber(L, it->second);
                lua_setfield(L, -2, it->first.c_str());
        }
@@ -1180,8 +1276,13 @@ static bool push_json_value_helper(lua_State *L, const Json::Value &value,
                        lua_newtable(L);
                        for (Json::Value::const_iterator it = value.begin();
                                        it != value.end(); ++it) {
+#ifndef JSONCPP_STRING
                                const char *str = it.memberName();
                                lua_pushstring(L, str ? str : "");
+#else
+                               std::string str = it.name();
+                               lua_pushstring(L, str.c_str());
+#endif
                                push_json_value_helper(L, *it, nullindex);
                                lua_rawset(L, -3);
                        }