diff --git a/minetest.conf.example b/minetest.conf.example index 6559ac88b..49fc95ba2 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -239,6 +239,10 @@ #congestion_control_aim_rtt = 0.2 #congestion_control_max_rate = 400 #congestion_control_min_rate = 10 +# Specifies URL from which client fetches media instead of using UDP +# $filename should be accessible from $remote_media$filename via cURL +# (obviously, remote_media should end with a slash) +# Files that are not present would be fetched the usual way #remote_media = # Mapgen stuff diff --git a/src/biome.cpp b/src/biome.cpp index 180a9c4a5..34d51839f 100644 --- a/src/biome.cpp +++ b/src/biome.cpp @@ -127,7 +127,7 @@ void BiomeDefManager::addBiome(Biome *b) { bgroup->push_back(b); verbosestream << "BiomeDefManager: added biome '" << b->name << - "' to biome group " << b->groupid << std::endl; + "' to biome group " << (int)b->groupid << std::endl; } diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index e6526d3d7..a164d0693 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -177,7 +177,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", "19"); + settings->setDefault("mg_flags", "trees, caves, v6_biome_blend"); settings->setDefault("mgv6_freq_desert", "0.45"); settings->setDefault("mgv6_freq_beach", "0.15"); diff --git a/src/map.cpp b/src/map.cpp index ea82194b8..717b0cf9b 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -2013,10 +2013,10 @@ ServerMap::ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emer if (g_settings->get("fixed_map_seed").empty()) { - m_seed = (((u64)(myrand()%0xffff)<<0) - + ((u64)(myrand()%0xffff)<<16) - + ((u64)(myrand()%0xffff)<<32) - + ((u64)(myrand()&0xffff)<<48)); + m_seed = (((u64)(myrand() & 0xffff) << 0) + | ((u64)(myrand() & 0xffff) << 16) + | ((u64)(myrand() & 0xffff) << 32) + | ((u64)(myrand() & 0xffff) << 48)); m_mgparams->seed = m_seed; } @@ -3078,14 +3078,7 @@ void ServerMap::saveMapMeta() Settings params; - params.set("mg_name", m_emerge->params->mg_name); - params.setU64("seed", m_emerge->params->seed); - params.setS16("water_level", m_emerge->params->water_level); - params.setS16("chunksize", m_emerge->params->chunksize); - params.setS32("mg_flags", m_emerge->params->flags); - - m_emerge->params->writeParams(¶ms); - + m_emerge->setParamsToSettings(¶ms); params.writeLines(os); os<<"[end_of_params]\n"; diff --git a/src/mapgen.cpp b/src/mapgen.cpp index f2745bdb4..b19073e90 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -35,6 +35,15 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "treegen.h" #include "mapgen_v6.h" +FlagDesc flagdesc_mapgen[] = { + {"trees", MG_TREES}, + {"caves", MG_CAVES}, + {"dungeons", MG_DUNGEONS}, + {"v6_forests", MGV6_FORESTS}, + {"v6_biome_blend", MGV6_BIOME_BLEND}, + {"flat", MG_FLAT}, + {NULL, 0} +}; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////// Emerge Manager //////////////////////////////// @@ -149,7 +158,7 @@ MapgenParams *EmergeManager::getParamsFromSettings(Settings *settings) { mgparams->seed = settings->getU64(settings == g_settings ? "fixed_map_seed" : "seed"); mgparams->water_level = settings->getS16("water_level"); mgparams->chunksize = settings->getS16("chunksize"); - mgparams->flags = settings->getS32("mg_flags"); + mgparams->flags = settings->getFlagStr("mg_flags", flagdesc_mapgen); if (!mgparams->readParams(settings)) { delete mgparams; @@ -159,7 +168,18 @@ MapgenParams *EmergeManager::getParamsFromSettings(Settings *settings) { } -bool EmergeManager::registerMapgen(std::string mgname, MapgenFactory *mgfactory) { +void EmergeManager::setParamsToSettings(Settings *settings) { + settings->set("mg_name", params->mg_name); + 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); + + params->writeParams(settings); +} + + +void EmergeManager::registerMapgen(std::string mgname, MapgenFactory *mgfactory) { mglist.insert(std::make_pair(mgname, mgfactory)); infostream << "EmergeManager: registered mapgen " << mgname << std::endl; } diff --git a/src/mapgen.h b/src/mapgen.h index 728290ffc..4f1ab4ebd 100644 --- a/src/mapgen.h +++ b/src/mapgen.h @@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MG_DUNGEONS 0x04 #define MGV6_FORESTS 0x08 #define MGV6_BIOME_BLEND 0x10 +#define MG_FLAT 0x20 class BiomeDefManager; class Biome; @@ -121,8 +122,9 @@ public: Mapgen *getMapgen(); void addBlockToQueue(); - bool registerMapgen(std::string name, MapgenFactory *mgfactory); + void registerMapgen(std::string name, MapgenFactory *mgfactory); MapgenParams *getParamsFromSettings(Settings *settings); + void setParamsToSettings(Settings *settings); //mapgen helper methods Biome *getBiomeAtPoint(v3s16 p); diff --git a/src/mapgen_v6.cpp b/src/mapgen_v6.cpp index 30df1673c..3a5e10930 100644 --- a/src/mapgen_v6.cpp +++ b/src/mapgen_v6.cpp @@ -278,6 +278,9 @@ bool MapgenV6::block_is_underground(u64 seed, v3s16 blockpos) double MapgenV6::base_rock_level_2d(u64 seed, v2s16 p) { + if (flags & MG_FLAT) + return water_level; + int index = (p.Y - node_min.Z) * ystride + (p.X - node_min.X); // The base ground level @@ -333,6 +336,9 @@ double MapgenV6::base_rock_level_2d(u64 seed, v2s16 p) } double MapgenV6::baseRockLevelFromNoise(v2s16 p) { + if (flags & MG_FLAT) + return water_level; + double base = water_level + NoisePerlin2DPosOffset(noise_terrain_base->np, p.X, 0.5, p.Y, 0.5, seed); double higher = water_level + @@ -370,6 +376,9 @@ s16 MapgenV6::find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision) double MapgenV6::get_mud_add_amount(u64 seed, v2s16 p) { + if (flags & MG_FLAT) + return AVERAGE_MUD_AMOUNT; + /*return ((float)AVERAGE_MUD_AMOUNT + 2.0 * noise2d_perlin( 0.5+(float)p.X/200, 0.5+(float)p.Y/200, seed+91013, 3, 0.55));*/ @@ -491,34 +500,37 @@ void MapgenV6::makeChunk(BlockMakeData *data) int z = node_min.Z; // Need to adjust for the original implementation's +.5 offset... - noise_terrain_base->perlinMap2D( - x + 0.5 * noise_terrain_base->np->spread.X, - z + 0.5 * noise_terrain_base->np->spread.Z); - noise_terrain_base->transformNoiseMap(); + if (!(flags & MG_FLAT)) { + noise_terrain_base->perlinMap2D( + x + 0.5 * noise_terrain_base->np->spread.X, + z + 0.5 * noise_terrain_base->np->spread.Z); + noise_terrain_base->transformNoiseMap(); - noise_terrain_higher->perlinMap2D( - x + 0.5 * noise_terrain_higher->np->spread.X, - z + 0.5 * noise_terrain_higher->np->spread.Z); - noise_terrain_higher->transformNoiseMap(); + noise_terrain_higher->perlinMap2D( + x + 0.5 * noise_terrain_higher->np->spread.X, + z + 0.5 * noise_terrain_higher->np->spread.Z); + noise_terrain_higher->transformNoiseMap(); - noise_steepness->perlinMap2D( - x + 0.5 * noise_steepness->np->spread.X, - z + 0.5 * noise_steepness->np->spread.Z); - noise_steepness->transformNoiseMap(); - - noise_height_select->perlinMap2D( - x + 0.5 * noise_height_select->np->spread.X, - z + 0.5 * noise_height_select->np->spread.Z); + noise_steepness->perlinMap2D( + x + 0.5 * noise_steepness->np->spread.X, + z + 0.5 * noise_steepness->np->spread.Z); + noise_steepness->transformNoiseMap(); + noise_height_select->perlinMap2D( + x + 0.5 * noise_height_select->np->spread.X, + z + 0.5 * noise_height_select->np->spread.Z); + } + noise_trees->perlinMap2D( x + 0.5 * noise_trees->np->spread.X, z + 0.5 * noise_trees->np->spread.Z); - - noise_mud->perlinMap2D( - x + 0.5 * noise_mud->np->spread.X, - z + 0.5 * noise_mud->np->spread.Z); - noise_mud->transformNoiseMap(); - + + if (!(flags & MG_FLAT)) { + noise_mud->perlinMap2D( + x + 0.5 * noise_mud->np->spread.X, + z + 0.5 * noise_mud->np->spread.Z); + noise_mud->transformNoiseMap(); + } noise_beach->perlinMap2D( x + 0.2 * noise_beach->np->spread.X, z + 0.7 * noise_beach->np->spread.Z); diff --git a/src/noise.cpp b/src/noise.cpp index de9d48808..bfb1960c8 100644 --- a/src/noise.cpp +++ b/src/noise.cpp @@ -367,6 +367,7 @@ void Noise::resizeNoiseBuf(bool is3d) { * values from the previous noise lattice as midpoints in the new lattice for the * next octave. */ +#define idx(x, y) ((y) * nlx + (x)) void Noise::gradientMap2D(float x, float y, float step_x, float step_y, int seed) { float v00, v01, v10, v11, u, v, orig_u; int index, i, j, x0, y0, noisex, noisey; @@ -387,25 +388,26 @@ void Noise::gradientMap2D(float x, float y, float step_x, float step_y, int seed noisebuf[index++] = noise2d(x0 + i, y0 + j, seed); //calculate interpolations + index = 0; noisey = 0; for (j = 0; j != sy; j++) { - v00 = noisebuf[noisey * nlx]; - v10 = noisebuf[noisey * nlx + 1]; - v01 = noisebuf[(noisey + 1) * nlx]; - v11 = noisebuf[(noisey + 1) * nlx + 1]; + v00 = noisebuf[idx(0, noisey)]; + v10 = noisebuf[idx(1, noisey)]; + v01 = noisebuf[idx(0, noisey + 1)]; + v11 = noisebuf[idx(1, noisey + 1)]; u = orig_u; noisex = 0; for (i = 0; i != sx; i++) { - buf[j * sx + i] = biLinearInterpolation(v00, v10, v01, v11, u, v); + buf[index++] = biLinearInterpolation(v00, v10, v01, v11, u, v); u += step_x; if (u >= 1.0) { u -= 1.0; noisex++; v00 = v10; v01 = v11; - v10 = noisebuf[noisey * nlx + noisex + 1]; - v11 = noisebuf[(noisey + 1) * nlx + noisex + 1]; + v10 = noisebuf[idx(noisex + 1, noisey)]; + v11 = noisebuf[idx(noisex + 1, noisey + 1)]; } } @@ -416,14 +418,16 @@ void Noise::gradientMap2D(float x, float y, float step_x, float step_y, int seed } } } +#undef idx +#define idx(x, y, z) ((z) * nly * nlx + (y) * nlx + (x)) void Noise::gradientMap3D(float x, float y, float z, float step_x, float step_y, float step_z, int seed) { float v000, v010, v100, v110; float v001, v011, v101, v111; - float u, v, w, orig_u, orig_w; + float u, v, w, orig_u, orig_v; int index, i, j, k, x0, y0, z0, noisex, noisey, noisez; int nlx, nly, nlz; @@ -434,49 +438,39 @@ void Noise::gradientMap3D(float x, float y, float z, v = y - (float)y0; w = z - (float)z0; orig_u = u; - orig_w = w; + orig_v = v; //calculate noise point lattice nlx = (int)(u + sx * step_x) + 2; nly = (int)(v + sy * step_y) + 2; - nlz = (int)(v + sy * step_z) + 2; + nlz = (int)(w + sz * step_z) + 2; index = 0; for (k = 0; k != nlz; k++) for (j = 0; j != nly; j++) for (i = 0; i != nlx; i++) noisebuf[index++] = noise3d(x0 + i, y0 + j, z0 + k, seed); -#define index(x, y, z) ((z) * nly * nlx + (y) * nlx + (x)) - //calculate interpolations + index = 0; noisey = 0; noisez = 0; for (k = 0; k != sz; k++) { - v000 = noisebuf[index(0, noisey, noisez)]; - v100 = noisebuf[index(1, noisey, noisez)]; - v010 = noisebuf[index(0, noisey + 1, noisez)]; - v110 = noisebuf[index(1, noisey + 1, noisez)]; - v001 = noisebuf[index(0, noisey, noisez + 1)]; - v101 = noisebuf[index(1, noisey, noisez + 1)]; - v011 = noisebuf[index(0, noisey + 1, noisez + 1)]; - v111 = noisebuf[index(1, noisey + 1, noisez + 1)]; - - w = orig_w; + v = orig_v; noisey = 0; for (j = 0; j != sy; j++) { - v000 = noisebuf[index(0, noisey, noisez)]; - v100 = noisebuf[index(1, noisey, noisez)]; - v010 = noisebuf[index(0, noisey + 1, noisez)]; - v110 = noisebuf[index(1, noisey + 1, noisez)]; - v001 = noisebuf[index(0, noisey, noisez + 1)]; - v101 = noisebuf[index(1, noisey, noisez + 1)]; - v011 = noisebuf[index(0, noisey + 1, noisez + 1)]; - v111 = noisebuf[index(1, noisey + 1, noisez + 1)]; + v000 = noisebuf[idx(0, noisey, noisez)]; + v100 = noisebuf[idx(1, noisey, noisez)]; + v010 = noisebuf[idx(0, noisey + 1, noisez)]; + v110 = noisebuf[idx(1, noisey + 1, noisez)]; + v001 = noisebuf[idx(0, noisey, noisez + 1)]; + v101 = noisebuf[idx(1, noisey, noisez + 1)]; + v011 = noisebuf[idx(0, noisey + 1, noisez + 1)]; + v111 = noisebuf[idx(1, noisey + 1, noisez + 1)]; u = orig_u; noisex = 0; for (i = 0; i != sx; i++) { - buf[j * sx + i] = triLinearInterpolation( + buf[index++] = triLinearInterpolation( v000, v100, v010, v110, v001, v101, v011, v111, u, v, w); @@ -486,12 +480,12 @@ void Noise::gradientMap3D(float x, float y, float z, noisex++; v000 = v100; v010 = v110; - v100 = noisebuf[index(noisex + 1, noisey, noisez)]; - v110 = noisebuf[index(noisex + 1, noisey + 1, noisez)]; + v100 = noisebuf[idx(noisex + 1, noisey, noisez)]; + v110 = noisebuf[idx(noisex + 1, noisey + 1, noisez)]; v001 = v101; v011 = v111; - v101 = noisebuf[index(noisex + 1, noisey, noisez + 1)]; - v111 = noisebuf[index(noisex + 1, noisey + 1, noisez + 1)]; + v101 = noisebuf[idx(noisex + 1, noisey, noisez + 1)]; + v111 = noisebuf[idx(noisex + 1, noisey + 1, noisez + 1)]; } } @@ -509,6 +503,7 @@ void Noise::gradientMap3D(float x, float y, float z, } } } +#undef idx float *Noise::perlinMap2D(float x, float y) { diff --git a/src/porting.cpp b/src/porting.cpp index de15de9ce..f8a2cca5c 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -220,7 +220,7 @@ void initializePaths() //TODO: Test this code char buf[BUFSIZ]; uint32_t len = sizeof(buf); - assert(_NSGetExecutablePath(buf, &len) != 0); + assert(_NSGetExecutablePath(buf, &len) != -1); pathRemoveFile(buf, '/'); diff --git a/src/porting.h b/src/porting.h index c8d19154c..9ba3394bb 100644 --- a/src/porting.h +++ b/src/porting.h @@ -56,6 +56,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define strtof(x, y) (float)strtod(x, y) #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) #else #define ALIGNOF(x) __alignof__(x) #endif diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 6e2a0a314..020709cab 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -693,6 +693,30 @@ static NodeBox read_nodebox(lua_State *L, int index) return nodebox; } +/* + NoiseParams +*/ +static NoiseParams *read_noiseparams(lua_State *L, int index) +{ + if (index < 0) + index = lua_gettop(L) + 1 + index; + + if (!lua_istable(L, index)) + return NULL; + + NoiseParams *np = new NoiseParams; + + 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); + 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; +} + /* Groups */ @@ -3241,11 +3265,6 @@ static void objectref_get_or_create(lua_State *L, } } - -/* - PerlinNoise - */ - class LuaPerlinNoise { private: @@ -3355,6 +3374,145 @@ const luaL_reg LuaPerlinNoise::methods[] = { {0,0} }; +/* + PerlinNoiseMap + */ +class LuaPerlinNoiseMap +{ +private: + Noise *noise; + static const char className[]; + static const luaL_reg methods[]; + + static int gc_object(lua_State *L) + { + LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)(lua_touserdata(L, 1)); + delete o; + return 0; + } + + static int l_get2dMap(lua_State *L) + { + int i = 0; + + LuaPerlinNoiseMap *o = checkobject(L, 1); + v2f p = read_v2f(L, 2); + + Noise *n = o->noise; + n->perlinMap2D(p.X, p.Y); + + lua_newtable(L); + for (int y = 0; y != n->sy; y++) { + lua_newtable(L); + for (int x = 0; x != n->sx; x++) { + float noiseval = n->np->offset + n->np->scale * n->result[i++]; + lua_pushnumber(L, noiseval); + lua_rawseti(L, -2, x + 1); + } + lua_rawseti(L, -2, y + 1); + } + return 1; + } + + static int l_get3dMap(lua_State *L) + { + int i = 0; + + LuaPerlinNoiseMap *o = checkobject(L, 1); + v3f p = read_v3f(L, 2); + + Noise *n = o->noise; + n->perlinMap3D(p.X, p.Y, p.Z); + + lua_newtable(L); + for (int z = 0; z != n->sz; z++) { + lua_newtable(L); + for (int y = 0; y != n->sy; y++) { + lua_newtable(L); + for (int x = 0; x != n->sx; x++) { + lua_pushnumber(L, n->np->offset + n->np->scale * n->result[i++]); + lua_rawseti(L, -2, x + 1); + } + lua_rawseti(L, -2, y + 1); + } + lua_rawseti(L, -2, z + 1); + } + return 1; + } + +public: + LuaPerlinNoiseMap(NoiseParams *np, int seed, v3s16 size) { + noise = new Noise(np, seed, size.X, size.Y, size.Z); + } + + ~LuaPerlinNoiseMap() + { + delete noise->np; + delete noise; + } + + // LuaPerlinNoiseMap(np, size) + // Creates an LuaPerlinNoiseMap and leaves it on top of stack + static int create_object(lua_State *L) + { + NoiseParams *np = read_noiseparams(L, 1); + if (!np) + return 0; + v3s16 size = read_v3s16(L, 2); + + LuaPerlinNoiseMap *o = new LuaPerlinNoiseMap(np, 0, size); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + return 1; + } + + static LuaPerlinNoiseMap *checkobject(lua_State *L, int narg) + { + luaL_checktype(L, narg, LUA_TUSERDATA); + + void *ud = luaL_checkudata(L, narg, className); + if (!ud) + luaL_typerror(L, narg, className); + + return *(LuaPerlinNoiseMap **)ud; // unbox pointer + } + + static void Register(lua_State *L) + { + lua_newtable(L); + int methodtable = lua_gettop(L); + luaL_newmetatable(L, className); + int metatable = lua_gettop(L); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); // hide metatable from Lua getmetatable() + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, gc_object); + lua_settable(L, metatable); + + lua_pop(L, 1); // drop metatable + + luaL_openlib(L, 0, methods, 0); // fill methodtable + lua_pop(L, 1); // drop methodtable + + // Can be created from Lua (PerlinNoiseMap(np, size) + lua_register(L, className, create_object); + } +}; +const char LuaPerlinNoiseMap::className[] = "PerlinNoiseMap"; +const luaL_reg LuaPerlinNoiseMap::methods[] = { + method(LuaPerlinNoiseMap, get2dMap), + method(LuaPerlinNoiseMap, get3dMap), + {0,0} +}; + /* NodeTimerRef */ @@ -4019,6 +4177,28 @@ private: lua_setmetatable(L, -2); return 1; } + + // EnvRef:get_perlin_map(noiseparams, size) + // returns world-specific PerlinNoiseMap + static int l_get_perlin_map(lua_State *L) + { + EnvRef *o = checkobject(L, 1); + ServerEnvironment *env = o->m_env; + if (env == NULL) + return 0; + + NoiseParams *np = read_noiseparams(L, 2); + if (!np) + return 0; + v3s16 size = read_v3s16(L, 3); + + int seed = (int)(env->getServerMap().getSeed()); + LuaPerlinNoiseMap *n = new LuaPerlinNoiseMap(np, seed, size); + *(void **)(lua_newuserdata(L, sizeof(void *))) = n; + luaL_getmetatable(L, "PerlinNoiseMap"); + lua_setmetatable(L, -2); + return 1; + } // EnvRef:clear_objects() // clear all objects in the environment @@ -4158,8 +4338,7 @@ const luaL_reg EnvRef::methods[] = { method(EnvRef, find_node_near), method(EnvRef, find_nodes_in_area), method(EnvRef, get_perlin), - //method{EnvRef, get_perlin_map_2d}, - //method{EnvRef, get_perlin_map_3d}, + method(EnvRef, get_perlin_map), method(EnvRef, clear_objects), method(EnvRef, spawn_tree), {0,0} @@ -5424,6 +5603,7 @@ void scriptapi_export(lua_State *L, Server *server) EnvRef::Register(L); LuaPseudoRandom::Register(L); LuaPerlinNoise::Register(L); + LuaPerlinNoiseMap::Register(L); } bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath, diff --git a/src/settings.h b/src/settings.h index 2b46676c6..addd9980c 100644 --- a/src/settings.h +++ b/src/settings.h @@ -569,6 +569,12 @@ public: return value; } + u32 getFlagStr(std::string name, FlagDesc *flagdesc) + { + std::string val = get(name); + return (isdigit(val[0])) ? stoi(val) : readFlagString(val, flagdesc); + } + template T *getStruct(std::string name, std::string format) { size_t len = sizeof(T); @@ -831,6 +837,11 @@ fail: set(name, std::string(sbuf)); return true; } + + void setFlagStr(std::string name, u32 flags, FlagDesc *flagdesc) + { + set(name, writeFlagString(flags, flagdesc)); + } void setBool(std::string name, bool value) { diff --git a/src/util/string.cpp b/src/util/string.cpp index c10755ae1..61b307c60 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "../sha1.h" #include "../base64.h" +#include "../porting.h" // Get an sha-1 hash of the player's name combined with // the password entered. That's what the server uses as @@ -48,6 +49,45 @@ size_t curl_write_data(char *ptr, size_t size, size_t nmemb, void *userdata) { return count; } +u32 readFlagString(std::string str, FlagDesc *flagdesc) { + u32 result = 0; + char *s = &str[0]; + char *flagstr, *strpos = NULL; + + while ((flagstr = strtok_r(s, ",", &strpos))) { + s = NULL; + + while (*flagstr == ' ' || *flagstr == '\t') + flagstr++; + + for (int i = 0; flagdesc[i].name; i++) { + if (!strcasecmp(flagstr, flagdesc[i].name)) { + result |= flagdesc[i].flag; + break; + } + } + } + + return result; +} + +std::string writeFlagString(u32 flags, FlagDesc *flagdesc) { + std::string result; + + for (int i = 0; flagdesc[i].name; i++) { + if (flags & flagdesc[i].flag) { + 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 *t; diff --git a/src/util/string.h b/src/util/string.h index d081b365b..a469a074a 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -28,6 +28,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include +struct FlagDesc { + const char *name; + u32 flag; +}; + static inline std::string padStringRight(std::string s, size_t len) { if(len > s.size()) @@ -283,6 +288,8 @@ inline std::string wrap_rows(const std::string &from, u32 rowlen) std::string translatePassword(std::string playername, std::wstring password); size_t curl_write_data(char *ptr, size_t size, size_t nmemb, void *userdata); +u32 readFlagString(std::string str, FlagDesc *flagdesc); +std::string writeFlagString(u32 flags, FlagDesc *flagdesc); char *mystrtok_r(char *s, const char *sep, char **lasts); #endif