Jelajahi Sumber

Make flag strings clear specified flag with 'no' prefix

Remove flagmask field from set_mapgen_params table
Add small bits of needed documentation
kwolekr 10 tahun lalu
induk
melakukan
83bafbe08b

+ 3 - 4
doc/lua_api.txt

@@ -1360,11 +1360,10 @@ minetest.get_mapgen_object(objectname)
 minetest.set_mapgen_params(MapgenParams)
 ^ Set map generation parameters
 ^ Function cannot be called after the registration period; only initialization and on_mapgen_init
-^ Takes a table as an argument with the fields mgname, seed, water_level, flags, and flagmask.
+^ Takes a table as an argument with the fields mgname, seed, water_level, and flags.
 ^ Leave field unset to leave that parameter unchanged
-^ flagmask field must be set to all mapgen flags that are being modified
-^ flags contains only the flags that are being set
-^ flags and flagmask are in the same format and have the same options as 'mgflags' in minetest.conf
+^ flags contains a comma-delimited string of flags to set, or if the prefix "no" is attached, clears instead.
+^ flags is in the same format and has the same options as 'mg_flags' in minetest.conf
 minetest.clear_objects()
 ^ clear all objects in the environments
 minetest.line_of_sight(pos1, pos2, stepsize) -> true/false, pos

+ 6 - 4
minetest.conf.example

@@ -381,10 +381,12 @@
 #water_level = 1
 # Size of chunks to be generated.
 #chunksize = 5
-# Map generation attributes.  Currently supported: trees, caves, flat, dungeons, nolight
+# Map generation attributes.  Currently supported: trees, caves, flat, dungeons, light
+# Flags that are not specified in the flag string are not modified from the default.
+# To explicitly turn off a flag, prepend "no" to the beginning, e.g. nolight.
 #mg_flags = trees, caves
-# Map generation attributes specific to Mapgen V6.  Currently supported: v6_biome_blend, v6_jungles, v6_nomudflow
-#mgv6_spflags = v6_biome_blend
+# Map generation attributes specific to Mapgen V6.  Currently supported: biomeblend, jungles, mudflow
+#mgv6_spflags = biomeblend
 # How large deserts and beaches are
 #mgv6_freq_desert = 0.45
 #mgv6_freq_beach = 0.15
@@ -402,7 +404,7 @@
 #mgv6_np_trees = 0, 1, (125, 125, 125), 2, 4, 0.66
 #mgv6_np_apple_trees = 0, 1, (100, 100, 100), 342902, 3, 0.45
 
-#mgv7_spflags = v7_mountains, v7_ridges
+#mgv7_spflags = mountains, ridges
 #mgv7_np_terrain = 10, 12, (350, 350, 350), 82341, 5, 0.6
 #mgv7_np_bgroup = 0.5, 0.3125, (350, 350, 350), 5923, 2, 0.6
 #mgv7_np_heat = 25, 50, (500, 500, 500), 35293, 1, 0

+ 1 - 1
src/defaultsettings.cpp

@@ -249,7 +249,7 @@ void set_default_settings(Settings *settings)
 	settings->setDefault("mg_name", "v6");
 	settings->setDefault("water_level", "1");
 	settings->setDefault("chunksize", "5");
-	settings->setDefault("mg_flags", "trees, caves");
+	settings->setDefault("mg_flags", "");
 
 	settings->setDefault("mgmath_generator", "mandelbox");
 

+ 1 - 2
src/emerge.cpp

@@ -372,7 +372,6 @@ void EmergeManager::loadParamsFromSettings(Settings *settings) {
 	params.sparams = createMapgenParams(params.mg_name);
 	if (params.sparams)
 		params.sparams->readParams(settings);
-
 }
 
 
@@ -381,7 +380,7 @@ void EmergeManager::saveParamsToSettings(Settings *settings) {
 	settings->setU64("seed",         params.seed);
 	settings->setS16("water_level",  params.water_level);
 	settings->setS16("chunksize",    params.chunksize);
-	settings->setFlagStr("mg_flags", params.flags, flagdesc_mapgen);
+	settings->setFlagStr("mg_flags", params.flags, flagdesc_mapgen, (u32)-1);
 
 	if (params.sparams)
 		params.sparams->writeParams(settings);

+ 6 - 6
src/mapgen.cpp

@@ -41,12 +41,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 
 FlagDesc flagdesc_mapgen[] = {
-	{"trees",          MG_TREES},
-	{"caves",          MG_CAVES},
-	{"dungeons",       MG_DUNGEONS},
-	{"flat",           MG_FLAT},
-	{"nolight",        MG_NOLIGHT},
-	{NULL,             0}
+	{"trees",    MG_TREES},
+	{"caves",    MG_CAVES},
+	{"dungeons", MG_DUNGEONS},
+	{"flat",     MG_FLAT},
+	{"light",    MG_LIGHT},
+	{NULL,       0}
 };
 
 FlagDesc flagdesc_ore[] = {

+ 3 - 3
src/mapgen.h

@@ -35,7 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define MG_CAVES         0x02
 #define MG_DUNGEONS      0x04
 #define MG_FLAT          0x08
-#define MG_NOLIGHT       0x10
+#define MG_LIGHT         0x10
 
 /////////////////// Ore generation flags
 // Use absolute value of height to determine ore placement
@@ -114,11 +114,11 @@ struct MapgenParams {
 	MapgenSpecificParams *sparams;
 
 	MapgenParams() {
-		mg_name     = "v6";
+		mg_name     = DEFAULT_MAPGEN;
 		seed        = 0;
 		water_level = 1;
 		chunksize   = 5;
-		flags       = MG_TREES | MG_CAVES;
+		flags       = MG_TREES | MG_CAVES | MG_LIGHT;
 		sparams     = NULL;
 	}
 };

+ 1 - 1
src/mapgen_math.cpp

@@ -169,7 +169,7 @@ void MapgenMathParams::writeParams(Settings *settings) {
 
 MapgenMath::MapgenMath(int mapgenid, MapgenParams *params_, EmergeManager *emerge) : MapgenV7(mapgenid, params_, emerge) {
 	mg_params = (MapgenMathParams *)params_;
-	this->flags |= MG_NOLIGHT;
+	this->flags &= ~MG_LIGHT;
 
 	Json::Value & params = mg_params->params;
 	invert = params["invert"].empty() ? 1 : params["invert"].asBool(); //params["invert"].empty()?1:params["invert"].asBool();

+ 1 - 1
src/mapgen_singlenode.cpp

@@ -89,7 +89,7 @@ void MapgenSinglenode::makeChunk(BlockMakeData *data) {
 	updateLiquid(&data->transforming_liquid, node_min, node_max);
 
 	// Calculate lighting
-	if (!(flags & MG_NOLIGHT))
+	if (flags & MG_LIGHT)
 		calcLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE,
 					 node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE);
 	

+ 9 - 9
src/mapgen_v6.cpp

@@ -38,10 +38,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "mapgen_v6.h"
 
 FlagDesc flagdesc_mapgen_v6[] = {
-	{"v6_jungles",     MGV6_JUNGLES},
-	{"v6_biome_blend", MGV6_BIOME_BLEND},
-	{"v6_nomudflow",   MGV6_NOMUDFLOW},
-	{NULL,             0}
+	{"jungles",    MGV6_JUNGLES},
+	{"biomeblend", MGV6_BIOMEBLEND},
+	{"mudflow",    MGV6_MUDFLOW},
+	{NULL,         0}
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -93,7 +93,7 @@ MapgenV6::~MapgenV6() {
 
 
 MapgenV6Params::MapgenV6Params() {
-	spflags     = MGV6_BIOME_BLEND;
+	spflags     = MGV6_BIOMEBLEND | MGV6_MUDFLOW;
 	freq_desert = 0.45;
 	freq_beach  = 0.15;
 
@@ -131,7 +131,7 @@ void MapgenV6Params::readParams(Settings *settings) {
 
 
 void MapgenV6Params::writeParams(Settings *settings) {
-	settings->setFlagStr("mgv6_spflags", spflags, flagdesc_mapgen_v6);
+	settings->setFlagStr("mgv6_spflags", spflags, flagdesc_mapgen_v6, (u32)-1);
 	settings->setFloat("mgv6_freq_desert", freq_desert);
 	settings->setFloat("mgv6_freq_beach",  freq_beach);
 
@@ -365,7 +365,7 @@ BiomeType MapgenV6::getBiome(int index, v2s16 p)
 	if (d > freq_desert)
 		return BT_DESERT;
 		
-	if ((spflags & MGV6_BIOME_BLEND) &&
+	if ((spflags & MGV6_BIOMEBLEND) &&
 		(d > freq_desert - 0.10) &&
 		((noise2d(p.X, p.Y, seed) + 1.0) > (freq_desert - d) * 20.0))
 		return BT_DESERT;
@@ -481,7 +481,7 @@ void MapgenV6::makeChunk(BlockMakeData *data) {
 		addDirtGravelBlobs();
 
 		// Flow mud away from steep edges
-		if (!(spflags & MGV6_NOMUDFLOW))
+		if (spflags & MGV6_MUDFLOW)
 			flowMud(mudflow_minpos, mudflow_maxpos);
 
 	}
@@ -543,7 +543,7 @@ void MapgenV6::makeChunk(BlockMakeData *data) {
 	}
 
 	// Calculate lighting
-	if (!(flags & MG_NOLIGHT))
+	if (flags & MG_LIGHT)
 		calcLighting(node_min - v3s16(1, 1, 1) * MAP_BLOCKSIZE,
 					 node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE);
 	

+ 3 - 3
src/mapgen_v6.h

@@ -25,9 +25,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define AVERAGE_MUD_AMOUNT 4
 
 /////////////////// Mapgen V6 flags
-#define MGV6_JUNGLES     0x01
-#define MGV6_BIOME_BLEND 0x02
-#define MGV6_NOMUDFLOW   0x04
+#define MGV6_JUNGLES    0x01
+#define MGV6_BIOMEBLEND 0x02
+#define MGV6_MUDFLOW    0x04
 
 
 extern FlagDesc flagdesc_mapgen_v6[];

+ 8 - 8
src/mapgen_v7.cpp

@@ -39,9 +39,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 
 FlagDesc flagdesc_mapgen_v7[] = {
-	{"v7_mountains", MGV7_MOUNTAINS},
-	{"v7_ridges",    MGV7_RIDGES},
-	{NULL,           0}
+	{"mountains", MGV7_MOUNTAINS},
+	{"ridges",    MGV7_RIDGES},
+	{NULL,        0}
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -53,10 +53,10 @@ MapgenV7::MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge) {
 	this->emerge = emerge;
 	this->bmgr   = emerge->biomedef;
 
-	this->seed     = (int)params->seed;
+	this->seed        = (int)params->seed;
 	this->water_level = params->water_level;
-	this->flags    = params->flags | MGV7_MOUNTAINS | MGV7_RIDGES;
-	this->gennotify = emerge->gennotify;
+	this->flags       = params->flags;
+	this->gennotify   = emerge->gennotify;
 
 	this->csize   = v3s16(1, 1, 1) * params->chunksize * MAP_BLOCKSIZE;
 
@@ -141,7 +141,7 @@ void MapgenV7Params::readParams(Settings *settings) {
 
 
 void MapgenV7Params::writeParams(Settings *settings) {
-	settings->setFlagStr("mgv7_spflags", spflags, flagdesc_mapgen_v7);
+	settings->setFlagStr("mgv7_spflags", spflags, flagdesc_mapgen_v7, (u32)-1);
 
 	settings->setNoiseParams("mgv7_np_terrain_base",    np_terrain_base);
 	settings->setNoiseParams("mgv7_np_terrain_alt",     np_terrain_alt);
@@ -262,7 +262,7 @@ void MapgenV7::makeChunk(BlockMakeData *data) {
 	
 	updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
 	
-	if (!(flags & MG_NOLIGHT))
+	if (flags & MG_LIGHT)
 		calcLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE,
 					 node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE);
 	//setLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE,

+ 1 - 0
src/porting.h

@@ -87,6 +87,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 	#define strtoll(x, y, z) _strtoi64(x, y, z)
 	#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)
 #else
 	#define ALIGNOF(x) __alignof__(x)
 #endif

+ 5 - 6
src/script/common/c_content.cpp

@@ -839,12 +839,11 @@ void push_hit_params(lua_State *L,const HitParams &params)
 }
 
 /******************************************************************************/
-u32 getflagsfield(lua_State *L, int table,
-	const char *fieldname, FlagDesc *flagdesc) {
-	std::string flagstring;
-
-	flagstring = getstringfield_default(L, table, fieldname, "");
-	return readFlagString(flagstring, flagdesc);
+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);
 }
 
 /******************************************************************************/

+ 1 - 1
src/script/common/c_content.h

@@ -121,7 +121,7 @@ int                getenumfield              (lua_State *L,
 
 u32                getflagsfield             (lua_State *L, int table,
                                               const char *fieldname,
-                                              FlagDesc *flagdesc);
+                                              FlagDesc *flagdesc, u32 *flagmask);
 
 void               push_items                (lua_State *L,
                                               const std::vector<ItemStack> &items);

+ 2 - 1
src/script/cpp_api/s_env.cpp

@@ -78,7 +78,8 @@ void ScriptApiEnv::environment_OnMapgenInit(MapgenParams *mgparams)
 	lua_pushinteger(L, mgparams->water_level);
 	lua_setfield(L, -2, "water_level");
 	
-	std::string flagstr = writeFlagString(mgparams->flags, flagdesc_mapgen);
+	std::string flagstr = writeFlagString(mgparams->flags,
+		flagdesc_mapgen, (u32)-1);
 	lua_pushstring(L, flagstr.c_str());
 	lua_setfield(L, -2, "flags");
 	

+ 15 - 6
src/script/lua_api/l_mapgen.cpp

@@ -210,13 +210,20 @@ int ModApiMapgen::l_set_mapgen_params(lua_State *L)
 	lua_getfield(L, 1, "flagmask");
 	if (lua_isstring(L, -1)) {
 		flagstr = lua_tostring(L, -1);
-		emerge->params.flags &= ~readFlagString(flagstr, flagdesc_mapgen);
+		emerge->params.flags &= ~readFlagString(flagstr, flagdesc_mapgen, NULL);
+		errorstream << "set_mapgen_params(): flagmask field is deprecated, "
+			"see lua_api.txt" << std::endl;
 	}
 
 	lua_getfield(L, 1, "flags");
 	if (lua_isstring(L, -1)) {
+		u32 flags, flagmask;
+
 		flagstr = lua_tostring(L, -1);
-		emerge->params.flags |= readFlagString(flagstr, flagdesc_mapgen);
+		flags   = readFlagString(flagstr, flagdesc_mapgen, &flagmask);
+
+		emerge->params.flags &= ~flagmask;
+		emerge->params.flags |= flags;
 	}
 
 	return 0;
@@ -227,7 +234,8 @@ int ModApiMapgen::l_set_gen_notify(lua_State *L)
 {
 	if (lua_isstring(L, 1)) {
 		EmergeManager *emerge = getServer(L)->getEmergeManager();
-		emerge->gennotify = readFlagString(lua_tostring(L, 1), flagdesc_gennotify);
+		emerge->gennotify = readFlagString(lua_tostring(L, 1),
+			flagdesc_gennotify, NULL);
 	}
 	return 0;
 }
@@ -371,9 +379,10 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
 			break; }
 		case DECO_SCHEMATIC: {
 			DecoSchematic *dschem = (DecoSchematic *)deco;
-			dschem->flags    = getflagsfield(L, index, "flags", flagdesc_deco_schematic);
+			dschem->flags = getflagsfield(L, index, "flags",
+				flagdesc_deco_schematic, NULL);
 			dschem->rotation = (Rotation)getenumfield(L, index,
-								"rotation", es_Rotation, ROTATE_0);
+				"rotation", es_Rotation, ROTATE_0);
 
 			lua_getfield(L, index, "replacements");
 			if (lua_istable(L, -1)) {
@@ -445,7 +454,7 @@ int ModApiMapgen::l_register_ore(lua_State *L)
 	ore->clust_size     = getintfield_default(L, index, "clust_size", 0);
 	ore->height_min     = getintfield_default(L, index, "height_min", 0);
 	ore->height_max     = getintfield_default(L, index, "height_max", 0);
-	ore->flags          = getflagsfield(L, index, "flags", flagdesc_ore);
+	ore->flags          = getflagsfield(L, index, "flags", flagdesc_ore, NULL);
 	ore->nthresh        = getfloatfield_default(L, index, "noise_threshhold", 0.);
 
 	lua_getfield(L, index, "wherein");

+ 22 - 6
src/settings.h

@@ -572,12 +572,15 @@ public:
 		return value;
 	}
 
-	u32 getFlagStr(std::string name, FlagDesc *flagdesc)
+	u32 getFlagStr(std::string name, FlagDesc *flagdesc, u32 *flagmask)
 	{
 		std::string val = get(name);
-		return (isdigit(val[0])) ? stoi(val) : readFlagString(val, flagdesc);
+		return (isdigit(val[0])) ? stoi(val) :
+			readFlagString(val, flagdesc, flagmask);
 	}
 
+	// N.B. if getStruct() is used to read a non-POD aggregate type,
+	// the behavior is undefined.
 	bool getStruct(std::string name, std::string format, void *out, size_t olen)
 	{
 		size_t len = olen;
@@ -755,10 +758,19 @@ fail:
 		}
 	}
 
+	// N.B. getFlagStrNoEx() does not set val, but merely modifies it.  Thus,
+	// val must be initialized before using getFlagStrNoEx().  The intention of
+	// this is to simplify modifying a flags field from a default value.
 	bool getFlagStrNoEx(std::string name, u32 &val, FlagDesc *flagdesc)
 	{
 		try {
-			val = getFlagStr(name, flagdesc);
+			u32 flags, flagmask;
+
+			flags = getFlagStr(name, flagdesc, &flagmask);
+
+			val &= ~flagmask;
+			val |=  flags;
+
 			return true;
 		} catch (SettingNotFoundException &e) {
 			return false;
@@ -856,6 +868,9 @@ fail:
 	}
 
 	//////////// Set setting
+
+	// N.B. if setStruct() is used to write a non-POD aggregate type,
+	// the behavior is undefined.
 	bool setStruct(std::string name, std::string format, void *value)
 	{
 		char sbuf[2048];
@@ -959,10 +974,11 @@ fail:
 		set(name, std::string(sbuf));
 		return true;
 	}
-	
-	void setFlagStr(std::string name, u32 flags, FlagDesc *flagdesc)
+
+	void setFlagStr(std::string name, u32 flags,
+		FlagDesc *flagdesc, u32 flagmask)
 	{
-		set(name, writeFlagString(flags, flagdesc));
+		set(name, writeFlagString(flags, flagdesc, flagmask));
 	}
 
 	void setBool(std::string name, bool value)

+ 32 - 14
src/util/string.cpp

@@ -108,46 +108,63 @@ std::string urldecode(std::string str)
 	return oss.str();
 }
 
-u32 readFlagString(std::string str, FlagDesc *flagdesc) {
-	u32 result = 0;
+u32 readFlagString(std::string str, FlagDesc *flagdesc, u32 *flagmask)
+{
+	u32 result = 0, mask = 0;
 	char *s = &str[0];
 	char *flagstr, *strpos = NULL;
-	
+
 	while ((flagstr = strtok_r(s, ",", &strpos))) {
 		s = NULL;
-		
+
 		while (*flagstr == ' ' || *flagstr == '\t')
 			flagstr++;
-		
+
+		bool flagset = true;
+		if (!strncasecmp(flagstr, "no", 2)) {
+			flagset = false;
+			flagstr += 2;
+		}
+
 		for (int i = 0; flagdesc[i].name; i++) {
 			if (!strcasecmp(flagstr, flagdesc[i].name)) {
-				result |= flagdesc[i].flag;
+				mask |= flagdesc[i].flag;
+				if (flagset)
+					result |= flagdesc[i].flag;
 				break;
 			}
 		}
 	}
-	
+
+	if (flagmask)
+		*flagmask = mask;
+
 	return result;
 }
 
-std::string writeFlagString(u32 flags, FlagDesc *flagdesc) {
+std::string writeFlagString(u32 flags, FlagDesc *flagdesc, u32 flagmask)
+{
 	std::string result;
-	
+
 	for (int i = 0; flagdesc[i].name; i++) {
-		if (flags & flagdesc[i].flag) {
+		if (flagmask & flagdesc[i].flag) {
+			if (!(flags & flagdesc[i].flag))
+				result += "no";
+
 			result += flagdesc[i].name;
 			result += ", ";
 		}
 	}
-	
+
 	size_t len = result.length();
 	if (len >= 2)
 		result.erase(len - 2, 2);
-	
+
 	return result;
 }
 
-char *mystrtok_r(char *s, const char *sep, char **lasts) {
+char *mystrtok_r(char *s, const char *sep, char **lasts)
+{
 	char *t;
 
 	if (!s)
@@ -172,7 +189,8 @@ char *mystrtok_r(char *s, const char *sep, char **lasts) {
 	return s;
 }
 
-u64 read_seed(const char *str) {
+u64 read_seed(const char *str)
+{
 	char *endptr;
 	u64 num;
 	

+ 2 - 2
src/util/string.h

@@ -319,8 +319,8 @@ inline std::string unescape_string(std::string &s)
 std::string translatePassword(std::string playername, std::wstring password);
 std::string urlencode(std::string str);
 std::string urldecode(std::string str);
-u32 readFlagString(std::string str, FlagDesc *flagdesc);
-std::string writeFlagString(u32 flags, FlagDesc *flagdesc);
+u32 readFlagString(std::string str, FlagDesc *flagdesc, u32 *flagmask);
+std::string writeFlagString(u32 flags, FlagDesc *flagdesc, u32 flagmask);
 char *mystrtok_r(char *s, const char *sep, char **lasts);
 u64 read_seed(const char *str);