void MapgenV6::placeTreesAndJungleGrass() { //TimeTaker t("placeTrees"); PseudoRandom grassrandom(blockseed + 53); content_t c_sand = ndef->getId("mapgen_sand"); content_t c_junglegrass = ndef->getId("mapgen_junglegrass"); // if we don't have junglegrass, don't place cignore... that's bad if (c_junglegrass == CONTENT_IGNORE) c_junglegrass = CONTENT_AIR; MapNode n_junglegrass(c_junglegrass); v3s16 em = vm->m_area.getExtent(); // Divide area into parts s16 div = 8; s16 sidelen = central_area_size.X / div; double area = sidelen * sidelen; // N.B. We must add jungle grass first, since tree leaves will // obstruct the ground, giving us a false ground level for (s16 z0 = 0; z0 < div; z0++) for (s16 x0 = 0; x0 < div; x0++) { // Center position of part of division v2s16 p2d_center( node_min.X + sidelen / 2 + sidelen * x0, node_min.Z + sidelen / 2 + sidelen * z0 ); // Minimum edge of part of division v2s16 p2d_min( node_min.X + sidelen * x0, node_min.Z + sidelen * z0 ); // Maximum edge of part of division v2s16 p2d_max( node_min.X + sidelen + sidelen * x0 - 1, node_min.Z + sidelen + sidelen * z0 - 1 ); // Get biome at center position of part of division BiomeV6Type bt = getBiome(v3POS(p2d_center.X, node_min.Y, p2d_center.Y)); // Amount of trees float humidity = getHumidity(v3POS(p2d_center.X, node_max.Y, p2d_center.Y)); s32 tree_count; if (bt == BT_JUNGLE || bt == BT_TAIGA || bt == BT_NORMAL) { tree_count = area * getTreeAmount(p2d_center) * ((humidity + 1)/2.0); if (bt == BT_JUNGLE) tree_count *= 4; } else { tree_count = 0; } if (node_max.Y < water_level) tree_count /= 2; // Add jungle grass if (bt == BT_JUNGLE) { u32 grass_count = 5 * humidity * tree_count; for (u32 i = 0; i < grass_count; i++) { s16 x = grassrandom.range(p2d_min.X, p2d_max.X); s16 z = grassrandom.range(p2d_min.Y, p2d_max.Y); /* wtf int mapindex = central_area_size.X * (z - node_min.Z) + (x - node_min.X); s16 y = heightmap[mapindex]; */ s16 y = findGroundLevelFull(v2s16(x, z)); if (y < water_level) continue; u32 vi = vm->m_area.index(x, y, z); // place on dirt_with_grass, since we know it is exposed to sunlight if (vm->m_data[vi].getContent() == c_dirt_with_grass) { vm->m_area.add_y(em, vi, 1); vm->m_data[vi] = n_junglegrass; } } } // Put trees in random places on part of division for (s32 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); /* wtf int mapindex = central_area_size.X * (z - node_min.Z) + (x - node_min.X); s16 y = heightmap[mapindex]; */ s16 y = findGroundLevelFull(v2s16(x, z)); // Don't make a tree under water level // Don't make a tree so high that it doesn't fit if (y > node_max.Y - 6) continue; v3s16 p(x, y, z); // Trees grow only on mud and grass and snowblock { u32 i = vm->m_area.index(p); content_t c = vm->m_data[i].getContent(); if (c != c_dirt && c != c_dirt_with_grass && c != c_dirt_with_snow && c != c_snowblock && (y >= water_level || c != c_sand)) continue; } p.Y++; // Make a tree if (y < water_level) { if (y < water_level - 20) // do not spawn trees in lakes treegen::make_cavetree(*vm, p, bt == BT_JUNGLE, ndef, myrand()); } else if (bt == BT_JUNGLE) { treegen::make_jungletree(*vm, p, ndef, myrand()); } else if (bt == BT_TAIGA) { treegen::make_pine_tree(*vm, p - v3s16(0, 1, 0), ndef, myrand()); } else if (bt == BT_NORMAL) { bool is_apple_tree = (myrand_range(0, 3) == 0) && getHaveAppleTree(v2s16(x, z)); treegen::make_tree(*vm, p, is_apple_tree, ndef, myrand()); } } } //printf("placeTreesAndJungleGrass: %dms\n", t.stop()); }
void MapgenV6::placeTreesAndJungleGrass() { //TimeTaker t("placeTrees"); PseudoRandom grassrandom(blockseed + 53); content_t c_sand = ndef->getId("mapgen_sand"); content_t c_junglegrass = ndef->getId("mapgen_junglegrass"); // if we don't have junglegrass, don't place cignore... that's bad if (c_junglegrass == CONTENT_IGNORE) c_junglegrass = CONTENT_AIR; MapNode n_junglegrass(c_junglegrass); v3s16 em = vm->m_area.getExtent(); // Divide area into parts s16 div = 8; s16 sidelen = central_area_size.X / div; double area = sidelen * sidelen; // N.B. We must add jungle grass first, since tree leaves will // obstruct the ground, giving us a false ground level for (s16 z0 = 0; z0 < div; z0++) for (s16 x0 = 0; x0 < div; x0++) { // Center position of part of division v2s16 p2d_center( node_min.X + sidelen / 2 + sidelen * x0, node_min.Z + sidelen / 2 + sidelen * z0 ); // Minimum edge of part of division v2s16 p2d_min( node_min.X + sidelen * x0, node_min.Z + sidelen * z0 ); // Maximum edge of part of division v2s16 p2d_max( node_min.X + sidelen + sidelen * x0 - 1, node_min.Z + sidelen + sidelen * z0 - 1 ); // Amount of trees, jungle area u32 tree_count = area * getTreeAmount(p2d_center); float humidity = 0; bool is_jungle = false; if (flags & MGV6_JUNGLES) { humidity = getHumidity(p2d_center); if (humidity > 0.75) { is_jungle = true; tree_count *= 4; } } if (node_max.Y < water_level) tree_count /= 2; // Add jungle grass if (is_jungle) { u32 grass_count = 5 * humidity * tree_count; for (u32 i = 0; i < grass_count; i++) { s16 x = grassrandom.range(p2d_min.X, p2d_max.X); s16 z = grassrandom.range(p2d_min.Y, p2d_max.Y); s16 y = findGroundLevelFull(v2s16(x, z)); ////////////////optimize this! if (y < water_level || y < node_min.Y || y > node_max.Y) continue; u32 vi = vm->m_area.index(x, y, z); // place on dirt_with_grass, since we know it is exposed to sunlight if (vm->m_data[vi].getContent() == c_dirt_with_grass) { vm->m_area.add_y(em, vi, 1); vm->m_data[vi] = n_junglegrass; } } } // Put trees in random places on part of division 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 = 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 > node_max.Y - 6) continue; v3s16 p(x,y,z); // Trees grow only on mud and grass { u32 i = vm->m_area.index(p); MapNode *n = &vm->m_data[i]; if (n->getContent() != c_dirt && n->getContent() != c_dirt_with_grass && (y >= water_level || n->getContent() != c_sand)) continue; } p.Y++; // Make a tree if (y < water_level) { if (y < water_level - 20) // do not spawn trees in lakes treegen::make_cavetree(*vm, p, is_jungle, ndef, myrand()); } else if (is_jungle) { treegen::make_jungletree(*vm, p, ndef, myrand()); } else { bool is_apple_tree = (myrand_range(0, 3) == 0) && getHaveAppleTree(v2s16(x, z)); treegen::make_tree(*vm, p, is_apple_tree, ndef, myrand()); } } } //printf("placeTreesAndJungleGrass: %dms\n", t.stop()); }