Minetest源码分析十三:Mapgen
2017-08-31 22:50
155 查看
Minetest源码分析十三:Mapgen
minetest->margen.h minetest->mapgen_v6.h
Mapgen:真实生成具体的地图。要生成什么样的地图,具体参数都是是这里设置。通过MapgenParams结构来存储传递参数的。
类的实例初始化:
在类EmergeManager中的initMapgens()中创建实例的,在实例的create函数中传入MapgenParams参数。initMapgens()方法只在server对象的构造函数中调用。程序运行过程中,只在开始时调用一次EmergeManager中的initMapgens,也就是开始给emergeThread创建了这个Mapgen对象。
具体方法如下:
MapgenParams:Mapgen类中使用到的参数,这里是定义的一个结构。地图参数存储在map_meta.txt文件中。
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值。
参数:BlockMakeData,init Block 时创建的数据结构。
调用:一般与initBlockMake、finishBlockMake一起使用,在这两个方法中间调用。主要是EmergeThread的Thread()线程函数的循环体中使用,不断获取需要生成的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 nodes:growGrass();
8.Generate some trees, and add grass, if a jungle
9.Generate the registered decorations
10.Generate the registered ores
11.Calculate lighting
参考资料
http://dev.minetest.net/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 mapgens for (u32 i = 0; i != emergethread.size(); i++) { Mapgen *mg = createMapgen(params.mg_name, i, ¶ms); mapgen.push_back(mg); } }
MapgenParams:Mapgen类中使用到的参数,这里是定义的一个结构。地图参数存储在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值。
参数:BlockMakeData,init Block 时创建的数据结构。
调用:一般与initBlockMake、finishBlockMake一起使用,在这两个方法中间调用。主要是EmergeThread的Thread()线程函数的循环体中使用,不断获取需要生成的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 nodes:growGrass();
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 block v3s16 blockpos = data->blockpos_requested; v3s16 blockpos_min = data->blockpos_min; v3s16 blockpos_max = data->blockpos_max; // Area of central chunk node_min = blockpos_min * MAP_BLOCKSIZE; node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1); // Full allocated area full_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 seed blockseed = get_blockseed(data->seed, full_node_min); // Make some noise calculateNoise(); // Maximum height of the stone surface and obstacles. // This is used to guide the cave generation s16 stone_surface_max_y; // Generate general ground level to full area stone_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 nicely const 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 chunk addMud(); // Flow mud away from steep edges if (spflags & MGV6_MUDFLOW) flowMud(mudflow_minpos, mudflow_maxpos); } // // // Update heightmap after mudflow // updateHeightmap(node_min, node_max); // Add dungeons if ((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' 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; } 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 queue updateLiquid(&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 decorations m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max); // Generate the registered ores m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max); // Calculate lighting if (flags & MG_LIGHT) calcLighting(node_min, node_max); this->generating = false; }
参考资料
http://dev.minetest.net/Mapgen
相关文章推荐
- 逆向工程核心原理学习笔记(十三):分析abex' crackme #1 的延伸:将参数压入栈
- 搭建ELK(ElasticSearch+Logstash+Kibana)日志分析系统(十三) kibana 界面查询语法
- PostgreSQL的 initdb 源代码分析之十三
- 对天乙社区bbscs8实现的详细分析十三
- 深入浅出 - Android系统移植与平台开发(十三) - Sensor HAL框架分析之三
- BT源代码学习心得(十三):客户端源代码分析(对等客户的连接建立及其握手协议)
- 测试工具Loadrunner message函数详细分析(十三)
- jQuery 1.9.1源码分析系列(十三)之位置大小操作
- newstyles项目实战(十三)前台系统搭建分析、服务层工程搭建
- 【android学习之十三】——SDK实例NotePad 分析2
- Heritrix源码分析(十三) Heritrix的控制中心(大脑)CrawlController(二)
- Spring3.1.0实现原理分析(十三).MVC请求映射信息RequestMappingInfo详解
- 十三、我们应当怎样做需求分析:查询报表分析
- Minetest源码分析十一:EmergeManager
- Redis源码分析(十三)——集合类型t_set
- python/pandas数据分析(十三)-数据清理、转换、合并,重塑
- 性能优化十三之电量分析环境安装
- 亚盘分析(十三)
- linux驱动编写之十三(设备模型之sysfs,bus,device,driver源代码分析)
- 【python数据挖掘课程】十三.WordCloud词云配置过程及词频分析