Prechádzať zdrojové kódy

Add minetest.set_noiseparam_defaults() Lua API

kwolekr 10 rokov pred
rodič
commit
3570f3e396

+ 4 - 0
doc/lua_api.txt

@@ -1386,6 +1386,10 @@ minetest.set_mapgen_params(MapgenParams)
 ^ Leave field unset to leave that parameter unchanged
 ^ 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.set_noiseparam_defaults({np1=NoiseParams, np2= NoiseParams, ...})
+^ Sets the default value of a noiseparam setting
+^ Takes a table as an argument that maps one or more setting names to NoiseParams structures
+^ Possible setting names consist of any NoiseParams setting exposed through the global settings
 minetest.clear_objects()
 ^ clear all objects in the environments
 minetest.line_of_sight(pos1, pos2, stepsize) -> true/false, pos

+ 1 - 0
src/defaultsettings.cpp

@@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "settings.h"
+#include "porting.h"
 #include "filesys.h"
 #include "config.h"
 

+ 12 - 9
src/emerge.cpp

@@ -125,15 +125,6 @@ EmergeManager::EmergeManager(IGameDef *gamedef) {
 		emergethread.push_back(new EmergeThread((Server *)gamedef, i));
 
 	infostream << "EmergeManager: using " << nthreads << " threads" << std::endl;
-
-	loadParamsFromSettings(g_settings);
-
-	if (g_settings->get("fixed_map_seed").empty()) {
-		params.seed = (((u64)(myrand() & 0xffff) << 0)
-					 | ((u64)(myrand() & 0xffff) << 16)
-					 | ((u64)(myrand() & 0xffff) << 32)
-					 | ((u64)(myrand() & 0xffff) << 48));
-	}
 }
 
 
@@ -168,6 +159,18 @@ EmergeManager::~EmergeManager() {
 }
 
 
+void EmergeManager::loadMapgenParams() {
+	loadParamsFromSettings(g_settings);
+
+	if (g_settings->get("fixed_map_seed").empty()) {
+		params.seed = (((u64)(myrand() & 0xffff) << 0)
+					 | ((u64)(myrand() & 0xffff) << 16)
+					 | ((u64)(myrand() & 0xffff) << 32)
+					 | ((u64)(myrand() & 0xffff) << 48));
+	}
+}
+
+
 void EmergeManager::initMapgens() {
 	if (mapgen.size())
 		return;

+ 1 - 0
src/emerge.h

@@ -103,6 +103,7 @@ public:
 	EmergeManager(IGameDef *gamedef);
 	~EmergeManager();
 
+	void loadMapgenParams();
 	void initMapgens();
 	Mapgen *getCurrentMapgen();
 	Mapgen *createMapgen(std::string mgname, int mgid,

+ 5 - 2
src/noise.h

@@ -85,8 +85,11 @@ struct NoiseParams {
 
 
 // Convenience macros for getting/setting NoiseParams in Settings
-#define getNoiseParams(x, y) getStruct((x), "f,f,v3,s32,s32,f", &(y), sizeof(y))
-#define setNoiseParams(x, y) setStruct((x), "f,f,v3,s32,s32,f", &(y))
+
+#define NOISEPARAMS_FMT_STR "f,f,v3,s32,s32,f"
+
+#define getNoiseParams(x, y) getStruct((x), NOISEPARAMS_FMT_STR, &(y), sizeof(y))
+#define setNoiseParams(x, y) setStruct((x), NOISEPARAMS_FMT_STR, &(y))
 
 class Noise {
 public:

+ 19 - 8
src/script/common/c_content.cpp

@@ -958,25 +958,36 @@ void luaentity_get(lua_State *L, u16 id)
 
 /******************************************************************************/
 NoiseParams *read_noiseparams(lua_State *L, int index)
+{
+	NoiseParams *np = new NoiseParams;
+
+	if (!read_noiseparams_nc(L, index, np)) {
+		delete np;
+		np = NULL;
+	}
+
+	return np;
+}
+
+bool read_noiseparams_nc(lua_State *L, int index, NoiseParams *np)
 {
 	if (index < 0)
 		index = lua_gettop(L) + 1 + index;
 
 	if (!lua_istable(L, index))
-		return NULL;
+		return false;
 
-	NoiseParams *np = new NoiseParams;
+	np->offset  = getfloatfield_default(L, index, "offset",  0.0);
+	np->scale   = getfloatfield_default(L, index, "scale",   0.0);
+	np->persist = getfloatfield_default(L, index, "persist", 0.0);
+	np->seed    = getintfield_default(L,   index, "seed",    0);
+	np->octaves = getintfield_default(L,   index, "octaves", 0);
 
-	np->offset  = getfloatfield_default(L, index, "offset", 0.0);
-	np->scale   = getfloatfield_default(L, index, "scale", 0.0);
 	lua_getfield(L, index, "spread");
 	np->spread  = read_v3f(L, -1);
 	lua_pop(L, 1);
-	np->seed    = getintfield_default(L, index, "seed", 0);
-	np->octaves = getintfield_default(L, index, "octaves", 0);
-	np->persist = getfloatfield_default(L, index, "persist", 0.0);
 
-	return np;
+	return true;
 }
 
 /******************************************************************************/

+ 3 - 0
src/script/common/c_content.h

@@ -144,6 +144,9 @@ bool               string_to_enum            (const EnumString *spec,
 
 NoiseParams*       read_noiseparams          (lua_State *L, int index);
 
+bool               read_noiseparams_nc       (lua_State *L, int index,
+                                              NoiseParams *np);
+
 bool               read_schematic            (lua_State *L, int index,
                                               DecoSchematic *dschem,
                                               Server *server);

+ 28 - 0
src/script/lua_api/l_mapgen.cpp

@@ -229,6 +229,33 @@ int ModApiMapgen::l_set_mapgen_params(lua_State *L)
 	return 0;
 }
 
+// minetest.set_noiseparam_defaults({np1={noise params}, ...})
+// set default values for noise parameters if not present in global settings
+int ModApiMapgen::l_set_noiseparam_defaults(lua_State *L)
+{
+	NoiseParams np;
+	std::string val, name;
+
+	if (!lua_istable(L, 1))
+		return 0;
+
+	lua_pushnil(L);
+	while (lua_next(L, 1)) {
+		if (read_noiseparams_nc(L, -1, &np)) {
+			if (!serializeStructToString(&val, NOISEPARAMS_FMT_STR, &np))
+				continue;
+			if (!lua_isstring(L, -2))
+				continue;
+
+			name = lua_tostring(L, -2);
+			g_settings->setDefault(name, val);
+		}
+		lua_pop(L, 1);
+	}
+
+	return 0;
+}
+
 // set_gen_notify(string)
 int ModApiMapgen::l_set_gen_notify(lua_State *L)
 {
@@ -607,6 +634,7 @@ void ModApiMapgen::Initialize(lua_State *L, int top)
 	API_FCT(get_mapgen_object);
 
 	API_FCT(set_mapgen_params);
+	API_FCT(set_noiseparam_defaults);
 	API_FCT(set_gen_notify);
 
 	API_FCT(register_biome);

+ 3 - 0
src/script/lua_api/l_mapgen.h

@@ -32,6 +32,9 @@ private:
 	// set mapgen parameters
 	static int l_set_mapgen_params(lua_State *L);
 
+	// minetest.set_noiseparam_defaults({np1={noise params}, ...})
+	static int l_set_noiseparam_defaults(lua_State *L);
+
 	// set_gen_notify(flagstring)
 	static int l_set_gen_notify(lua_State *L);
 

+ 4 - 0
src/server.cpp

@@ -341,6 +341,10 @@ Server::Server(
 	// Apply item aliases in the node definition manager
 	m_nodedef->updateAliases(m_itemdef);
 
+	// Load the mapgen params from global settings now after any
+	// initial overrides have been set by the mods
+	m_emerge->loadMapgenParams();
+
 	// Initialize Environment
 	ServerMap *servermap = new ServerMap(path_world, this, m_emerge);
 	m_env = new ServerEnvironment(servermap, m_script, this);

+ 7 - 251
src/settings.h

@@ -32,7 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "debug.h"
 #include "log.h"
 #include "util/string.h"
-#include "porting.h"
+#include "util/serialize.h"
 #include <list>
 #include <map>
 #include <set>
@@ -583,11 +583,7 @@ public:
 	// the behavior is undefined.
 	bool getStruct(std::string name, std::string format, void *out, size_t olen)
 	{
-		size_t len = olen;
-		std::vector<std::string *> strs_alloced;
-		std::string *str, valstr;
-		char *f, *snext;
-		size_t pos;
+		std::string valstr;
 
 		try {
 			valstr = get(name);
@@ -595,155 +591,9 @@ public:
 			return false;
 		}
 
-		char *s = &valstr[0];
-		char *buf = new char[len];
-		char *bufpos = buf;
-
-		char *fmtpos, *fmt = &format[0];
-		while ((f = strtok_r(fmt, ",", &fmtpos)) && s) {
-			fmt = NULL;
-
-			bool is_unsigned = false;
-			int width = 0;
-			char valtype = *f;
-
-			width = (int)strtol(f + 1, &f, 10);
-			if (width && valtype == 's')
-				valtype = 'i';
-
-			switch (valtype) {
-				case 'u':
-					is_unsigned = true;
-					/* FALLTHROUGH */
-				case 'i':
-					if (width == 16) {
-						bufpos += PADDING(bufpos, u16);
-						if ((bufpos - buf) + sizeof(u16) <= len) {
-							if (is_unsigned)
-								*(u16 *)bufpos = (u16)strtoul(s, &s, 10);
-							else
-								*(s16 *)bufpos = (s16)strtol(s, &s, 10);
-						}
-						bufpos += sizeof(u16);
-					} else if (width == 32) {
-						bufpos += PADDING(bufpos, u32);
-						if ((bufpos - buf) + sizeof(u32) <= len) {
-							if (is_unsigned)
-								*(u32 *)bufpos = (u32)strtoul(s, &s, 10);
-							else
-								*(s32 *)bufpos = (s32)strtol(s, &s, 10);
-						}
-						bufpos += sizeof(u32);
-					} else if (width == 64) {
-						bufpos += PADDING(bufpos, u64);
-						if ((bufpos - buf) + sizeof(u64) <= len) {
-							if (is_unsigned)
-								*(u64 *)bufpos = (u64)strtoull(s, &s, 10);
-							else
-								*(s64 *)bufpos = (s64)strtoll(s, &s, 10);
-						}
-						bufpos += sizeof(u64);
-					}
-					s = strchr(s, ',');
-					break;
-				case 'b':
-					snext = strchr(s, ',');
-					if (snext)
-						*snext++ = 0;
-
-					bufpos += PADDING(bufpos, bool);
-					if ((bufpos - buf) + sizeof(bool) <= len)
-						*(bool *)bufpos = is_yes(std::string(s));
-					bufpos += sizeof(bool);
-
-					s = snext;
-					break;
-				case 'f':
-					bufpos += PADDING(bufpos, float);
-					if ((bufpos - buf) + sizeof(float) <= len)
-						*(float *)bufpos = strtof(s, &s);
-					bufpos += sizeof(float);
-
-					s = strchr(s, ',');
-					break;
-				case 's':
-					while (*s == ' ' || *s == '\t')
-						s++;
-					if (*s++ != '"') //error, expected string
-						goto fail;
-					snext = s;
-
-					while (snext[0] && !(snext[-1] != '\\' && snext[0] == '"'))
-						snext++;
-					*snext++ = 0;
-
-					bufpos += PADDING(bufpos, std::string *);
-
-					str = new std::string(s);
-					pos = 0;
-					while ((pos = str->find("\\\"", pos)) != std::string::npos)
-						str->erase(pos, 1);
-
-					if ((bufpos - buf) + sizeof(std::string *) <= len)
-						*(std::string **)bufpos = str;
-					bufpos += sizeof(std::string *);
-					strs_alloced.push_back(str);
-
-					s = *snext ? snext + 1 : NULL;
-					break;
-				case 'v':
-					while (*s == ' ' || *s == '\t')
-						s++;
-					if (*s++ != '(') //error, expected vector
-						goto fail;
-
-					if (width == 2) {
-						bufpos += PADDING(bufpos, v2f);
-
-						if ((bufpos - buf) + sizeof(v2f) <= len) {
-						v2f *v = (v2f *)bufpos;
-							v->X = strtof(s, &s);
-							s++;
-							v->Y = strtof(s, &s);
-						}
-
-						bufpos += sizeof(v2f);
-					} else if (width == 3) {
-						bufpos += PADDING(bufpos, v3f);
-						if ((bufpos - buf) + sizeof(v3f) <= len) {
-							v3f *v = (v3f *)bufpos;
-							v->X = strtof(s, &s);
-							s++;
-							v->Y = strtof(s, &s);
-							s++;
-							v->Z = strtof(s, &s);
-						}
-
-						bufpos += sizeof(v3f);
-					}
-					s = strchr(s, ',');
-					break;
-				default: //error, invalid format specifier
-					goto fail;
-			}
-
-			if (s && *s == ',')
-				s++;
-
-			if ((size_t)(bufpos - buf) > len) //error, buffer too small
-				goto fail;
-		}
-
-		if (f && *f) { //error, mismatched number of fields and values
-fail:
-			for (size_t i = 0; i != strs_alloced.size(); i++)
-				delete strs_alloced[i];
-			delete[] buf;
+		if (!deSerializeStringToStruct(valstr, format, out, olen))
 			return false;
-		}
 
-		memcpy(out, buf, olen);
-		delete[] buf;
 		return true;
 	}
 
@@ -873,105 +723,11 @@ fail:
 	// the behavior is undefined.
 	bool setStruct(std::string name, std::string format, void *value)
 	{
-		char sbuf[2048];
-		int sbuflen = sizeof(sbuf) - 1;
-		sbuf[sbuflen] = 0;
-		std::string str;
-		int pos = 0;
-		size_t fpos;
-		char *f;
-
-		char *bufpos = (char *)value;
-		char *fmtpos, *fmt = &format[0];
-		while ((f = strtok_r(fmt, ",", &fmtpos))) {
-			fmt = NULL;
-			bool is_unsigned = false;
-			int width = 0, nprinted = 0;
-			char valtype = *f;
-
-			width = (int)strtol(f + 1, &f, 10);
-			if (width && valtype == 's')
-				valtype = 'i';
-
-			switch (valtype) {
-				case 'u':
-					is_unsigned = true;
-					/* FALLTHROUGH */
-				case 'i':
-					if (width == 16) {
-						bufpos += PADDING(bufpos, u16);
-						nprinted = snprintf(sbuf + pos, sbuflen,
-									is_unsigned ? "%u, " : "%d, ",
-									*((u16 *)bufpos));
-						bufpos += sizeof(u16);
-					} else if (width == 32) {
-						bufpos += PADDING(bufpos, u32);
-						nprinted = snprintf(sbuf + pos, sbuflen,
-									is_unsigned ? "%u, " : "%d, ",
-									*((u32 *)bufpos));
-						bufpos += sizeof(u32);
-					} else if (width == 64) {
-						bufpos += PADDING(bufpos, u64);
-						nprinted = snprintf(sbuf + pos, sbuflen,
-									is_unsigned ? "%llu, " : "%lli, ",
-									(unsigned long long)*((u64 *)bufpos));
-						bufpos += sizeof(u64);
-					}
-					break;
-				case 'b':
-					bufpos += PADDING(bufpos, bool);
-					nprinted = snprintf(sbuf + pos, sbuflen, "%s, ",
-										*((bool *)bufpos) ? "true" : "false");
-					bufpos += sizeof(bool);
-					break;
-				case 'f':
-					bufpos += PADDING(bufpos, float);
-					nprinted = snprintf(sbuf + pos, sbuflen, "%f, ",
-										*((float *)bufpos));
-					bufpos += sizeof(float);
-					break;
-				case 's':
-					bufpos += PADDING(bufpos, std::string *);
-					str = **((std::string **)bufpos);
-
-					fpos = 0;
-					while ((fpos = str.find('"', fpos)) != std::string::npos) {
-						str.insert(fpos, 1, '\\');
-						fpos += 2;
-					}
-
-					nprinted = snprintf(sbuf + pos, sbuflen, "\"%s\", ",
-										(*((std::string **)bufpos))->c_str());
-					bufpos += sizeof(std::string *);
-					break;
-				case 'v':
-					if (width == 2) {
-						bufpos += PADDING(bufpos, v2f);
-						v2f *v = (v2f *)bufpos;
-						nprinted = snprintf(sbuf + pos, sbuflen,
-											"(%f, %f), ", v->X, v->Y);
-						bufpos += sizeof(v2f);
-					} else {
-						bufpos += PADDING(bufpos, v3f);
-						v3f *v = (v3f *)bufpos;
-						nprinted = snprintf(sbuf + pos, sbuflen,
-											"(%f, %f, %f), ", v->X, v->Y, v->Z);
-						bufpos += sizeof(v3f);
-					}
-					break;
-				default:
-					return false;
-			}
-			if (nprinted < 0) //error, buffer too small
-				return false;
-			pos     += nprinted;
-			sbuflen -= nprinted;
-		}
-
-		if (pos >= 2)
-			sbuf[pos - 2] = 0;
+		std::string structstr;
+		if (!serializeStructToString(&structstr, format, value))
+			return false;
 
-		set(name, std::string(sbuf));
+		set(name, structstr);
 		return true;
 	}
 

+ 271 - 0
src/util/serialize.cpp

@@ -19,10 +19,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include "serialize.h"
 #include "pointer.h"
+#include "porting.h"
+#include "util/string.h"
 #include "../exceptions.h"
 
 #include <sstream>
 #include <iomanip>
+#include <vector>
 
 // Creates a string with the length as the first two bytes
 std::string serializeString(const std::string &plain)
@@ -219,3 +222,271 @@ std::string deSerializeJsonString(std::istream &is)
 }
 
 
+bool deSerializeStringToStruct(std::string valstr,
+	std::string format, void *out, size_t olen)
+{
+	size_t len = olen;
+	std::vector<std::string *> strs_alloced;
+	std::string *str;
+	char *f, *snext;
+	size_t pos;
+
+	char *s = &valstr[0];
+	char *buf = new char[len];
+	char *bufpos = buf;
+
+	char *fmtpos, *fmt = &format[0];
+	while ((f = strtok_r(fmt, ",", &fmtpos)) && s) {
+		fmt = NULL;
+
+		bool is_unsigned = false;
+		int width = 0;
+		char valtype = *f;
+
+		width = (int)strtol(f + 1, &f, 10);
+		if (width && valtype == 's')
+			valtype = 'i';
+
+		switch (valtype) {
+			case 'u':
+				is_unsigned = true;
+				/* FALLTHROUGH */
+			case 'i':
+				if (width == 16) {
+					bufpos += PADDING(bufpos, u16);
+					if ((bufpos - buf) + sizeof(u16) <= len) {
+						if (is_unsigned)
+							*(u16 *)bufpos = (u16)strtoul(s, &s, 10);
+						else
+							*(s16 *)bufpos = (s16)strtol(s, &s, 10);
+					}
+					bufpos += sizeof(u16);
+				} else if (width == 32) {
+					bufpos += PADDING(bufpos, u32);
+					if ((bufpos - buf) + sizeof(u32) <= len) {
+						if (is_unsigned)
+							*(u32 *)bufpos = (u32)strtoul(s, &s, 10);
+						else
+							*(s32 *)bufpos = (s32)strtol(s, &s, 10);
+					}
+					bufpos += sizeof(u32);
+				} else if (width == 64) {
+					bufpos += PADDING(bufpos, u64);
+					if ((bufpos - buf) + sizeof(u64) <= len) {
+						if (is_unsigned)
+							*(u64 *)bufpos = (u64)strtoull(s, &s, 10);
+						else
+							*(s64 *)bufpos = (s64)strtoll(s, &s, 10);
+					}
+					bufpos += sizeof(u64);
+				}
+				s = strchr(s, ',');
+				break;
+			case 'b':
+				snext = strchr(s, ',');
+				if (snext)
+					*snext++ = 0;
+
+				bufpos += PADDING(bufpos, bool);
+				if ((bufpos - buf) + sizeof(bool) <= len)
+					*(bool *)bufpos = is_yes(std::string(s));
+				bufpos += sizeof(bool);
+
+				s = snext;
+				break;
+			case 'f':
+				bufpos += PADDING(bufpos, float);
+				if ((bufpos - buf) + sizeof(float) <= len)
+					*(float *)bufpos = strtof(s, &s);
+				bufpos += sizeof(float);
+
+				s = strchr(s, ',');
+				break;
+			case 's':
+				while (*s == ' ' || *s == '\t')
+					s++;
+				if (*s++ != '"') //error, expected string
+					goto fail;
+				snext = s;
+
+				while (snext[0] && !(snext[-1] != '\\' && snext[0] == '"'))
+					snext++;
+				*snext++ = 0;
+
+				bufpos += PADDING(bufpos, std::string *);
+
+				str = new std::string(s);
+				pos = 0;
+				while ((pos = str->find("\\\"", pos)) != std::string::npos)
+					str->erase(pos, 1);
+
+				if ((bufpos - buf) + sizeof(std::string *) <= len)
+					*(std::string **)bufpos = str;
+				bufpos += sizeof(std::string *);
+				strs_alloced.push_back(str);
+
+				s = *snext ? snext + 1 : NULL;
+				break;
+			case 'v':
+				while (*s == ' ' || *s == '\t')
+					s++;
+				if (*s++ != '(') //error, expected vector
+					goto fail;
+
+				if (width == 2) {
+					bufpos += PADDING(bufpos, v2f);
+
+					if ((bufpos - buf) + sizeof(v2f) <= len) {
+					v2f *v = (v2f *)bufpos;
+						v->X = strtof(s, &s);
+						s++;
+						v->Y = strtof(s, &s);
+					}
+
+					bufpos += sizeof(v2f);
+				} else if (width == 3) {
+					bufpos += PADDING(bufpos, v3f);
+					if ((bufpos - buf) + sizeof(v3f) <= len) {
+						v3f *v = (v3f *)bufpos;
+						v->X = strtof(s, &s);
+						s++;
+						v->Y = strtof(s, &s);
+						s++;
+						v->Z = strtof(s, &s);
+					}
+
+					bufpos += sizeof(v3f);
+				}
+				s = strchr(s, ',');
+				break;
+			default: //error, invalid format specifier
+				goto fail;
+		}
+
+		if (s && *s == ',')
+			s++;
+
+		if ((size_t)(bufpos - buf) > len) //error, buffer too small
+			goto fail;
+	}
+
+	if (f && *f) { //error, mismatched number of fields and values
+fail:
+		for (size_t i = 0; i != strs_alloced.size(); i++)
+			delete strs_alloced[i];
+		delete[] buf;
+		return false;
+	}
+
+	memcpy(out, buf, olen);
+	delete[] buf;
+	return true;
+}
+
+
+bool serializeStructToString(std::string *outstr,
+	std::string format, void *value)
+{
+	char sbuf[2048];
+	int sbuflen = sizeof(sbuf) - 1;
+	sbuf[sbuflen] = 0;
+	std::string str;
+	int pos = 0;
+	size_t fpos;
+	char *f;
+
+	char *bufpos = (char *)value;
+	char *fmtpos, *fmt = &format[0];
+	while ((f = strtok_r(fmt, ",", &fmtpos))) {
+		fmt = NULL;
+		bool is_unsigned = false;
+		int width = 0, nprinted = 0;
+		char valtype = *f;
+
+		width = (int)strtol(f + 1, &f, 10);
+		if (width && valtype == 's')
+			valtype = 'i';
+
+		switch (valtype) {
+			case 'u':
+				is_unsigned = true;
+				/* FALLTHROUGH */
+			case 'i':
+				if (width == 16) {
+					bufpos += PADDING(bufpos, u16);
+					nprinted = snprintf(sbuf + pos, sbuflen,
+								is_unsigned ? "%u, " : "%d, ",
+								*((u16 *)bufpos));
+					bufpos += sizeof(u16);
+				} else if (width == 32) {
+					bufpos += PADDING(bufpos, u32);
+					nprinted = snprintf(sbuf + pos, sbuflen,
+								is_unsigned ? "%u, " : "%d, ",
+								*((u32 *)bufpos));
+					bufpos += sizeof(u32);
+				} else if (width == 64) {
+					bufpos += PADDING(bufpos, u64);
+					nprinted = snprintf(sbuf + pos, sbuflen,
+								is_unsigned ? "%llu, " : "%lli, ",
+								(unsigned long long)*((u64 *)bufpos));
+					bufpos += sizeof(u64);
+				}
+				break;
+			case 'b':
+				bufpos += PADDING(bufpos, bool);
+				nprinted = snprintf(sbuf + pos, sbuflen, "%s, ",
+									*((bool *)bufpos) ? "true" : "false");
+				bufpos += sizeof(bool);
+				break;
+			case 'f':
+				bufpos += PADDING(bufpos, float);
+				nprinted = snprintf(sbuf + pos, sbuflen, "%f, ",
+									*((float *)bufpos));
+				bufpos += sizeof(float);
+				break;
+			case 's':
+				bufpos += PADDING(bufpos, std::string *);
+				str = **((std::string **)bufpos);
+
+				fpos = 0;
+				while ((fpos = str.find('"', fpos)) != std::string::npos) {
+					str.insert(fpos, 1, '\\');
+					fpos += 2;
+				}
+
+				nprinted = snprintf(sbuf + pos, sbuflen, "\"%s\", ",
+									(*((std::string **)bufpos))->c_str());
+				bufpos += sizeof(std::string *);
+				break;
+			case 'v':
+				if (width == 2) {
+					bufpos += PADDING(bufpos, v2f);
+					v2f *v = (v2f *)bufpos;
+					nprinted = snprintf(sbuf + pos, sbuflen,
+										"(%f, %f), ", v->X, v->Y);
+					bufpos += sizeof(v2f);
+				} else {
+					bufpos += PADDING(bufpos, v3f);
+					v3f *v = (v3f *)bufpos;
+					nprinted = snprintf(sbuf + pos, sbuflen,
+										"(%f, %f, %f), ", v->X, v->Y, v->Z);
+					bufpos += sizeof(v3f);
+				}
+				break;
+			default:
+				return false;
+		}
+		if (nprinted < 0) //error, buffer too small
+			return false;
+		pos     += nprinted;
+		sbuflen -= nprinted;
+	}
+
+	// this is to trim off the trailing comma
+	if (pos >= 2)
+		sbuf[pos - 2] = 0;
+
+	*outstr = sbuf;
+
+	return true;
+}

+ 10 - 0
src/util/serialize.h

@@ -401,5 +401,15 @@ std::string serializeJsonString(const std::string &plain);
 // Reads a string encoded in JSON format
 std::string deSerializeJsonString(std::istream &is);
 
+// Creates a string containing comma delimited values of a struct whose layout is
+// described by the parameter format
+bool serializeStructToString(std::string *outstr,
+	std::string format, void *value);
+
+// Reads a comma delimited string of values into a struct whose layout is
+// decribed by the parameter format
+bool deSerializeStringToStruct(std::string valstr,
+	std::string format, void *out, size_t olen);
+
 #endif