Minetest源码分析十三:Mapgen

来源:互联网 发布:数据库原理范式 编辑:程序博客网 时间:2024/06/03 09:54

Minetest源码分析十三:Mapgen


minetest->margen.h   minetest->mapgen_v6.h


Mapgen:真实生成具体的地图。要生成什么样的地图,具体参数都是是这里设置。通过MapgenParams结构来存储传递参数的。


类的实例初始化:

在类EmergeManager中的initMapgens()中创建实例的,在实例的create函数中传入MapgenParams参数。initMapgens()方法只在server对象的构造函数中调用。程序运行过程中,只在开始时调用一次EmergeManager中的initMapgens,也就是开始给emergeThread创建了这个Mapgen对象。

具体方法如下:


void EmergeManager::initMapgens(){if (!params.sparams) {params.sparams = createMapgenParams(params.mg_name);params.sparams->readParams(g_settings);}// Create the mapgensfor (u32 i = 0; i != emergethread.size(); i++) {Mapgen *mg = createMapgen(params.mg_name, i, ¶ms);mapgen.push_back(mg);}}


MapgenParamsMapgen类中使用到的参数,这里是定义的一个结构。地图参数存储在map_meta.txt文件中。

struct MapgenParams {std::string mg_name;s16 chunksize;u64 seed;s16 water_level;u32 flags;NoiseParams np_biome_heat;NoiseParams np_biome_humidity;MapgenSpecificParams *sparams;MapgenParams() :mg_name(DEFAULT_MAPGEN),chunksize(5),seed(0),water_level(1),flags(MG_TREES | MG_CAVES | MG_LIGHT),np_biome_heat(NoiseParams(50, 50, v3f(500.0, 500.0, 500.0), 5349, 3, 0.5, 2.0)),np_biome_humidity(NoiseParams(50, 50, v3f(500.0, 500.0, 500.0), 842, 3, 0.5, 2.0)),sparams(NULL){}void load(const Settings &settings);void save(Settings &settings) const;};


MapgenParams中使用到的相关宏定义

#define MG_TREES         0x01

#define MG_CAVES         0x02

#define MG_DUNGEONS      0x04

#define MG_FLAT          0x08

#define MG_LIGHT         0x10



Mapgen:



主要方法:

void MapgenV6::makeChunk(BlockMakeData *data)

功能:给Block创建的数据结构设置值、填充值。主要是BlockMakeData结构中MMVManip变量设置值,MMVManip实例变量中主要是设置MapNode *m_data这个成员变量值。也就是说makeChunk主要是设置一系列MapNode的data值。


参数:BlockMakeDatainit Block 时创建的数据结构。

调用:一般与initBlockMakefinishBlockMake一起使用,在这两个方法中间调用。主要是EmergeThreadThread()线程函数的循环体中使用,不断获取需要生成的block 位置,然后根据位置进行生成block的数据结构,之后就需要使用makeChunk来设置好block数据结构中该有的数据。

initBlockMake(&data, p);

mapgen->makeChunk(&data);

finishBlockMake(&data, modified_blocks);


函数主要流程:

1.Generate general ground level to full area

2.Make caves (this code is relatively horrible)

3.Add mud to the central chunk

4.Flow mud away from steep edges

5.Add dungeons

6.Add top and bottom side of water to transforming_liquid queue

7.Add surface nodesgrowGrass();

8.Generate some trees, and add grass, if a jungle

9.Generate the registered decorations

10.Generate the registered ores

11.Calculate lighting


void MapgenV6::makeChunk(BlockMakeData *data){this->generating = true;this->vm   = data->vmanip;this->ndef = data->nodedef;// Hack: use minimum block coords for old code that assumes a single blockv3s16 blockpos = data->blockpos_requested;v3s16 blockpos_min = data->blockpos_min;v3s16 blockpos_max = data->blockpos_max;// Area of central chunknode_min = blockpos_min * MAP_BLOCKSIZE;node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);// Full allocated areafull_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);central_area_size = node_max - node_min + v3s16(1, 1, 1);assert(central_area_size.X == central_area_size.Z);int volume_blocks = (blockpos_max.X - blockpos_min.X + 1)  * (blockpos_max.Y - blockpos_min.Y + 1)  * (blockpos_max.Z - blockpos_max.Z + 1);volume_nodes = volume_blocks *MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE;// Create a block-specific seedblockseed = get_blockseed(data->seed, full_node_min);// Make some noisecalculateNoise();// Maximum height of the stone surface and obstacles.// This is used to guide the cave generations16 stone_surface_max_y;// Generate general ground level to full areastone_surface_max_y = generateGround();        //// Create initial heightmap to limit caves//updateHeightmap(node_min, node_max);const s16 max_spread_amount = MAP_BLOCKSIZE;// Limit dirt flow area by 1 because mud is flown into neighbors.s16 mudflow_minpos = -max_spread_amount + 1;s16 mudflow_maxpos = central_area_size.X + max_spread_amount - 2;// Loop this part, it will make stuff look older and newer nicelyconst u32 age_loops = 2;for (u32 i_age = 0; i_age < age_loops; i_age++) { // Aging loop// Make caves (this code is relatively horrible)//if (flags & MG_CAVES)//generateCaves(stone_surface_max_y);// Add mud to the central chunkaddMud();// Flow mud away from steep edgesif (spflags & MGV6_MUDFLOW)flowMud(mudflow_minpos, mudflow_maxpos);}////// Update heightmap after mudflow//updateHeightmap(node_min, node_max);// Add dungeonsif ((flags & MG_DUNGEONS) && (stone_surface_max_y >= node_min.Y)) {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_DESERT) {dp.c_cobble  = c_sandbrick;dp.c_moss    = c_sandbrick; // should make this 'cracked sandstone' laterdp.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;} else {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;}//DungeonGen dgen(this, &dp);//dgen.generate(blockseed, full_node_min, full_node_max);}// Add top and bottom side of water to transforming_liquid queueupdateLiquid(&data->transforming_liquid, full_node_min, full_node_max);//// Add surface nodes//growGrass();//// Generate some trees, and add grass, if a jungle//if (flags & MG_TREES)//placeTreesAndJungleGrass();// Generate the registered decorationsm_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);// Generate the registered oresm_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);// Calculate lightingif (flags & MG_LIGHT)calcLighting(node_min, node_max);this->generating = false;}

参考资料

http://dev.minetest.net/Mapgen


原创粉丝点击