X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fmapgen.cpp;h=d8eb8068a8680efe9c5b02bb95e59208c317a609;hb=ab04b7fe941003cf33350d7def69e4c1cc751314;hp=835c14be13cd196a1200ef8144e6a81afea4c6e1;hpb=1dfc2e02b3c358af4bb20bb3cb60ac7bd3ed1124;p=minetest.git diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 835c14be1..d8eb8068a 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -20,200 +20,174 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapgen.h" #include "voxel.h" #include "noise.h" -#include "biome.h" +#include "gamedef.h" +#include "mg_biome.h" #include "mapblock.h" #include "mapnode.h" #include "map.h" -//#include "serverobject.h" #include "content_sao.h" #include "nodedef.h" +#include "emerge.h" #include "content_mapnode.h" // For content_mapnode_get_new_name #include "voxelalgorithms.h" +#include "porting.h" #include "profiler.h" -#include "settings.h" // For g_settings -#include "main.h" // For g_profiler +#include "settings.h" #include "treegen.h" -#include "mapgen_v6.h" -#include "mapgen_v7.h" +#include "serialization.h" +#include "util/serialize.h" +#include "util/numeric.h" +#include "filesys.h" +#include "log.h" FlagDesc flagdesc_mapgen[] = { - {"trees", MG_TREES}, - {"caves", MG_CAVES}, - {"dungeons", MG_DUNGEONS}, - {"v6_jungles", MGV6_JUNGLES}, - {"v6_biome_blend", MGV6_BIOME_BLEND}, - {"flat", MG_FLAT}, - {NULL, 0} + {"trees", MG_TREES}, + {"caves", MG_CAVES}, + {"dungeons", MG_DUNGEONS}, + {"flat", MG_FLAT}, + {"light", MG_LIGHT}, + {NULL, 0} }; -FlagDesc flagdesc_ore[] = { - {"absheight", OREFLAG_ABSHEIGHT}, - {"scatter_noisedensity", OREFLAG_DENSITY}, - {"claylike_nodeisnt", OREFLAG_NODEISNT}, - {NULL, 0} +FlagDesc flagdesc_gennotify[] = { + {"dungeon", 1 << GENNOTIFY_DUNGEON}, + {"temple", 1 << GENNOTIFY_TEMPLE}, + {"cave_begin", 1 << GENNOTIFY_CAVE_BEGIN}, + {"cave_end", 1 << GENNOTIFY_CAVE_END}, + {"large_cave_begin", 1 << GENNOTIFY_LARGECAVE_BEGIN}, + {"large_cave_end", 1 << GENNOTIFY_LARGECAVE_END}, + {"decoration", 1 << GENNOTIFY_DECORATION}, + {NULL, 0} }; /////////////////////////////////////////////////////////////////////////////// -Ore *createOre(OreType type) { - switch (type) { - case ORE_SCATTER: - return new OreScatter; - case ORE_SHEET: - return new OreSheet; - //case ORE_CLAYLIKE: //TODO: implement this! - // return new OreClaylike; - default: - return NULL; - } +Mapgen::Mapgen() +{ + generating = false; + id = -1; + seed = 0; + water_level = 0; + flags = 0; + + vm = NULL; + ndef = NULL; + heightmap = NULL; + biomemap = NULL; } -Ore::~Ore() { - delete np; - delete noise; +Mapgen::Mapgen(int mapgenid, MapgenParams *params, EmergeManager *emerge) : + gennotify(emerge->gen_notify_on, &emerge->gen_notify_on_deco_ids) +{ + generating = false; + id = mapgenid; + seed = (int)params->seed; + water_level = params->water_level; + flags = params->flags; + csize = v3s16(1, 1, 1) * (params->chunksize * MAP_BLOCKSIZE); + + vm = NULL; + ndef = NULL; + heightmap = NULL; + biomemap = NULL; } -void Ore::resolveNodeNames(INodeDefManager *ndef) { - if (ore == CONTENT_IGNORE) { - ore = ndef->getId(ore_name); - if (ore == CONTENT_IGNORE) { - errorstream << "Ore::resolveNodeNames: ore node '" - << ore_name << "' not defined"; - ore = CONTENT_AIR; - wherein = CONTENT_AIR; - } - } - - if (wherein == CONTENT_IGNORE) { - wherein = ndef->getId(wherein_name); - if (wherein == CONTENT_IGNORE) { - errorstream << "Ore::resolveNodeNames: wherein node '" - << wherein_name << "' not defined"; - ore = CONTENT_AIR; - wherein = CONTENT_AIR; - } - } +Mapgen::~Mapgen() +{ } -void Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) { - int in_range = 0; +u32 Mapgen::getBlockSeed(v3s16 p, int seed) +{ + return (u32)seed + + p.Z * 38134234 + + p.Y * 42123 + + p.X * 23; +} - in_range |= (nmin.Y <= height_max && nmax.Y >= height_min); - if (flags & OREFLAG_ABSHEIGHT) - in_range |= (nmin.Y >= -height_max && nmax.Y <= -height_min) << 1; - if (!in_range) - return; - resolveNodeNames(mg->ndef); - - int ymin, ymax; - - if (in_range & ORE_RANGE_MIRROR) { - ymin = MYMAX(nmin.Y, -height_max); - ymax = MYMIN(nmax.Y, -height_min); - } else { - ymin = MYMAX(nmin.Y, height_min); - ymax = MYMIN(nmax.Y, height_max); - } - if (clust_size >= ymax - ymin + 1) - return; - - nmin.Y = ymin; - nmax.Y = ymax; - generate(mg->vm, mg->seed, blockseed, nmin, nmax); -} - - -void OreScatter::generate(ManualMapVoxelManipulator *vm, int seed, - u32 blockseed, v3s16 nmin, v3s16 nmax) { - PseudoRandom pr(blockseed); - MapNode n_ore(ore, 0, ore_param2); - - int volume = (nmax.X - nmin.X + 1) * - (nmax.Y - nmin.Y + 1) * - (nmax.Z - nmin.Z + 1); - int csize = clust_size; - int orechance = (csize * csize * csize) / clust_num_ores; - int nclusters = volume / clust_scarcity; - - for (int i = 0; i != nclusters; i++) { - int x0 = pr.range(nmin.X, nmax.X - csize + 1); - int y0 = pr.range(nmin.Y, nmax.Y - csize + 1); - int z0 = pr.range(nmin.Z, nmax.Z - csize + 1); - - if (np && (NoisePerlin3D(np, x0, y0, z0, seed) < nthresh)) - continue; - - for (int z1 = 0; z1 != csize; z1++) - for (int y1 = 0; y1 != csize; y1++) - for (int x1 = 0; x1 != csize; x1++) { - if (pr.range(1, orechance) != 1) - continue; - - u32 i = vm->m_area.index(x0 + x1, y0 + y1, z0 + z1); - if (vm->m_data[i].getContent() == wherein) - vm->m_data[i] = n_ore; - } +u32 Mapgen::getBlockSeed2(v3s16 p, int seed) +{ + u32 n = 1619 * p.X + 31337 * p.Y + 52591 * p.Z + 1013 * seed; + n = (n >> 13) ^ n; + return (n * (n * n * 60493 + 19990303) + 1376312589); +} + + +// Returns Y one under area minimum if not found +s16 Mapgen::findGroundLevelFull(v2s16 p2d) +{ + v3s16 em = vm->m_area.getExtent(); + s16 y_nodes_max = vm->m_area.MaxEdge.Y; + s16 y_nodes_min = vm->m_area.MinEdge.Y; + u32 i = vm->m_area.index(p2d.X, y_nodes_max, p2d.Y); + s16 y; + + for (y = y_nodes_max; y >= y_nodes_min; y--) { + MapNode &n = vm->m_data[i]; + if (ndef->get(n).walkable) + break; + + vm->m_area.add_y(em, i, -1); } + return (y >= y_nodes_min) ? y : y_nodes_min - 1; } -void OreSheet::generate(ManualMapVoxelManipulator *vm, int seed, - u32 blockseed, v3s16 nmin, v3s16 nmax) { - PseudoRandom pr(blockseed + 4234); - MapNode n_ore(ore, 0, ore_param2); - - int max_height = clust_size; - int y_start = pr.range(nmin.Y, nmax.Y - max_height); - - if (!noise) { - int sx = nmax.X - nmin.X + 1; - int sz = nmax.Z - nmin.Z + 1; - noise = new Noise(np, 0, sx, sz); +// Returns -MAP_GENERATION_LIMIT if not found +s16 Mapgen::findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax) +{ + v3s16 em = vm->m_area.getExtent(); + u32 i = vm->m_area.index(p2d.X, ymax, p2d.Y); + s16 y; + + for (y = ymax; y >= ymin; y--) { + MapNode &n = vm->m_data[i]; + if (ndef->get(n).walkable) + break; + + vm->m_area.add_y(em, i, -1); } - noise->seed = seed + y_start; - noise->perlinMap2D(nmin.X, nmin.Z); - + return (y >= ymin) ? y : -MAP_GENERATION_LIMIT; +} + + +void Mapgen::updateHeightmap(v3s16 nmin, v3s16 nmax) +{ + if (!heightmap) + return; + + //TimeTaker t("Mapgen::updateHeightmap", NULL, PRECISION_MICRO); int index = 0; - for (int z = nmin.Z; z <= nmax.Z; z++) - for (int x = nmin.X; x <= nmax.X; x++) { - float noiseval = noise->result[index++]; - if (noiseval < nthresh) - continue; - - int height = max_height * (1. / pr.range(1, 3)); - int y0 = y_start + np->scale * noiseval; //pr.range(1, 3) - 1; - int y1 = y0 + height; - for (int y = y0; y != y1; y++) { - u32 i = vm->m_area.index(x, y, z); - if (!vm->m_area.contains(i)) - continue; - - if (vm->m_data[i].getContent() == wherein) - vm->m_data[i] = n_ore; + for (s16 z = nmin.Z; z <= nmax.Z; z++) { + for (s16 x = nmin.X; x <= nmax.X; x++, index++) { + s16 y = findGroundLevel(v2s16(x, z), nmin.Y, nmax.Y); + + heightmap[index] = y; } } + //printf("updateHeightmap: %dus\n", t.stop()); } -void Mapgen::updateLiquid(UniqueQueue *trans_liquid, v3s16 nmin, v3s16 nmax) { +void Mapgen::updateLiquid(UniqueQueue *trans_liquid, v3s16 nmin, v3s16 nmax) +{ bool isliquid, wasliquid; v3s16 em = vm->m_area.getExtent(); for (s16 z = nmin.Z; z <= nmax.Z; z++) { for (s16 x = nmin.X; x <= nmax.X; x++) { wasliquid = true; - + u32 i = vm->m_area.index(x, nmax.Y, z); for (s16 y = nmax.Y; y >= nmin.Y; y--) { isliquid = ndef->get(vm->m_data[i]).isLiquid(); - - // there was a change between liquid and nonliquid, add to queue + + // there was a change between liquid and nonliquid, add to queue. if (isliquid != wasliquid) trans_liquid->push_back(v3s16(x, y, z)); @@ -225,7 +199,8 @@ void Mapgen::updateLiquid(UniqueQueue *trans_liquid, v3s16 nmin, v3s16 nm } -void Mapgen::setLighting(v3s16 nmin, v3s16 nmax, u8 light) { +void Mapgen::setLighting(u8 light, v3s16 nmin, v3s16 nmax) +{ ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG); VoxelArea a(nmin, nmax); @@ -239,10 +214,11 @@ void Mapgen::setLighting(v3s16 nmin, v3s16 nmax, u8 light) { } -void Mapgen::lightSpread(VoxelArea &a, v3s16 p, u8 light) { +void Mapgen::lightSpread(VoxelArea &a, v3s16 p, u8 light) +{ if (light <= 1 || !a.contains(p)) return; - + u32 vi = vm->m_area.index(p); MapNode &nn = vm->m_data[vi]; @@ -250,9 +226,9 @@ void Mapgen::lightSpread(VoxelArea &a, v3s16 p, u8 light) { // should probably compare masked, but doesn't seem to make a difference if (light <= nn.param1 || !ndef->get(nn).light_propagates) return; - + nn.param1 = light; - + lightSpread(a, p + v3s16(0, 0, 1), light); lightSpread(a, p + v3s16(0, 1, 0), light); lightSpread(a, p + v3s16(1, 0, 0), light); @@ -262,15 +238,43 @@ void Mapgen::lightSpread(VoxelArea &a, v3s16 p, u8 light) { } -void Mapgen::calcLighting(v3s16 nmin, v3s16 nmax) { - VoxelArea a(nmin, nmax); - bool block_is_underground = (water_level >= nmax.Y); +void Mapgen::calcLighting(v3s16 nmin, v3s16 nmax, v3s16 full_nmin, v3s16 full_nmax) +{ + ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG); + //TimeTaker t("updateLighting"); + + propagateSunlight(nmin, nmax); + spreadLight(full_nmin, full_nmax); + + //printf("updateLighting: %dms\n", t.stop()); +} + + +void Mapgen::calcLighting(v3s16 nmin, v3s16 nmax) +{ ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG); //TimeTaker t("updateLighting"); - // first, send vertical rays of sunshine downward + propagateSunlight( + nmin - v3s16(1, 1, 1) * MAP_BLOCKSIZE, + nmax + v3s16(1, 0, 1) * MAP_BLOCKSIZE); + + spreadLight( + nmin - v3s16(1, 1, 1) * MAP_BLOCKSIZE, + nmax + v3s16(1, 1, 1) * MAP_BLOCKSIZE); + + //printf("updateLighting: %dms\n", t.stop()); +} + + +void Mapgen::propagateSunlight(v3s16 nmin, v3s16 nmax) +{ + //TimeTaker t("propagateSunlight"); + VoxelArea a(nmin, nmax); + bool block_is_underground = (water_level >= nmax.Y); v3s16 em = vm->m_area.getExtent(); + for (int z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++) { for (int x = a.MinEdge.X; x <= a.MaxEdge.X; x++) { // see if we can get a light value from the overtop @@ -292,8 +296,16 @@ void Mapgen::calcLighting(v3s16 nmin, v3s16 nmax) { } } } - - // now spread the sunlight and light up any sources + //printf("propagateSunlight: %dms\n", t.stop()); +} + + + +void Mapgen::spreadLight(v3s16 nmin, v3s16 nmax) +{ + //TimeTaker t("spreadLight"); + VoxelArea a(nmin, nmax); + for (int z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++) { for (int y = a.MinEdge.Y; y <= a.MaxEdge.Y; y++) { u32 i = vm->m_area.index(a.MinEdge.X, y, z); @@ -302,11 +314,11 @@ void Mapgen::calcLighting(v3s16 nmin, v3s16 nmax) { if (n.getContent() == CONTENT_IGNORE || !ndef->get(n).light_propagates) continue; - + u8 light_produced = ndef->get(n).light_source & 0x0F; if (light_produced) n.param1 = light_produced; - + u8 light = n.param1 & 0x0F; if (light) { lightSpread(a, v3s16(x, y, z + 1), light); @@ -319,26 +331,28 @@ void Mapgen::calcLighting(v3s16 nmin, v3s16 nmax) { } } } - - //printf("updateLighting: %dms\n", t.stop()); + + //printf("spreadLight: %dms\n", t.stop()); } -void Mapgen::calcLightingOld(v3s16 nmin, v3s16 nmax) { + +void Mapgen::calcLightingOld(v3s16 nmin, v3s16 nmax) +{ enum LightBank banks[2] = {LIGHTBANK_DAY, LIGHTBANK_NIGHT}; VoxelArea a(nmin, nmax); bool block_is_underground = (water_level > nmax.Y); bool sunlight = !block_is_underground; ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG); - + for (int i = 0; i < 2; i++) { enum LightBank bank = banks[i]; std::set light_sources; std::map unlight_from; voxalgo::clearLightAndCollectSources(*vm, a, bank, ndef, - light_sources, unlight_from); + light_sources, unlight_from); voxalgo::propagateSunlight(*vm, a, sunlight, light_sources, ndef); vm->unspreadLight(bank, unlight_from, light_sources, ndef); @@ -347,94 +361,267 @@ void Mapgen::calcLightingOld(v3s16 nmin, v3s16 nmax) { } -//////////////////////// Mapgen V6 parameter read/write +/////////////////////////////////////////////////////////////////////////////// + +GenerateNotifier::GenerateNotifier() +{ + m_notify_on = 0; +} -bool MapgenV6Params::readParams(Settings *settings) { - freq_desert = settings->getFloat("mgv6_freq_desert"); - freq_beach = settings->getFloat("mgv6_freq_beach"); - bool success = - settings->getNoiseParams("mgv6_np_terrain_base", np_terrain_base) && - settings->getNoiseParams("mgv6_np_terrain_higher", np_terrain_higher) && - settings->getNoiseParams("mgv6_np_steepness", np_steepness) && - settings->getNoiseParams("mgv6_np_height_select", np_height_select) && - settings->getNoiseParams("mgv6_np_mud", np_mud) && - settings->getNoiseParams("mgv6_np_beach", np_beach) && - settings->getNoiseParams("mgv6_np_biome", np_biome) && - settings->getNoiseParams("mgv6_np_cave", np_cave) && - settings->getNoiseParams("mgv6_np_humidity", np_humidity) && - settings->getNoiseParams("mgv6_np_trees", np_trees) && - settings->getNoiseParams("mgv6_np_apple_trees", np_apple_trees); - return success; +GenerateNotifier::GenerateNotifier(u32 notify_on, + std::set *notify_on_deco_ids) +{ + m_notify_on = notify_on; + m_notify_on_deco_ids = notify_on_deco_ids; } -void MapgenV6Params::writeParams(Settings *settings) { - settings->setFloat("mgv6_freq_desert", freq_desert); - settings->setFloat("mgv6_freq_beach", freq_beach); - - settings->setNoiseParams("mgv6_np_terrain_base", np_terrain_base); - settings->setNoiseParams("mgv6_np_terrain_higher", np_terrain_higher); - settings->setNoiseParams("mgv6_np_steepness", np_steepness); - settings->setNoiseParams("mgv6_np_height_select", np_height_select); - settings->setNoiseParams("mgv6_np_mud", np_mud); - settings->setNoiseParams("mgv6_np_beach", np_beach); - settings->setNoiseParams("mgv6_np_biome", np_biome); - settings->setNoiseParams("mgv6_np_cave", np_cave); - settings->setNoiseParams("mgv6_np_humidity", np_humidity); - settings->setNoiseParams("mgv6_np_trees", np_trees); - settings->setNoiseParams("mgv6_np_apple_trees", np_apple_trees); +void GenerateNotifier::setNotifyOn(u32 notify_on) +{ + m_notify_on = notify_on; } -bool MapgenV7Params::readParams(Settings *settings) { - bool success = - settings->getNoiseParams("mgv7_np_terrain_base", np_terrain_base) && - settings->getNoiseParams("mgv7_np_terrain_alt", np_terrain_alt) && - settings->getNoiseParams("mgv7_np_terrain_mod", np_terrain_mod) && - settings->getNoiseParams("mgv7_np_terrain_persist", np_terrain_persist) && - settings->getNoiseParams("mgv7_np_height_select", np_height_select) && - settings->getNoiseParams("mgv7_np_ridge", np_ridge); - return success; +void GenerateNotifier::setNotifyOnDecoIds(std::set *notify_on_deco_ids) +{ + m_notify_on_deco_ids = notify_on_deco_ids; } -void MapgenV7Params::writeParams(Settings *settings) { - settings->setNoiseParams("mgv7_np_terrain_base", np_terrain_base); - settings->setNoiseParams("mgv7_np_terrain_alt", np_terrain_alt); - settings->setNoiseParams("mgv7_np_terrain_mod", np_terrain_mod); - settings->setNoiseParams("mgv7_np_terrain_persist", np_terrain_persist); - settings->setNoiseParams("mgv7_np_height_select", np_height_select); - settings->setNoiseParams("mgv7_np_ridge", np_ridge); +bool GenerateNotifier::addEvent(GenNotifyType type, v3s16 pos, u32 id) +{ + if (!(m_notify_on & (1 << type))) + return false; + + if (type == GENNOTIFY_DECORATION && + m_notify_on_deco_ids->find(id) == m_notify_on_deco_ids->end()) + return false; + + GenNotifyEvent gne; + gne.type = type; + gne.pos = pos; + gne.id = id; + m_notify_events.push_back(gne); + + return true; +} + + +void GenerateNotifier::getEvents( + std::map > &event_map, + bool peek_events) +{ + std::list::iterator it; + + for (it = m_notify_events.begin(); it != m_notify_events.end(); ++it) { + GenNotifyEvent &gn = *it; + std::string name = (gn.type == GENNOTIFY_DECORATION) ? + "decoration#"+ itos(gn.id) : + flagdesc_gennotify[gn.type].name; + + event_map[name].push_back(gn.pos); + } + + if (!peek_events) + m_notify_events.clear(); +} + + +/////////////////////////////////////////////////////////////////////////////// + + +ObjDefManager::ObjDefManager(IGameDef *gamedef, ObjDefType type) +{ + m_objtype = type; + m_ndef = gamedef->getNodeDefManager(); +} + + +ObjDefManager::~ObjDefManager() +{ + for (size_t i = 0; i != m_objects.size(); i++) + delete m_objects[i]; +} + + +ObjDefHandle ObjDefManager::add(ObjDef *obj) +{ + assert(obj); + + if (obj->name.length() && getByName(obj->name)) + return OBJDEF_INVALID_HANDLE; + + u32 index = addRaw(obj); + if (index == OBJDEF_INVALID_INDEX) + return OBJDEF_INVALID_HANDLE; + + obj->handle = createHandle(index, m_objtype, obj->uid); + return obj->handle; +} + + +ObjDef *ObjDefManager::get(ObjDefHandle handle) const +{ + u32 index = validateHandle(handle); + return (index != OBJDEF_INVALID_INDEX) ? getRaw(index) : NULL; +} + + +ObjDef *ObjDefManager::set(ObjDefHandle handle, ObjDef *obj) +{ + u32 index = validateHandle(handle); + return (index != OBJDEF_INVALID_INDEX) ? setRaw(index, obj) : NULL; +} + + +u32 ObjDefManager::addRaw(ObjDef *obj) +{ + size_t nobjects = m_objects.size(); + if (nobjects >= OBJDEF_MAX_ITEMS) + return -1; + + obj->index = nobjects; + + // Ensure UID is nonzero so that a valid handle == OBJDEF_INVALID_HANDLE + // is not possible. The slight randomness bias isn't very significant. + obj->uid = myrand() & OBJDEF_UID_MASK; + if (obj->uid == 0) + obj->uid = 1; + + m_objects.push_back(obj); + + infostream << "ObjDefManager: added " << getObjectTitle() + << ": name=\"" << obj->name + << "\" index=" << obj->index + << " uid=" << obj->uid + << std::endl; + + return nobjects; +} + + +ObjDef *ObjDefManager::getRaw(u32 index) const +{ + return m_objects[index]; +} + + +ObjDef *ObjDefManager::setRaw(u32 index, ObjDef *obj) +{ + ObjDef *old_obj = m_objects[index]; + m_objects[index] = obj; + return old_obj; +} + + +ObjDef *ObjDefManager::getByName(const std::string &name) const +{ + for (size_t i = 0; i != m_objects.size(); i++) { + ObjDef *obj = m_objects[i]; + if (obj && !strcasecmp(name.c_str(), obj->name.c_str())) + return obj; + } + + return NULL; +} + + +void ObjDefManager::clear() +{ + for (size_t i = 0; i != m_objects.size(); i++) + delete m_objects[i]; + + m_objects.clear(); } -/////////////////////////////////// legacy static functions for farmesh +u32 ObjDefManager::validateHandle(ObjDefHandle handle) const +{ + ObjDefType type; + u32 index; + u32 uid; + bool is_valid = + (handle != OBJDEF_INVALID_HANDLE) && + decodeHandle(handle, &index, &type, &uid) && + (type == m_objtype) && + (index < m_objects.size()) && + (m_objects[index]->uid == uid); -s16 Mapgen::find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision) { - //just need to return something - s16 level = 5; - return level; + return is_valid ? index : -1; } -bool Mapgen::get_have_beach(u64 seed, v2s16 p2d) { - double sandnoise = noise2d_perlin( - 0.2+(float)p2d.X/250, 0.7+(float)p2d.Y/250, - seed+59420, 3, 0.50); +ObjDefHandle ObjDefManager::createHandle(u32 index, ObjDefType type, u32 uid) +{ + ObjDefHandle handle = 0; + set_bits(&handle, 0, 18, index); + set_bits(&handle, 18, 6, type); + set_bits(&handle, 24, 7, uid); + + u32 parity = calc_parity(handle); + set_bits(&handle, 31, 1, parity); - return (sandnoise > 0.15); + return handle ^ OBJDEF_HANDLE_SALT; } -double Mapgen::tree_amount_2d(u64 seed, v2s16 p) { - double noise = noise2d_perlin( - 0.5+(float)p.X/125, 0.5+(float)p.Y/125, - seed+2, 4, 0.66); - double zeroval = -0.39; - if(noise < zeroval) - return 0; +bool ObjDefManager::decodeHandle(ObjDefHandle handle, u32 *index, + ObjDefType *type, u32 *uid) +{ + handle ^= OBJDEF_HANDLE_SALT; + + u32 parity = get_bits(handle, 31, 1); + set_bits(&handle, 31, 1, 0); + if (parity != calc_parity(handle)) + return false; + + *index = get_bits(handle, 0, 18); + *type = (ObjDefType)get_bits(handle, 18, 6); + *uid = get_bits(handle, 24, 7); + return true; +} + + +/////////////////////////////////////////////////////////////////////////////// + + +void MapgenParams::load(const Settings &settings) +{ + std::string seed_str; + const char *seed_name = (&settings == g_settings) ? "fixed_map_seed" : "seed"; + + if (settings.getNoEx(seed_name, seed_str) && !seed_str.empty()) + seed = read_seed(seed_str.c_str()); else - return 0.04 * (noise-zeroval) / (1.0-zeroval); + myrand_bytes(&seed, sizeof(seed)); + + settings.getNoEx("mg_name", mg_name); + settings.getS16NoEx("water_level", water_level); + settings.getS16NoEx("chunksize", chunksize); + settings.getFlagStrNoEx("mg_flags", flags, flagdesc_mapgen); + settings.getNoiseParams("mg_biome_np_heat", np_biome_heat); + settings.getNoiseParams("mg_biome_np_humidity", np_biome_humidity); + + delete sparams; + sparams = EmergeManager::createMapgenParams(mg_name); + if (sparams) + sparams->readParams(&settings); +} + + +void MapgenParams::save(Settings &settings) const +{ + settings.set("mg_name", mg_name); + settings.setU64("seed", seed); + settings.setS16("water_level", water_level); + settings.setS16("chunksize", chunksize); + settings.setFlagStr("mg_flags", flags, flagdesc_mapgen, (u32)-1); + settings.setNoiseParams("mg_biome_np_heat", np_biome_heat); + settings.setNoiseParams("mg_biome_np_humidity", np_biome_humidity); + + if (sparams) + sparams->writeParams(&settings); } +