Minetest源码分析十三:Mapgen

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 mapgens
	for (u32 i = 0; i != emergethread.size(); i++) {
		Mapgen *mg = createMapgen(params.mg_name, i, &params);
		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 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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值