diff --git a/src/emerge.cpp b/src/emerge.cpp index ed9aa9044..569f1b80a 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -351,8 +351,11 @@ MapgenParams *EmergeManager::getParamsFromSettings(Settings *settings) { if (!mgparams) return NULL; + std::string seedstr = settings->get(settings == g_settings ? + "fixed_map_seed" : "seed"); + mgparams->mg_name = mg_name; - mgparams->seed = settings->getU64(settings == g_settings ? "fixed_map_seed" : "seed"); + mgparams->seed = read_seed(seedstr.c_str()); mgparams->water_level = settings->getS16("water_level"); mgparams->chunksize = settings->getS16("chunksize"); mgparams->flags = settings->getFlagStr("mg_flags", flagdesc_mapgen); diff --git a/src/map.cpp b/src/map.cpp index 968897c0c..cea20b0d3 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -3507,7 +3507,7 @@ void ServerMap::loadMapMeta() m_seed = mgparams->seed; } else { if (params.exists("seed")) { - m_seed = params.getU64("seed"); + m_seed = read_seed(params.get("seed").c_str()); m_mgparams->seed = m_seed; } } diff --git a/src/util/numeric.cpp b/src/util/numeric.cpp index 67df4ffba..0426656a5 100644 --- a/src/util/numeric.cpp +++ b/src/util/numeric.cpp @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "../log.h" #include "../constants.h" // BS, MAP_BLOCKSIZE +#include #include // Calculate the borders of a "d-radius" cube @@ -139,6 +140,49 @@ int myrand_range(int min, int max) return (myrand()%(max-min+1))+min; } +// 64-bit unaligned version of MurmurHash +u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed) +{ + const u64 m = 0xc6a4a7935bd1e995; + const int r = 47; + u64 h = seed ^ (len * m); + + const u64 *data = (const u64 *)key; + const u64 *end = data + (len / 8); + + while (data != end) { + u64 k; + memcpy(&k, data, sizeof(u64)); + data++; + + k *= m; + k ^= k >> r; + k *= m; + + h ^= k; + h *= m; + } + + const unsigned char *data2 = (const unsigned char *)data; + switch (len & 7) { + case 7: h ^= (u64)data2[6] << 48; + case 6: h ^= (u64)data2[5] << 40; + case 5: h ^= (u64)data2[4] << 32; + case 4: h ^= (u64)data2[3] << 24; + case 3: h ^= (u64)data2[2] << 16; + case 2: h ^= (u64)data2[1] << 8; + case 1: h ^= (u64)data2[0]; + h *= m; + } + + h ^= h >> r; + h *= m; + h ^= h >> r; + + return h; +} + + /* blockpos: position of block in block coordinates camera_pos: position of camera in nodes diff --git a/src/util/numeric.h b/src/util/numeric.h index b96c94faa..8e3a617ff 100644 --- a/src/util/numeric.h +++ b/src/util/numeric.h @@ -222,6 +222,8 @@ int myrand_range(int min, int max); Miscellaneous functions */ +u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed); + bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 camera_fov, f32 range, f32 *distance_ptr=NULL); diff --git a/src/util/string.cpp b/src/util/string.cpp index 2c1dea497..a2312baf8 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "string.h" #include "pointer.h" +#include "numeric.h" #include "../sha1.h" #include "../base64.h" @@ -136,3 +137,18 @@ char *mystrtok_r(char *s, const char *sep, char **lasts) { *lasts = t; return s; } + +u64 read_seed(const char *str) { + char *endptr; + u64 num; + + if (str[0] == '0' && str[1] == 'x') + num = strtoull(str, &endptr, 16); + else + num = strtoull(str, &endptr, 10); + + if (*endptr) + num = murmur_hash_64_ua(str, (int)strlen(str), 0x1337); + + return num; +} diff --git a/src/util/string.h b/src/util/string.h index 7531600e3..81855962f 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -321,6 +321,7 @@ 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); +u64 read_seed(const char *str); #endif