Add capability to read table flag fields from Lua API
authorkwolekr <kwolekr@minetest.net>
Sun, 9 Feb 2014 17:38:50 +0000 (12:38 -0500)
committerkwolekr <kwolekr@minetest.net>
Sun, 9 Feb 2014 17:44:31 +0000 (12:44 -0500)
doc/lua_api.txt
src/porting.h
src/script/common/c_content.cpp
src/script/common/c_content.h
src/script/lua_api/l_mapgen.cpp
src/util/string.cpp
src/util/string.h

index aef17bec8e2cb49e1556788bada8f8b9f05bc98b..eb2820e2720ba87d443043241a4b7e6c4fc04877 100644 (file)
@@ -410,6 +410,7 @@ All default ores are of the uniformly-distributed scatter type.
 
 Ore attributes
 -------------------
+See section Flag Specifier Format.
 Currently supported flags:  absheight
  - absheight
     Also produce this same ore between the height range of -height_max and -height_min.
@@ -451,6 +452,7 @@ Important note: Node aliases cannot be used for a raw schematic provided when re
 
 Schematic attributes
 ---------------------
+See section Flag Specifier Format.
 Currently supported flags:  place_center_x, place_center_y, place_center_z
  - place_center_x
     Placement of this decoration is centered along the X axis.
@@ -525,6 +527,26 @@ pointed_thing:
   {type="node", under=pos, above=pos}
   {type="object", ref=ObjectRef}
 
+Flag Specifier Format
+-----------------------
+Flags using the standardized flag specifier format can be specified in either of two ways, by string or table.
+The string format is a comma-delimited set of flag names; whitespace and unrecognized flag fields are ignored.
+Specifying a flag in the string sets the flag, and specifying a flag prefixed by the string "no" explicitly
+clears the flag from whatever the default may be.
+In addition to the standard string flag format, the schematic flags field can also be a table of flag names
+to boolean values representing whether or not the flag is set.  Additionally, if a field with the flag name
+prefixed with "no" is present, mapped to a boolean of any value, the specified flag is unset.
+
+e.g. A flag field of value
+  {place_center_x = true, place_center_y=false, place_center_z=true}
+is equivalent to
+  {place_center_x = true, noplace_center_y=true, place_center_z=true}
+which is equivalent to
+  "place_center_x, noplace_center_y, place_center_z"
+or even
+  "place_center_x, place_center_z"
+since, by default, no schematic attributes are set.
+
 Items
 ------
 Node (register_node):
index 4cfac21d11d4ab5a492ef5758d2b10a2ea8238fa..0f2007fa795b21ecd7836e5c433a7210c057ec39 100644 (file)
@@ -88,6 +88,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
        #define strtoull(x, y, z) _strtoui64(x, y, z)
        #define strcasecmp(x, y) stricmp(x, y)
        #define strncasecmp(x, y, n) strnicmp(x, y, n)
+
+       // We can't simply alias strlcpy() to MSVC's strcpy_s(), since strcpy_s
+       // by default raises an assertion error and aborts the program if the
+       // buffer is too small.  So we need to define our own.
+       #define strlcpy(x, y, n) mystrlcpy(x, y, n)
 #else
        #define ALIGNOF(x) __alignof__(x)
 #endif
index d1e182f9f480bb67870cf94c0d8bb6eec13e64fe..4e26dc2454bf0df739e628ddf3314284cf78a31a 100644 (file)
@@ -842,8 +842,45 @@ void push_hit_params(lua_State *L,const HitParams &params)
 u32 getflagsfield(lua_State *L, int table, const char *fieldname,
        FlagDesc *flagdesc, u32 *flagmask)
 {
-       std::string flagstring = getstringfield_default(L, table, fieldname, "");
-       return readFlagString(flagstring, flagdesc, flagmask);
+       u32 flags = 0;
+       
+       lua_getfield(L, table, fieldname);
+
+       if (lua_isstring(L, -1)) {
+               std::string flagstr = lua_tostring(L, -1);
+               flags = readFlagString(flagstr, flagdesc, flagmask);
+       } else if (lua_istable(L, -1)) {
+               flags = read_flags_table(L, -1, flagdesc, flagmask);
+       }
+
+       lua_pop(L, 1);
+
+       return flags;
+}
+
+u32 read_flags_table(lua_State *L, int table, FlagDesc *flagdesc, u32 *flagmask)
+{
+       u32 flags = 0, mask = 0;
+       char fnamebuf[64] = "no";
+
+       for (int i = 0; flagdesc[i].name; i++) {
+               bool result;
+
+               if (getboolfield(L, table, flagdesc[i].name, result)) {
+                       mask |= flagdesc[i].flag;
+                       if (result)
+                               flags |= flagdesc[i].flag;
+               }
+
+               strlcpy(fnamebuf + 2, flagdesc[i].name, sizeof(fnamebuf) - 2);
+               if (getboolfield(L, table, fnamebuf, result))
+                       mask |= flagdesc[i].flag;
+       }
+
+       if (flagmask)
+               *flagmask = mask;
+
+       return flags;
 }
 
 /******************************************************************************/
index a89de1aadbfc38ab4cb8ae41a11ef69f9618614c..61617d7abaeecca219f4d04a27c9787171e0297e 100644 (file)
@@ -123,6 +123,9 @@ u32                getflagsfield             (lua_State *L, int table,
                                               const char *fieldname,
                                               FlagDesc *flagdesc, u32 *flagmask);
 
+u32                read_flags_table          (lua_State *L, int table,
+                                              FlagDesc *flagdesc, u32 *flagmask);
+
 void               push_items                (lua_State *L,
                                               const std::vector<ItemStack> &items);
 
index 4c6bca74e2756a1d2b18ccff039b9b995f102ca3..2e6d848b359746c05b8edcbbba8426435a74dc47 100644 (file)
@@ -456,7 +456,6 @@ int ModApiMapgen::l_register_ore(lua_State *L)
        ore->height_max     = getintfield_default(L, index, "height_max", 0);
        ore->flags          = getflagsfield(L, index, "flags", flagdesc_ore, NULL);
        ore->nthresh        = getfloatfield_default(L, index, "noise_threshhold", 0.);
-
        lua_getfield(L, index, "wherein");
        if (lua_istable(L, -1)) {
                int  i = lua_gettop(L);
index afe40610c02f27617136ccb66b14ca8bad405905..a3888c9ce9d16767059437e27721ee12b759e02a 100644 (file)
@@ -163,6 +163,19 @@ std::string writeFlagString(u32 flags, FlagDesc *flagdesc, u32 flagmask)
        return result;
 }
 
+size_t mystrlcpy(char *dst, const char *src, size_t size)
+{
+       size_t srclen  = strlen(src) + 1;
+       size_t copylen = MYMIN(srclen, size);
+
+       if (copylen > 0) {
+               memcpy(dst, src, copylen);
+               dst[copylen - 1] = '\0';
+       }
+
+       return srclen;
+}
+
 char *mystrtok_r(char *s, const char *sep, char **lasts)
 {
        char *t;
index d6a9926ab8df67ebeb5ed8e114e0d935079b68a6..9bb89f14aaac6d91894ae245d991bd19741b023b 100644 (file)
@@ -321,6 +321,7 @@ std::string urlencode(std::string str);
 std::string urldecode(std::string str);
 u32 readFlagString(std::string str, FlagDesc *flagdesc, u32 *flagmask);
 std::string writeFlagString(u32 flags, FlagDesc *flagdesc, u32 flagmask);
+size_t mystrlcpy(char *dst, const char *src, size_t size);
 char *mystrtok_r(char *s, const char *sep, char **lasts);
 u64 read_seed(const char *str);