X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fmapgen_v6.cpp;h=a212496a8bca679144bf4fc392c1363c057d4836;hb=58e6d25e033c76dc91aaac18fdeda92ac23fe0e1;hp=4a037bb8595454ecc9eb87eedb3260dcb4894cde;hpb=96e2931c5c154262566359495d4a0b8515376947;p=oweals%2Fminetest.git diff --git a/src/mapgen_v6.cpp b/src/mapgen_v6.cpp index 4a037bb85..a212496a8 100644 --- a/src/mapgen_v6.cpp +++ b/src/mapgen_v6.cpp @@ -33,64 +33,51 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "main.h" // For g_profiler #include "emerge.h" #include "dungeongen.h" +#include "cavegen.h" #include "treegen.h" #include "mapgen_v6.h" -/////////////////// Mapgen V6 perlin noise default values -NoiseParams nparams_v6_def_terrain_base = - {-AVERAGE_MUD_AMOUNT, 20.0, v3f(250.0, 250.0, 250.0), 82341, 5, 0.6}; -NoiseParams nparams_v6_def_terrain_higher = - {20.0, 16.0, v3f(500.0, 500.0, 500.0), 85039, 5, 0.6}; -NoiseParams nparams_v6_def_steepness = - {0.85, 0.5, v3f(125.0, 125.0, 125.0), -932, 5, 0.7}; -NoiseParams nparams_v6_def_height_select = - {0.5, 1.0, v3f(250.0, 250.0, 250.0), 4213, 5, 0.69}; -NoiseParams nparams_v6_def_mud = - {AVERAGE_MUD_AMOUNT, 2.0, v3f(200.0, 200.0, 200.0), 91013, 3, 0.55}; -NoiseParams nparams_v6_def_beach = - {0.0, 1.0, v3f(250.0, 250.0, 250.0), 59420, 3, 0.50}; -NoiseParams nparams_v6_def_biome = - {0.0, 1.0, v3f(250.0, 250.0, 250.0), 9130, 3, 0.50}; -NoiseParams nparams_v6_def_cave = - {6.0, 6.0, v3f(250.0, 250.0, 250.0), 34329, 3, 0.50}; -NoiseParams nparams_v6_def_humidity = - {0.5, 0.5, v3f(500.0, 500.0, 500.0), 72384, 4, 0.66}; -NoiseParams nparams_v6_def_trees = - {0.0, 1.0, v3f(125.0, 125.0, 125.0), 2, 4, 0.66}; -NoiseParams nparams_v6_def_apple_trees = - {0.0, 1.0, v3f(100.0, 100.0, 100.0), 342902, 3, 0.45}; - +FlagDesc flagdesc_mapgen_v6[] = { + {"jungles", MGV6_JUNGLES}, + {"biomeblend", MGV6_BIOMEBLEND}, + {"mudflow", MGV6_MUDFLOW}, + {NULL, 0} +}; /////////////////////////////////////////////////////////////////////////////// -MapgenV6::MapgenV6(int mapgenid, MapgenV6Params *params, EmergeManager *emerge) { +MapgenV6::MapgenV6(int mapgenid, MapgenParams *params, EmergeManager *emerge) { this->generating = false; this->id = mapgenid; this->emerge = emerge; - this->seed = (int)params->seed; + this->seed = (int)params->seed; this->water_level = params->water_level; - this->flags = params->flags; - this->csize = v3s16(1, 1, 1) * params->chunksize * MAP_BLOCKSIZE; - - this->freq_desert = params->freq_desert; - this->freq_beach = params->freq_beach; + this->flags = params->flags; + this->csize = v3s16(1, 1, 1) * params->chunksize * MAP_BLOCKSIZE; + this->gennotify = emerge->gennotify; this->ystride = csize.X; //////fix this - - np_cave = params->np_cave; - np_humidity = params->np_humidity; - np_trees = params->np_trees; - np_apple_trees = params->np_apple_trees; - - noise_terrain_base = new Noise(params->np_terrain_base, seed, csize.X, csize.Y); - noise_terrain_higher = new Noise(params->np_terrain_higher, seed, csize.X, csize.Y); - noise_steepness = new Noise(params->np_steepness, seed, csize.X, csize.Y); - noise_height_select = new Noise(params->np_height_select, seed, csize.X, csize.Y); - noise_mud = new Noise(params->np_mud, seed, csize.X, csize.Y); - noise_beach = new Noise(params->np_beach, seed, csize.X, csize.Y); - noise_biome = new Noise(params->np_biome, seed, csize.X, csize.Y); + + MapgenV6Params *sp = (MapgenV6Params *)params->sparams; + + this->spflags = sp->spflags; + this->freq_desert = sp->freq_desert; + this->freq_beach = sp->freq_beach; + + np_cave = &sp->np_cave; + np_humidity = &sp->np_humidity; + np_trees = &sp->np_trees; + np_apple_trees = &sp->np_apple_trees; + + noise_terrain_base = new Noise(&sp->np_terrain_base, seed, csize.X, csize.Y); + noise_terrain_higher = new Noise(&sp->np_terrain_higher, seed, csize.X, csize.Y); + noise_steepness = new Noise(&sp->np_steepness, seed, csize.X, csize.Y); + noise_height_select = new Noise(&sp->np_height_select, seed, csize.X, csize.Y); + noise_mud = new Noise(&sp->np_mud, seed, csize.X, csize.Y); + noise_beach = new Noise(&sp->np_beach, seed, csize.X, csize.Y); + noise_biome = new Noise(&sp->np_biome, seed, csize.X, csize.Y); } @@ -105,26 +92,66 @@ MapgenV6::~MapgenV6() { } -//////////////////////// Some helper functions for the map generator +MapgenV6Params::MapgenV6Params() { + spflags = MGV6_BIOMEBLEND | MGV6_MUDFLOW; + freq_desert = 0.45; + freq_beach = 0.15; + + np_terrain_base = NoiseParams(-4, 20.0, v3f(250.0, 250.0, 250.0), 82341, 5, 0.6); + np_terrain_higher = NoiseParams(20, 16.0, v3f(500.0, 500.0, 500.0), 85039, 5, 0.6); + np_steepness = NoiseParams(0.85,0.5, v3f(125.0, 125.0, 125.0), -932, 5, 0.7); + np_height_select = NoiseParams(0.5, 1.0, v3f(250.0, 250.0, 250.0), 4213, 5, 0.69); + np_mud = NoiseParams(4, 2.0, v3f(200.0, 200.0, 200.0), 91013, 3, 0.55); + np_beach = NoiseParams(0, 1.0, v3f(250.0, 250.0, 250.0), 59420, 3, 0.50); + np_biome = NoiseParams(0, 1.0, v3f(250.0, 250.0, 250.0), 9130, 3, 0.50); + np_cave = NoiseParams(6, 6.0, v3f(250.0, 250.0, 250.0), 34329, 3, 0.50); + np_humidity = NoiseParams(0.5, 0.5, v3f(500.0, 500.0, 500.0), 72384, 4, 0.66); + np_trees = NoiseParams(0, 1.0, v3f(125.0, 125.0, 125.0), 2, 4, 0.66); + np_apple_trees = NoiseParams(0, 1.0, v3f(100.0, 100.0, 100.0), 342902, 3, 0.45); +} -// Returns Y one under area minimum if not found -s16 MapgenV6::find_ground_level(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 MapgenV6Params::readParams(Settings *settings) { + settings->getFlagStrNoEx("mgv6_spflags", spflags, flagdesc_mapgen_v6); + settings->getFloatNoEx("mgv6_freq_desert", freq_desert); + settings->getFloatNoEx("mgv6_freq_beach", freq_beach); + + 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); } + +void MapgenV6Params::writeParams(Settings *settings) { + settings->setFlagStr("mgv6_spflags", spflags, flagdesc_mapgen_v6, (u32)-1); + 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); +} + + +//////////////////////// Some helper functions for the map generator + + // Returns Y one under area minimum if not found s16 MapgenV6::find_stone_level(v2s16 p2d) { v3s16 em = vm->m_area.getExtent(); @@ -165,8 +192,8 @@ bool MapgenV6::block_is_underground(u64 seed, v3s16 blockpos) float MapgenV6::baseTerrainLevel(float terrain_base, float terrain_higher, float steepness, float height_select) { - float base = water_level + terrain_base; - float higher = water_level + terrain_higher; + float base = 1 + terrain_base; + float higher = 1 + terrain_higher; // Limit higher ground level to at least base if(higher < base) @@ -338,7 +365,7 @@ BiomeType MapgenV6::getBiome(int index, v2s16 p) if (d > freq_desert) return BT_DESERT; - if ((flags & 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; @@ -374,8 +401,6 @@ void MapgenV6::makeChunk(BlockMakeData *data) { v3s16 blockpos = data->blockpos_requested; v3s16 blockpos_min = data->blockpos_min; v3s16 blockpos_max = data->blockpos_max; - v3s16 blockpos_full_min = blockpos_min - v3s16(1,1,1); - v3s16 blockpos_full_max = blockpos_max + v3s16(1,1,1); // Area of central chunk node_min = blockpos_min*MAP_BLOCKSIZE; @@ -411,10 +436,22 @@ void MapgenV6::makeChunk(BlockMakeData *data) { c_cobble = ndef->getId("mapgen_cobble"); c_desert_sand = ndef->getId("mapgen_desert_sand"); c_desert_stone = ndef->getId("mapgen_desert_stone"); + c_mossycobble = ndef->getId("mapgen_mossycobble"); + c_sandbrick = ndef->getId("mapgen_sandstonebrick"); + c_stair_cobble = ndef->getId("mapgen_stair_cobble"); + c_stair_sandstone = ndef->getId("mapgen_stair_sandstone"); if (c_desert_sand == CONTENT_IGNORE) c_desert_sand = c_sand; if (c_desert_stone == CONTENT_IGNORE) c_desert_stone = c_stone; + if (c_mossycobble == CONTENT_IGNORE) + c_mossycobble = c_cobble; + if (c_sandbrick == CONTENT_IGNORE) + c_sandbrick = c_desert_stone; + if (c_stair_cobble == CONTENT_IGNORE) + c_stair_cobble = c_cobble; + if (c_stair_sandstone == CONTENT_IGNORE) + c_stair_sandstone = c_sandbrick; // Maximum height of the stone surface and obstacles. // This is used to guide the cave generation @@ -423,7 +460,7 @@ void MapgenV6::makeChunk(BlockMakeData *data) { // Generate general ground level to full area stone_surface_max_y = generateGround(); - generateSomething(); + generateExperimental(); const s16 max_spread_amount = MAP_BLOCKSIZE; // Limit dirt flow area by 1 because mud is flown into neighbors. @@ -444,14 +481,43 @@ void MapgenV6::makeChunk(BlockMakeData *data) { addDirtGravelBlobs(); // Flow mud away from steep edges - flowMud(mudflow_minpos, mudflow_maxpos); + if (spflags & MGV6_MUDFLOW) + flowMud(mudflow_minpos, mudflow_maxpos); } // Add dungeons if (flags & MG_DUNGEONS) { - DungeonGen dgen(ndef, data->seed, water_level); - dgen.generate(vm, blockseed, full_node_min, full_node_max); + DungeonParams dp; + + dp.np_rarity = nparams_dungeon_rarity; + dp.np_density = nparams_dungeon_density; + dp.np_wetness = nparams_dungeon_wetness; + dp.c_water = c_water_source; + if (getBiome(0, v2s16(node_min.X, node_min.Z)) == BT_NORMAL) { + dp.c_cobble = c_cobble; + dp.c_moss = c_mossycobble; + dp.c_stair = c_stair_cobble; + + dp.diagonal_dirs = false; + dp.mossratio = 3.0; + dp.holesize = v3s16(1, 2, 1); + dp.roomsize = v3s16(0, 0, 0); + dp.notifytype = GENNOTIFY_DUNGEON; + } else { + dp.c_cobble = c_sandbrick; + dp.c_moss = c_sandbrick; // should make this 'cracked sandstone' later + dp.c_stair = c_stair_sandstone; + + dp.diagonal_dirs = true; + dp.mossratio = 0.0; + dp.holesize = v3s16(2, 3, 2); + dp.roomsize = v3s16(2, 5, 2); + dp.notifytype = GENNOTIFY_TEMPLE; + } + + DungeonGen dgen(this, &dp); + dgen.generate(blockseed, full_node_min, full_node_max); } // Add top and bottom side of water to transforming_liquid queue @@ -463,16 +529,23 @@ void MapgenV6::makeChunk(BlockMakeData *data) { // Generate some trees, and add grass, if a jungle if (flags & MG_TREES) placeTreesAndJungleGrass(); + + // Generate the registered decorations + for (unsigned int i = 0; i != emerge->decorations.size(); i++) { + Decoration *deco = emerge->decorations[i]; + deco->placeDeco(this, blockseed + i, node_min, node_max); + } // Generate the registered ores for (unsigned int i = 0; i != emerge->ores.size(); i++) { Ore *ore = emerge->ores[i]; - ore->generate(this, blockseed + i, node_min, node_max); + ore->placeOre(this, blockseed + i, node_min, node_max); } // Calculate lighting - calcLighting(node_min - v3s16(1, 1, 1) * MAP_BLOCKSIZE, - node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE); + if (flags & MG_LIGHT) + calcLighting(node_min - v3s16(1, 1, 1) * MAP_BLOCKSIZE, + node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE); this->generating = false; } @@ -835,7 +908,7 @@ void MapgenV6::placeTreesAndJungleGrass() { float humidity; bool is_jungle = false; - if (flags & MGV6_JUNGLES) { + if (spflags & MGV6_JUNGLES) { humidity = getHumidity(p2d_center); if (humidity > 0.75) { is_jungle = true; @@ -850,7 +923,7 @@ void MapgenV6::placeTreesAndJungleGrass() { s16 x = grassrandom.range(p2d_min.X, p2d_max.X); s16 z = grassrandom.range(p2d_min.Y, p2d_max.Y); - s16 y = find_ground_level(v2s16(x, z)); ////////////////optimize this! + s16 y = findGroundLevelFull(v2s16(x, z)); ////////////////optimize this! if (y < water_level || y < node_min.Y || y > node_max.Y) continue; @@ -867,7 +940,7 @@ void MapgenV6::placeTreesAndJungleGrass() { for (u32 i = 0; i < tree_count; i++) { s16 x = myrand_range(p2d_min.X, p2d_max.X); s16 z = myrand_range(p2d_min.Y, p2d_max.Y); - s16 y = find_ground_level(v2s16(x, z)); ////////////////////optimize this! + s16 y = findGroundLevelFull(v2s16(x, z)); ////////////////////optimize this! // Don't make a tree under water level // Don't make a tree so high that it doesn't fit if(y < water_level || y > node_max.Y - 6) @@ -927,35 +1000,10 @@ void MapgenV6::growGrass() { } -void MapgenV6::defineCave(Cave &cave, PseudoRandom ps, - v3s16 node_min, bool large_cave) { - cave.min_tunnel_diameter = 2; - cave.max_tunnel_diameter = ps.range(2,6); - cave.dswitchint = ps.range(1,14); - cave.flooded = true; //large_cave && ps.range(0,4); - if (large_cave){ - cave.part_max_length_rs = ps.range(2,4); - cave.tunnel_routepoints = ps.range(5, ps.range(15,30)); - cave.min_tunnel_diameter = 5; - cave.max_tunnel_diameter = ps.range(7, ps.range(8,24)); - } else { - cave.part_max_length_rs = ps.range(2,9); - cave.tunnel_routepoints = ps.range(10, ps.range(15,30)); - } - cave.large_cave_is_flat = (ps.range(0,1) == 0); -} - - void MapgenV6::generateCaves(int max_stone_y) { - // 24ms @cs=8 - //TimeTaker timer1("caves"); - - /*double cave_amount = 6.0 + 6.0 * noise2d_perlin( - 0.5+(double)node_min.X/250, 0.5+(double)node_min.Y/250, - data->seed+34329, 3, 0.50);*/ - const s16 max_spread_amount = MAP_BLOCKSIZE; float cave_amount = NoisePerlin2D(np_cave, node_min.X, node_min.Y, seed); - + int volume_nodes = (node_max.X - node_min.X + 1) * + (node_max.Y - node_min.Y + 1) * MAP_BLOCKSIZE; cave_amount = MYMAX(0.0, cave_amount); u32 caves_count = cave_amount * volume_nodes / 50000; u32 bruises_count = 1; @@ -970,238 +1018,10 @@ void MapgenV6::generateCaves(int max_stone_y) { bruises_count /= 3; } - for(u32 jj = 0; jj < caves_count + bruises_count; jj++) { - /*int avg_height = (int) - ((base_rock_level_2d(data->seed, v2s16(node_min.X, node_min.Z)) + - base_rock_level_2d(data->seed, v2s16(node_max.X, node_max.Z))) / 2); - if ((node_max.Y + node_min.Y) / 2 > avg_height) - break;*/ - - bool large_cave = (jj >= caves_count); - - Cave cave; - defineCave(cave, ps, node_min, large_cave); - - v3f main_direction(0,0,0); - - // Allowed route area size in nodes - v3s16 ar = central_area_size; + for (u32 i = 0; i < caves_count + bruises_count; i++) { + bool large_cave = (i >= caves_count); + CaveV6 cave(this, &ps, &ps2, large_cave); - // Area starting point in nodes - v3s16 of = node_min; - - // Allow a bit more - //(this should be more than the maximum radius of the tunnel) - s16 insure = 10; - s16 more = max_spread_amount - cave.max_tunnel_diameter / 2 - insure; - ar += v3s16(1,0,1) * more * 2; - of -= v3s16(1,0,1) * more; - - s16 route_y_min = 0; - // Allow half a diameter + 7 over stone surface - s16 route_y_max = -of.Y + max_stone_y + cave.max_tunnel_diameter/2 + 7; - - // Limit maximum to area - route_y_max = rangelim(route_y_max, 0, ar.Y-1); - - if(large_cave) - { - s16 min = 0; - if(node_min.Y < water_level && node_max.Y > water_level) - { - min = water_level - cave.max_tunnel_diameter/3 - of.Y; - route_y_max = water_level + cave.max_tunnel_diameter/3 - of.Y; - } - route_y_min = ps.range(min, min + cave.max_tunnel_diameter); - route_y_min = rangelim(route_y_min, 0, route_y_max); - } - - s16 route_start_y_min = route_y_min; - s16 route_start_y_max = route_y_max; - - route_start_y_min = rangelim(route_start_y_min, 0, ar.Y-1); - route_start_y_max = rangelim(route_start_y_max, route_start_y_min, ar.Y-1); - - // Randomize starting position - v3f orp( - (float)(ps.next()%ar.X)+0.5, - (float)(ps.range(route_start_y_min, route_start_y_max))+0.5, - (float)(ps.next()%ar.Z)+0.5 - ); - - v3s16 startp(orp.X, orp.Y, orp.Z); - startp += of; - - MapNode airnode(CONTENT_AIR); - MapNode waternode(c_water_source); - MapNode lavanode(c_lava_source); - - /* - Generate some tunnel starting from orp - */ - - for(u16 j=0; j= ar.X) - rp.X = ar.X-1; - if(rp.Y < route_y_min) - rp.Y = route_y_min; - else if(rp.Y >= route_y_max) - rp.Y = route_y_max-1; - if(rp.Z < 0) - rp.Z = 0; - else if(rp.Z >= ar.Z) - rp.Z = ar.Z-1; - vec = rp - orp; - - float veclen = vec.getLength(); - // As odd as it sounds, veclen is *exactly* - // 0.0 sometimes, causing a FPE - if (veclen == 0.0) - veclen = 1.0; - - for(float f=0; f<1.0; f+=1.0/veclen) - { - v3f fp = orp + vec * f; - fp.X += 0.1*ps.range(-10,10); - fp.Z += 0.1*ps.range(-10,10); - v3s16 cp(fp.X, fp.Y, fp.Z); - - s16 d0 = -rs/2; - s16 d1 = d0 + rs; - if(randomize_xz){ - d0 += ps.range(-1,1); - d1 += ps.range(-1,1); - } - for(s16 z0=d0; z0<=d1; z0++) - { - s16 si = rs/2 - MYMAX(0, abs(z0)-rs/7-1); - for(s16 x0=-si-ps.range(0,1); x0<=si-1+ps.range(0,1); x0++) - { - s16 maxabsxz = MYMAX(abs(x0), abs(z0)); - s16 si2 = rs/2 - MYMAX(0, maxabsxz-rs/7-1); - for(s16 y0=-si2; y0<=si2; y0++) - { - /*// Make better floors in small caves - if(y0 <= -rs/2 && rs<=7) - continue;*/ - if (cave.large_cave_is_flat) { - // Make large caves not so tall - if (rs > 7 && abs(y0) >= rs/3) - continue; - } - - s16 z = cp.Z + z0; - s16 y = cp.Y + y0; - s16 x = cp.X + x0; - v3s16 p(x,y,z); - p += of; - - if(vm->m_area.contains(p) == false) - continue; - - u32 i = vm->m_area.index(p); - - if(large_cave) { - if (cave.flooded && full_node_min.Y < water_level && - full_node_max.Y > water_level) { - if (p.Y <= water_level) - vm->m_data[i] = waternode; - else - vm->m_data[i] = airnode; - } else if (cave.flooded && full_node_max.Y < water_level) { - if (p.Y < startp.Y - 2) - vm->m_data[i] = lavanode; - else - vm->m_data[i] = airnode; - } else { - vm->m_data[i] = airnode; - } - } else { - // Don't replace air or water or lava or ignore - if (vm->m_data[i].getContent() == CONTENT_IGNORE || - vm->m_data[i].getContent() == CONTENT_AIR || - vm->m_data[i].getContent() == c_water_source || - vm->m_data[i].getContent() == c_lava_source) - continue; - - vm->m_data[i] = airnode; - - // Set tunnel flag - vm->m_flags[i] |= VMANIP_FLAG_CAVE; - } - } - } - } - } - orp = rp; - } + cave.makeCave(node_min, node_max, max_stone_y); } }