From 2a01050a0cf0826f25240e2cb407535394ee360f Mon Sep 17 00:00:00 2001 From: kwolekr Date: Sun, 9 Feb 2014 12:38:50 -0500 Subject: [PATCH] Add capability to read table flag fields from Lua API --- doc/lua_api.txt | 22 ++++++++++++++++++ src/porting.h | 5 ++++ src/script/common/c_content.cpp | 41 +++++++++++++++++++++++++++++++-- src/script/common/c_content.h | 3 +++ src/script/lua_api/l_mapgen.cpp | 1 - src/util/string.cpp | 13 +++++++++++ src/util/string.h | 1 + 7 files changed, 83 insertions(+), 3 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index aef17bec8..eb2820e27 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -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): diff --git a/src/porting.h b/src/porting.h index 4cfac21d1..0f2007fa7 100644 --- a/src/porting.h +++ b/src/porting.h @@ -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 diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index d1e182f9f..4e26dc245 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -842,8 +842,45 @@ void push_hit_params(lua_State *L,const HitParams ¶ms) 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; } /******************************************************************************/ diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h index a89de1aad..61617d7ab 100644 --- a/src/script/common/c_content.h +++ b/src/script/common/c_content.h @@ -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 &items); diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index 4c6bca74e..2e6d848b3 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -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); diff --git a/src/util/string.cpp b/src/util/string.cpp index afe40610c..a3888c9ce 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -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; diff --git a/src/util/string.h b/src/util/string.h index d6a9926ab..9bb89f14a 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -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);