コード例 #1
0
ファイル: mapgen_v6.cpp プロジェクト: 4aiman/Magichet-stable
void MapgenV6::addMud()
{
	// 15ms @cs=8
	//TimeTaker timer1("add mud");
	MapNode n_dirt(c_dirt), n_gravel(c_gravel);
	MapNode n_sand(c_sand), n_desert_sand(c_desert_sand);
	MapNode addnode;

	u32 index = 0;
	for (s16 z = node_min.Z; z <= node_max.Z; z++)
	for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
		// Randomize mud amount
		s16 mud_add_amount = getMudAmount(index) / 2.0 + 0.5;

		// Find ground level
		s16 surface_y = find_stone_level(v2s16(x, z)); /////////////////optimize this!

		// Handle area not found
		if (surface_y == vm->m_area.MinEdge.Y - 1)
			continue;

		BiomeV6Type bt = getBiome(v2s16(x, z));
		addnode = (bt == BT_DESERT) ? n_desert_sand : n_dirt;

		if (bt == BT_DESERT && surface_y + mud_add_amount <= water_level + 1) {
			addnode = n_sand;
		} else if (mud_add_amount <= 0) {
			mud_add_amount = 1 - mud_add_amount;
			addnode = n_gravel;
		} else if (bt != BT_DESERT && getHaveBeach(index) &&
				surface_y + mud_add_amount <= water_level + 2) {
			addnode = n_sand;
		}

		if ((bt == BT_DESERT || bt == BT_TUNDRA) && surface_y > 20)
			mud_add_amount = MYMAX(0, mud_add_amount - (surface_y - 20) / 5);

		/* If topmost node is grass, change it to mud.  It might be if it was
		// flown to there from a neighboring chunk and then converted.
		u32 i = vm->m_area.index(x, surface_y, z);
		if (vm->m_data[i].getContent() == c_dirt_with_grass)
			vm->m_data[i] = n_dirt;*/

		// Add mud on ground
		s16 mudcount = 0;
		v3s16 em = vm->m_area.getExtent();
		s16 y_start = surface_y + 1;
		u32 i = vm->m_area.index(x, y_start, z);
		for (s16 y = y_start; y <= node_max.Y; y++) {
			if (mudcount >= mud_add_amount)
				break;

			vm->m_data[i] = addnode;
			mudcount++;

			vm->m_area.add_y(em, i, 1);
		}
	}
}
コード例 #2
0
ファイル: mapgen_v5.cpp プロジェクト: WantedGames/freeminer
double get_sector_minimum_ground_level(u64 seed, v3s16 node_min, v3s16 node_max, double p=4)
{
	double a = 31000;
	// Corners
	a = MYMIN(a, find_ground_level_from_noise(seed,
			v2s16(node_min.X, node_min.Z), p));
	a = MYMIN(a, find_ground_level_from_noise(seed,
			v2s16(node_min.X, node_max.Z), p));
	a = MYMIN(a, find_ground_level_from_noise(seed,
			v2s16(node_max.X, node_max.Z), p));
	a = MYMIN(a, find_ground_level_from_noise(seed,
			v2s16(node_min.X, node_min.Z), p));
	// Center
	a = MYMIN(a, find_ground_level_from_noise(seed,
			v2s16((node_min.X+node_max.X)/2, (node_min.Z+node_max.Z)/2), p));
	// Side middle points
	a = MYMIN(a, find_ground_level_from_noise(seed,
			v2s16((node_min.X+node_max.X)/2, node_min.Z), p));
	a = MYMIN(a, find_ground_level_from_noise(seed,
			v2s16((node_min.X+node_max.X)/2, node_max.Z), p));
	a = MYMIN(a, find_ground_level_from_noise(seed,
			v2s16(node_min.X, (node_min.Z+node_max.Z)/2), p));
	a = MYMIN(a, find_ground_level_from_noise(seed,
			v2s16(node_max.X, (node_min.Z+node_max.Z)/2), p));
	return a;
}
コード例 #3
0
ファイル: test.cpp プロジェクト: Jetqvvf/minetest
	void Run()
	{
		TC parent;
		parent.position_valid = false;

		// Create one with no heightmaps
		ServerMapSector sector(&parent, v2s16(1,1));

		UASSERT(sector.getBlockNoCreateNoEx(0) == 0);
		UASSERT(sector.getBlockNoCreateNoEx(1) == 0);

		MapBlock * bref = sector.createBlankBlock(-2);

		UASSERT(sector.getBlockNoCreateNoEx(0) == 0);
		UASSERT(sector.getBlockNoCreateNoEx(-2) == bref);

		//TODO: Check for AlreadyExistsException

		/*bool exception_thrown = false;
		try{
			sector.getBlock(0);
		}
		catch(InvalidPositionException &e){
			exception_thrown = true;
		}
		UASSERT(exception_thrown);*/

	}
コード例 #4
0
ファイル: mapgen_v5.cpp プロジェクト: WantedGames/freeminer
double get_sector_average_ground_level(u64 seed, v3s16 node_min, v3s16 node_max, double p=4)
{
	double a = 0;
	a += find_ground_level_from_noise(seed,
			v2s16(node_min.X, node_min.Z), p);
	a += find_ground_level_from_noise(seed,
			v2s16(node_min.X, node_max.Z), p);
	a += find_ground_level_from_noise(seed,
			v2s16(node_max.X, node_max.Z), p);
	a += find_ground_level_from_noise(seed,
			v2s16(node_max.X, node_min.Z), p);
	a += find_ground_level_from_noise(seed,
			v2s16((node_min.X+node_max.X)/2, (node_min.Z+node_max.Z)/2), p);
	a /= 5;
	return a;
}
コード例 #5
0
ファイル: content_sao.cpp プロジェクト: alexxvk/freeminer
PlayerSAO::PlayerSAO(ServerEnvironment *env_, u16 peer_id_, bool is_singleplayer):
	UnitSAO(env_, v3f(0,0,0)),
	m_player(NULL),
	m_peer_id(peer_id_),
	m_inventory(NULL),
	m_damage(0),
	m_last_good_position(0,0,0),
	m_time_from_last_punch(0),
	m_nocheat_dig_pos(32767, 32767, 32767),
	m_nocheat_dig_time(0),
	m_wield_index(0),
	m_position_not_sent(false),
	m_armor_groups_sent(false),
	m_properties_sent(true),
	m_is_singleplayer(is_singleplayer),
	m_animation_speed(0),
	m_animation_blend(0),
	m_animation_loop(true),
	m_animation_sent(false),
	m_bone_position_sent(false),
	m_attachment_parent_id(0),
	m_attachment_sent(false),
	m_breath(PLAYER_MAX_BREATH),
	m_pitch(0),
	m_fov(0),
	m_wanted_range(0),
	// public
	m_physics_override_speed(1),
	m_physics_override_jump(1),
	m_physics_override_gravity(1),
	m_physics_override_sneak(true),
	m_physics_override_sneak_glitch(true),
	m_physics_override_sent(false)
{
	m_ms_from_last_respawn = 10000; //more than ignore move time (1)

	if (m_player) {
		++m_player->refs;
	}
	//assert(m_peer_id != 0);	// pre-condition
	m_armor_groups["fleshy"] = 100;

	m_prop.hp_max = PLAYER_MAX_HP;
	m_prop.physical = false;
	m_prop.weight = 75;
	m_prop.collisionbox = aabb3f(-1/3.,-1.0,-1/3., 1/3.,1.0,1/3.);
	// start of default appearance, this should be overwritten by LUA
	m_prop.visual = "upright_sprite";
	m_prop.visual_size = v2f(1, 2);
	m_prop.textures.clear();
	m_prop.textures.push_back("player.png");
	m_prop.textures.push_back("player_back.png");
	m_prop.colors.clear();
	m_prop.colors.push_back(video::SColor(255, 255, 255, 255));
	m_prop.spritediv = v2s16(1,1);
	// end of default appearance
	m_prop.is_visible = true;
	m_prop.makes_footstep_sound = true;
	m_hp = PLAYER_MAX_HP;
}
コード例 #6
0
ファイル: mapgen_v6.cpp プロジェクト: 4aiman/Magichet-stable
void MapgenV6::generateCaves(int max_stone_y)
{
	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;
	PseudoRandom ps(blockseed + 21343);
	PseudoRandom ps2(blockseed + 1032);

	if (ps.range(1, 6) == 1)
		bruises_count = ps.range(0, ps.range(0, 2));

	if (getBiome(v2s16(node_min.X, node_min.Z)) == BT_DESERT) {
		caves_count   /= 3;
		bruises_count /= 3;
	}

	for (u32 i = 0; i < caves_count + bruises_count; i++) {
		bool large_cave = (i >= caves_count);
		CaveV6 cave(this, &ps, &ps2, large_cave);

		cave.makeCave(node_min, node_max, max_stone_y);
	}
}
コード例 #7
0
ファイル: content_sao.cpp プロジェクト: Adam445/minetest
PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
		const std::set<std::string> &privs, bool is_singleplayer):
	ServerActiveObject(env_, v3f(0,0,0)),
	m_player(player_),
	m_peer_id(peer_id_),
	m_inventory(NULL),
	m_damage(0),
	m_last_good_position(0,0,0),
	m_time_from_last_punch(0),
	m_nocheat_dig_pos(32767, 32767, 32767),
	m_nocheat_dig_time(0),
	m_wield_index(0),
	m_position_not_sent(false),
	m_armor_groups_sent(false),
	m_properties_sent(true),
	m_privs(privs),
	m_is_singleplayer(is_singleplayer),
	m_animation_speed(0),
	m_animation_blend(0),
	m_animation_sent(false),
	m_bone_position_sent(false),
	m_attachment_parent_id(0),
	m_attachment_sent(false),
	// public
	m_moved(false),
	m_inventory_not_sent(false),
	m_hp_not_sent(false),
	m_breath_not_sent(false),
	m_wielded_item_not_sent(false),
	m_physics_override_speed(1),
	m_physics_override_jump(1),
	m_physics_override_gravity(1),
	m_physics_override_sneak(true),
	m_physics_override_sneak_glitch(true),
	m_physics_override_sent(false)
{
	assert(m_player);
	assert(m_peer_id != 0);
	setBasePosition(m_player->getPosition());
	m_inventory = &m_player->inventory;
	m_armor_groups["fleshy"] = 100;

	m_prop.hp_max = PLAYER_MAX_HP;
	m_prop.physical = false;
	m_prop.weight = 75;
	m_prop.collisionbox = core::aabbox3d<f32>(-1/3.,-1.0,-1/3., 1/3.,1.0,1/3.);
	// start of default appearance, this should be overwritten by LUA
	m_prop.visual = "upright_sprite";
	m_prop.visual_size = v2f(1, 2);
	m_prop.textures.clear();
	m_prop.textures.push_back("player.png");
	m_prop.textures.push_back("player_back.png");
	m_prop.colors.clear();
	m_prop.colors.push_back(video::SColor(255, 255, 255, 255));
	m_prop.spritediv = v2s16(1,1);
	// end of default appearance
	m_prop.is_visible = true;
	m_prop.makes_footstep_sound = true;
}
コード例 #8
0
void WeatherParticles::render() {
	core::list<v2s16> emitters_to_delete;

	scene::ISceneManager *smgr = m_device->getSceneManager();
	for (s16 zi = -m_particle_radius_i; zi < m_particle_radius_i; zi++) {
		if(zi < -(m_particle_radius_i/3) || zi > (m_particle_radius_i/3))
			zi++;
		for (s16 xi = -m_particle_radius_i; xi < m_particle_radius_i; xi++) {
			if(xi < -(m_particle_radius_i/3) || xi > (m_particle_radius_i/3))
						xi++;
			v3s16 pos = v3s16(m_camera_pos.X / BS, m_camera_pos.Y / BS,
					m_camera_pos.Z / BS);

			pos.X = pos.X + xi;
			pos.Z = pos.Z + zi;
			pos.Y = traceGroundLevel(pos);
			pos.Y += 1;
			if (m_emitter_map.find(v2s16(pos.X, pos.Z)) == 0) {
				if(pos.Y >= 100)
					continue;
				m_emitter_map.insert(
						v2s16(pos.X, pos.Z),
						new WEmitter(smgr->getRootSceneNode(), smgr, -1, pos,
								100-pos.Y));
			} else {

			}

		}
	}
	core::map<v2s16, WEmitter*>::Iterator ei;

	ei = m_emitter_map.getIterator();
	for (; ei.atEnd() == false; ei++) {
		if (ei.getNode()->getKey().X < (m_camera_pos.X / BS
				- m_particle_radius_i) || ei.getNode()->getKey().X
				> (m_camera_pos.X / BS + m_particle_radius_i)
				|| ei.getNode()->getKey().Y < (m_camera_pos.Z / BS
						- m_particle_radius_i - 1) || ei.getNode()->getKey().Y
				> (m_camera_pos.Z / BS + m_particle_radius_i)) {
			emitters_to_delete.push_back(ei.getNode()->getKey());
		}
	}

	removeEmitters(emitters_to_delete);
}
コード例 #9
0
ファイル: emerge.cpp プロジェクト: viphotman/minetest
bool EmergeManager::isBlockUnderground(v3s16 blockpos)
{
#if 0
	v2s16 p = v2s16((blockpos.X * MAP_BLOCKSIZE) + MAP_BLOCKSIZE / 2,
					(blockpos.Y * MAP_BLOCKSIZE) + MAP_BLOCKSIZE / 2);
	int ground_level = getGroundLevelAtPoint(p);
	return blockpos.Y * (MAP_BLOCKSIZE + 1) <= min(water_level, ground_level);
#endif

	// Use a simple heuristic; the above method is wildly inaccurate anyway.
	return blockpos.Y * (MAP_BLOCKSIZE + 1) <= params.water_level;
}
コード例 #10
0
ファイル: mapgen_v6.cpp プロジェクト: 4aiman/Magichet-stable
void MapgenV6::growGrass() // Add surface nodes
{
	MapNode n_dirt_with_grass(c_dirt_with_grass);
	MapNode n_dirt_with_snow(c_dirt_with_snow);
	MapNode n_snowblock(c_snowblock);
	MapNode n_snow(c_snow);
	v3s16 em = vm->m_area.getExtent();

	u32 index = 0;
	for (s16 z = full_node_min.Z; z <= full_node_max.Z; z++)
	for (s16 x = full_node_min.X; x <= full_node_max.X; x++, index++) {
		// Find the lowest surface to which enough light ends up to make
		// grass grow.  Basically just wait until not air and not leaves.
		s16 surface_y = 0;
		{
			u32 i = vm->m_area.index(x, node_max.Y, z);
			s16 y;
			// Go to ground level
			for (y = node_max.Y; y >= full_node_min.Y; y--) {
				MapNode &n = vm->m_data[i];
				if (ndef->get(n).param_type != CPT_LIGHT ||
						ndef->get(n).liquid_type != LIQUID_NONE ||
						n.getContent() == c_ice)
					break;
				vm->m_area.add_y(em, i, -1);
			}
			surface_y = (y >= full_node_min.Y) ? y : full_node_min.Y;
		}

		BiomeV6Type bt = getBiome(index, v2s16(x, z));
		u32 i = vm->m_area.index(x, surface_y, z);
		content_t c = vm->m_data[i].getContent();
		if (surface_y >= water_level - 20) {
			if (bt == BT_TAIGA && c == c_dirt) {
				vm->m_data[i] = n_snowblock;
				vm->m_area.add_y(em, i, -1);
				vm->m_data[i] = n_dirt_with_snow;
			} else if (bt == BT_TUNDRA) {
				if (c == c_dirt) {
					vm->m_data[i] = n_dirt_with_snow;
				} else if (c == c_stone && surface_y < node_max.Y) {
					vm->m_area.add_y(em, i, 1);
					vm->m_data[i] = n_snow;
				}
			} else if (c == c_dirt) {
				vm->m_data[i] = n_dirt_with_grass;
			}
		}
	}
}
コード例 #11
0
PlayerSAO::PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, u16 peer_id_,
		bool is_singleplayer):
	UnitSAO(env_, v3f(0,0,0)),
	m_player(player_),
	m_peer_id(peer_id_),
	m_inventory(NULL),
	m_damage(0),
	m_last_good_position(0,0,0),
	m_time_from_last_teleport(0),
	m_time_from_last_punch(0),
	m_nocheat_dig_pos(32767, 32767, 32767),
	m_nocheat_dig_time(0),
	m_wield_index(0),
	m_position_not_sent(false),
	m_is_singleplayer(is_singleplayer),
	m_breath(PLAYER_MAX_BREATH),
	m_pitch(0),
	m_fov(0),
	m_wanted_range(0),
	m_extended_attributes_modified(false),
	// public
	m_physics_override_speed(1),
	m_physics_override_jump(1),
	m_physics_override_gravity(1),
	m_physics_override_sneak(true),
	m_physics_override_sneak_glitch(false),
	m_physics_override_new_move(true),
	m_physics_override_sent(false)
{
	assert(m_peer_id != 0);	// pre-condition

	m_prop.hp_max = PLAYER_MAX_HP;
	m_prop.physical = false;
	m_prop.weight = 75;
	m_prop.collisionbox = aabb3f(-0.3f, -1.0f, -0.3f, 0.3f, 0.75f, 0.3f);
	// start of default appearance, this should be overwritten by LUA
	m_prop.visual = "upright_sprite";
	m_prop.visual_size = v2f(1, 2);
	m_prop.textures.clear();
	m_prop.textures.push_back("player.png");
	m_prop.textures.push_back("player_back.png");
	m_prop.colors.clear();
	m_prop.colors.push_back(video::SColor(255, 255, 255, 255));
	m_prop.spritediv = v2s16(1,1);
	// end of default appearance
	m_prop.is_visible = true;
	m_prop.makes_footstep_sound = true;
	m_hp = PLAYER_MAX_HP;
}
コード例 #12
0
s16 WeatherParticles::traceGroundLevel(v3s16 p) {
	//@TODO needs cachepurging
	if (m_heightmap.find(v2s16(p.X, p.Z)) > 0) {
		return m_heightmap.find(v2s16(p.X, p.Z))->getValue();
	}
	s16 y = p.Y + 100;
	if (y > 100)
		y = 100;
	bool isair = true;
	do {
		y--;
		try {
			isair
					= content_features(m_client->getNode(v3s16(p.X, y, p.Z)).d).air_equivalent;
		} catch (InvalidPositionException &e) {
		}
		if (y < p.Y - 100)
			break;
	} while (isair);

	m_heightmap.insert(v2s16(p.X, p.Z), y);
	//dstream << y << std::endl;
	return y;
}
コード例 #13
0
void TestSerialization::testStreamWrite()
{
	std::ostringstream os(std::ios_base::binary);
	std::string data;

	writeU8(os, 0x11);
	writeU16(os, 0x2233);
	writeU32(os, 0x44556677);
	writeU64(os, 0x8899AABBCCDDEEFF);

	writeS8(os, -128);
	writeS16(os, 30000);
	writeS32(os, -6);
	writeS64(os, -43);

	writeF1000(os, 53.53467f);
	writeF1000(os, -300000.32f);
	writeF1000(os, F1000_MIN);
	writeF1000(os, F1000_MAX);

	os << serializeString("foobar!");

	data = os.str();
	UASSERT(data.size() < sizeof(test_serialized_data));
	UASSERT(!memcmp(&data[0], test_serialized_data, data.size()));

	writeV2S16(os, v2s16(500, 500));
	writeV3S16(os, v3s16(4207, 604, -30));
	writeV2S32(os, v2s32(1920, 1080));
	writeV3S32(os, v3s32(-400, 6400054, 290549855));
	writeV2F1000(os, v2f(500.65661f, 350.34567f));

	os << serializeWideString(L"\x02~woof~\x5455");

	writeV3F1000(os, v3f(500, 10024.2f, -192.54f));
	writeARGB8(os, video::SColor(255, 128, 50, 128));

	os << serializeLongString("some longer string here");

	writeU16(os, 0xF00D);

	data = os.str();
	UASSERT(data.size() == sizeof(test_serialized_data));
	UASSERT(!memcmp(&data[0], test_serialized_data, sizeof(test_serialized_data)));
}
コード例 #14
0
ファイル: content_sao.cpp プロジェクト: AMDmi3/minetest
PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
		const std::set<std::string> &privs, bool is_singleplayer):
	ServerActiveObject(env_, v3f(0,0,0)),
	m_player(player_),
	m_peer_id(peer_id_),
	m_inventory(NULL),
	m_last_good_position(0,0,0),
	m_last_good_position_age(0),
	m_time_from_last_punch(0),
	m_nocheat_dig_pos(32767, 32767, 32767),
	m_nocheat_dig_time(0),
	m_wield_index(0),
	m_position_not_sent(false),
	m_armor_groups_sent(false),
	m_properties_sent(true),
	m_privs(privs),
	m_is_singleplayer(is_singleplayer),
	// public
	m_teleported(false),
	m_inventory_not_sent(false),
	m_hp_not_sent(false),
	m_wielded_item_not_sent(false)
{
	assert(m_player);
	assert(m_peer_id != 0);
	setBasePosition(m_player->getPosition());
	m_inventory = &m_player->inventory;
	m_armor_groups["choppy"] = 2;
	m_armor_groups["fleshy"] = 3;

	m_prop.hp_max = PLAYER_MAX_HP;
	m_prop.physical = false;
	m_prop.weight = 75;
	m_prop.collisionbox = core::aabbox3d<f32>(-1/3.,-1.0,-1/3., 1/3.,1.0,1/3.);
	m_prop.visual = "upright_sprite";
	m_prop.visual_size = v2f(1, 2);
	m_prop.textures.clear();
	m_prop.textures.push_back("player.png");
	m_prop.textures.push_back("player_back.png");
	m_prop.spritediv = v2s16(1,1);
	m_prop.is_visible = (getHP() != 0);
	m_prop.makes_footstep_sound = true;
}
コード例 #15
0
ファイル: mapgen_v6.cpp プロジェクト: 4aiman/Magichet-stable
int MapgenV6::generateGround()
{
	//TimeTaker timer1("Generating ground level");
	MapNode n_air(CONTENT_AIR), n_water_source(c_water_source);
	MapNode n_stone(c_stone), n_desert_stone(c_desert_stone);
	MapNode n_ice(c_ice);
	int stone_surface_max_y = -MAP_GENERATION_LIMIT;

	u32 index = 0;
	for (s16 z = node_min.Z; z <= node_max.Z; z++)
	for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
		// Surface height
		s16 surface_y = (s16)baseTerrainLevelFromMap(index);

		// Log it
		if (surface_y > stone_surface_max_y)
			stone_surface_max_y = surface_y;

		BiomeV6Type bt = getBiome(v2s16(x, z));

		// Fill ground with stone
		v3s16 em = vm->m_area.getExtent();
		u32 i = vm->m_area.index(x, node_min.Y, z);
		for (s16 y = node_min.Y; y <= node_max.Y; y++) {
			if (vm->m_data[i].getContent() == CONTENT_IGNORE) {
				if (y <= surface_y) {
					vm->m_data[i] = (y >= DESERT_STONE_BASE
							&& bt == BT_DESERT) ?
						n_desert_stone : n_stone;
				} else if (y <= water_level) {
					vm->m_data[i] = (y >= ICE_BASE
							&& bt == BT_TUNDRA) ?
						n_ice : n_water_source;
				} else {
					vm->m_data[i] = n_air;
				}
			}
			vm->m_area.add_y(em, i, 1);
		}
	}

	return stone_surface_max_y;
}
コード例 #16
0
void TestSerialization::testStreamRead()
{
	std::string datastr(
		(const char *)test_serialized_data,
		sizeof(test_serialized_data));
	std::istringstream is(datastr, std::ios_base::binary);

	UASSERT(readU8(is) == 0x11);
	UASSERT(readU16(is) == 0x2233);
	UASSERT(readU32(is) == 0x44556677);
	UASSERT(readU64(is) == 0x8899AABBCCDDEEFF);

	UASSERT(readS8(is) == -128);
	UASSERT(readS16(is) == 30000);
	UASSERT(readS32(is) == -6);
	UASSERT(readS64(is) == -43);

	UASSERT(readF1000(is) == 53.534f);
	UASSERT(readF1000(is) == -300000.32f);
	UASSERT(readF1000(is) == F1000_MIN);
	UASSERT(readF1000(is) == F1000_MAX);

	UASSERT(deSerializeString(is) == "foobar!");

	UASSERT(readV2S16(is) == v2s16(500, 500));
	UASSERT(readV3S16(is) == v3s16(4207, 604, -30));
	UASSERT(readV2S32(is) == v2s32(1920, 1080));
	UASSERT(readV3S32(is) == v3s32(-400, 6400054, 290549855));
	UASSERT(readV2F1000(is) == v2f(500.656f, 350.345f));

	UASSERT(deSerializeWideString(is) == L"\x02~woof~\x5455");

	UASSERT(readV3F1000(is) == v3f(500, 10024.2f, -192.54f));
	UASSERT(readARGB8(is) == video::SColor(255, 128, 50, 128));

	UASSERT(deSerializeLongString(is) == "some longer string here");

	UASSERT(is.rdbuf()->in_avail() == 2);
	UASSERT(readU16(is) == 0xF00D);
	UASSERT(is.rdbuf()->in_avail() == 0);
}
コード例 #17
0
ファイル: mapgen.cpp プロジェクト: Nate-Devv/freeminer
void Mapgen::updateHeightmap(v3s16 nmin, v3s16 nmax) {
	if (!heightmap)
		return;

	//TimeTaker t("Mapgen::updateHeightmap", NULL, PRECISION_MICRO);
	int index = 0;
	for (s16 z = nmin.Z; z <= nmax.Z; z++) {
		for (s16 x = nmin.X; x <= nmax.X; x++, index++) {
			s16 y = findGroundLevel(v2s16(x, z), nmin.Y, nmax.Y);

			// if the values found are out of range, trust the old heightmap
			if (y == nmax.Y && heightmap[index] > nmax.Y)
				continue;
			if (y == nmin.Y - 1 && heightmap[index] < nmin.Y)
				continue;

			heightmap[index] = y;
		}
	}
	//printf("updateHeightmap: %dus\n", t.stop());
}
コード例 #18
0
ファイル: mapgen_v6.cpp プロジェクト: jojoa1997/freeminer
int MapgenV6::generateGround() {
	//TimeTaker timer1("Generating ground level");
	MapNode n_air(CONTENT_AIR), n_water_source(c_water_source);
	MapNode n_stone(c_stone), n_desert_stone(c_desert_stone);
	MapNode n_ice(c_ice);
	int stone_surface_max_y = -MAP_GENERATION_LIMIT;
	u32 index = 0;
	
	for (s16 z = node_min.Z; z <= node_max.Z; z++)
	for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
		// Surface height
		s16 surface_y = (s16)baseTerrainLevelFromMap(index);
		
		// Log it
		if (surface_y > stone_surface_max_y)
			stone_surface_max_y = surface_y;

		BiomeType bt = getBiome(index, v2s16(x, z));
		
		// Fill ground with stone
		v3s16 em = vm->m_area.getExtent();
		u32 i = vm->m_area.index(x, node_min.Y, z);
		for (s16 y = node_min.Y; y <= node_max.Y; y++) {
			if (vm->m_data[i].getContent() == CONTENT_IGNORE) {
				if (y <= surface_y) {
					vm->m_data[i] = (y > water_level - surface_y && bt == BT_DESERT) ? 
						n_desert_stone : n_stone;
				} else if (y <= water_level) {
					s16 heat = emerge->env->m_use_weather ? emerge->env->getServerMap().updateBlockHeat(emerge->env, v3s16(x,y,z)) : 0;
					vm->m_data[i] = (heat < 0 && y > heat/3) ? n_ice : n_water_source;
				} else {
					vm->m_data[i] = n_air;
				}
			}
			vm->m_area.add_y(em, i, 1);
		}
	}
	
	return stone_surface_max_y;
}
コード例 #19
0
void TestSerialization::testVecPut()
{
	std::vector<u8> buf;

	putU8(&buf, 0x11);
	putU16(&buf, 0x2233);
	putU32(&buf, 0x44556677);
	putU64(&buf, 0x8899AABBCCDDEEFF);

	putS8(&buf, -128);
	putS16(&buf, 30000);
	putS32(&buf, -6);
	putS64(&buf, -43);

	putF1000(&buf, 53.53467f);
	putF1000(&buf, -300000.32f);
	putF1000(&buf, F1000_MIN);
	putF1000(&buf, F1000_MAX);

	putString(&buf, "foobar!");

	putV2S16(&buf, v2s16(500, 500));
	putV3S16(&buf, v3s16(4207, 604, -30));
	putV2S32(&buf, v2s32(1920, 1080));
	putV3S32(&buf, v3s32(-400, 6400054, 290549855));
	putV2F1000(&buf, v2f(500.65661f, 350.34567f));

	putWideString(&buf, L"\x02~woof~\x5455");

	putV3F1000(&buf, v3f(500, 10024.2f, -192.54f));
	putARGB8(&buf, video::SColor(255, 128, 50, 128));

	putLongString(&buf, "some longer string here");

	putU16(&buf, 0xF00D);

	UASSERT(buf.size() == sizeof(test_serialized_data));
	UASSERT(!memcmp(&buf[0], test_serialized_data, sizeof(test_serialized_data)));
}
コード例 #20
0
ファイル: mapgen_v6.cpp プロジェクト: jojoa1997/freeminer
void MapgenV6::addDirtGravelBlobs() {
	if (getBiome(v2s16(node_min.X, node_min.Z)) != BT_NORMAL)
		return;
	
	PseudoRandom pr(blockseed + 983);
	for (int i = 0; i < volume_nodes/10/10/10; i++) {
		bool only_fill_cave = (myrand_range(0,1) != 0);
		v3s16 size(
			pr.range(1, 8),
			pr.range(1, 8),
			pr.range(1, 8)
		);
		v3s16 p0(
			pr.range(node_min.X, node_max.X) - size.X / 2,
			pr.range(node_min.Y, node_max.Y) - size.Y / 2,
			pr.range(node_min.Z, node_max.Z) - size.Z / 2
		);
		
		MapNode n1((p0.Y > -32 && !pr.range(0, 1)) ? c_dirt : c_gravel);
		for (int z1 = 0; z1 < size.Z; z1++)
		for (int y1 = 0; y1 < size.Y; y1++)
		for (int x1 = 0; x1 < size.X; x1++) {
			v3s16 p = p0 + v3s16(x1, y1, z1);
			u32 i = vm->m_area.index(p);
			if (!vm->m_area.contains(i))
				continue;
			// Cancel if not stone and not cave air
			if (vm->m_data[i].getContent() != c_stone &&
				!(vm->m_flags[i] & VMANIP_FLAG_CAVE))
				continue;
			if (only_fill_cave && !(vm->m_flags[i] & VMANIP_FLAG_CAVE))
				continue;
			vm->m_data[i] = n1;
		}
	}
}
コード例 #21
0
PlayerSAO::PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, session_t peer_id_,
		bool is_singleplayer):
	UnitSAO(env_, v3f(0,0,0)),
	m_player(player_),
	m_peer_id(peer_id_),
	m_is_singleplayer(is_singleplayer)
{
	assert(m_peer_id != 0);	// pre-condition

	m_prop.hp_max = PLAYER_MAX_HP_DEFAULT;
	m_prop.breath_max = PLAYER_MAX_BREATH_DEFAULT;
	m_prop.physical = false;
	m_prop.weight = 75;
	m_prop.collisionbox = aabb3f(-0.3f, 0.0f, -0.3f, 0.3f, 1.77f, 0.3f);
	m_prop.selectionbox = aabb3f(-0.3f, 0.0f, -0.3f, 0.3f, 1.77f, 0.3f);
	m_prop.pointable = true;
	// Start of default appearance, this should be overwritten by Lua
	m_prop.visual = "upright_sprite";
	m_prop.visual_size = v2f(1, 2);
	m_prop.textures.clear();
	m_prop.textures.emplace_back("player.png");
	m_prop.textures.emplace_back("player_back.png");
	m_prop.colors.clear();
	m_prop.colors.emplace_back(255, 255, 255, 255);
	m_prop.spritediv = v2s16(1,1);
	m_prop.eye_height = 1.625f;
	// End of default appearance
	m_prop.is_visible = true;
	m_prop.backface_culling = false;
	m_prop.makes_footstep_sound = true;
	m_prop.stepheight = PLAYER_DEFAULT_STEPHEIGHT * BS;
	m_hp = m_prop.hp_max;
	m_breath = m_prop.breath_max;
	// Disable zoom in survival mode using a value of 0
	m_prop.zoom_fov = g_settings->getBool("creative_mode") ? 15.0f : 0.0f;
}
コード例 #22
0
ファイル: mapgen_v6.cpp プロジェクト: Wayward1/freeminer
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());
}
コード例 #23
0
ファイル: clientlauncher.cpp プロジェクト: 4aiman/MultiCraft
void ClientLauncher::speed_tests()
{
    // volatile to avoid some potential compiler optimisations
    volatile static s16 temp16;
    volatile static f32 tempf;
    static v3f tempv3f1;
    static v3f tempv3f2;
    static std::string tempstring;
    static std::string tempstring2;

    tempv3f1 = v3f();
    tempv3f2 = v3f();
    tempstring = std::string();
    tempstring2 = std::string();

    {
        infostream << "The following test should take around 20ms." << std::endl;
        TimeTaker timer("Testing std::string speed");
        const u32 jj = 10000;
        for (u32 j = 0; j < jj; j++) {
            tempstring = "";
            tempstring2 = "";
            const u32 ii = 10;
            for (u32 i = 0; i < ii; i++) {
                tempstring2 += "asd";
            }
            for (u32 i = 0; i < ii+1; i++) {
                tempstring += "asd";
                if (tempstring == tempstring2)
                    break;
            }
        }
    }

    infostream << "All of the following tests should take around 100ms each."
               << std::endl;

    {
        TimeTaker timer("Testing floating-point conversion speed");
        tempf = 0.001;
        for (u32 i = 0; i < 4000000; i++) {
            temp16 += tempf;
            tempf += 0.001;
        }
    }

    {
        TimeTaker timer("Testing floating-point vector speed");

        tempv3f1 = v3f(1, 2, 3);
        tempv3f2 = v3f(4, 5, 6);
        for (u32 i = 0; i < 10000000; i++) {
            tempf += tempv3f1.dotProduct(tempv3f2);
            tempv3f2 += v3f(7, 8, 9);
        }
    }

    {
        TimeTaker timer("Testing std::map speed");

        std::map<v2s16, f32> map1;
        tempf = -324;
        const s16 ii = 300;
        for (s16 y = 0; y < ii; y++) {
            for (s16 x = 0; x < ii; x++) {
                map1[v2s16(x, y)] =  tempf;
                tempf += 1;
            }
        }
        for (s16 y = ii - 1; y >= 0; y--) {
            for (s16 x = 0; x < ii; x++) {
                tempf = map1[v2s16(x, y)];
            }
        }
    }

    {
        infostream << "Around 5000/ms should do well here." << std::endl;
        TimeTaker timer("Testing mutex speed");

        JMutex m;
        u32 n = 0;
        u32 i = 0;
        do {
            n += 10000;
            for (; i < n; i++) {
                m.Lock();
                m.Unlock();
            }
        }
        // Do at least 10ms
        while(timer.getTimerTime() < 10);

        u32 dtime = timer.stop();
        u32 per_ms = n / dtime;
        infostream << "Done. " << dtime << "ms, " << per_ms << "/ms" << std::endl;
    }
}
コード例 #24
0
ファイル: main.cpp プロジェクト: Oblomov/minetest
void SpeedTests()
{
	{
		dstream<<"The following test should take around 20ms."<<std::endl;
		TimeTaker timer("Testing std::string speed");
		const u32 jj = 10000;
		for(u32 j=0; j<jj; j++)
		{
			tempstring = "";
			tempstring2 = "";
			const u32 ii = 10;
			for(u32 i=0; i<ii; i++){
				tempstring2 += "asd";
			}
			for(u32 i=0; i<ii+1; i++){
				tempstring += "asd";
				if(tempstring == tempstring2)
					break;
			}
		}
	}
	
	dstream<<"All of the following tests should take around 100ms each."
			<<std::endl;

	{
		TimeTaker timer("Testing floating-point conversion speed");
		tempf = 0.001;
		for(u32 i=0; i<4000000; i++){
			temp16 += tempf;
			tempf += 0.001;
		}
	}
	
	{
		TimeTaker timer("Testing floating-point vector speed");

		tempv3f1 = v3f(1,2,3);
		tempv3f2 = v3f(4,5,6);
		for(u32 i=0; i<10000000; i++){
			tempf += tempv3f1.dotProduct(tempv3f2);
			tempv3f2 += v3f(7,8,9);
		}
	}

	{
		TimeTaker timer("Testing core::map speed");
		
		core::map<v2s16, f32> map1;
		tempf = -324;
		const s16 ii=300;
		for(s16 y=0; y<ii; y++){
			for(s16 x=0; x<ii; x++){
				map1.insert(v2s16(x,y), tempf);
				tempf += 1;
			}
		}
		for(s16 y=ii-1; y>=0; y--){
			for(s16 x=0; x<ii; x++){
				tempf = map1[v2s16(x,y)];
			}
		}
	}

	{
		dstream<<"Around 5000/ms should do well here."<<std::endl;
		TimeTaker timer("Testing mutex speed");
		
		JMutex m;
		m.Init();
		u32 n = 0;
		u32 i = 0;
		do{
			n += 10000;
			for(; i<n; i++){
				m.Lock();
				m.Unlock();
			}
		}
		// Do at least 10ms
		while(timer.getTime() < 10);

		u32 dtime = timer.stop();
		u32 per_ms = n / dtime;
		dstream<<"Done. "<<dtime<<"ms, "
				<<per_ms<<"/ms"<<std::endl;
	}
}
コード例 #25
0
ファイル: mapgen_v6.cpp プロジェクト: Wayward1/freeminer
void MapgenV6::flowMud(s16 &mudflow_minpos, s16 &mudflow_maxpos)
{
	// 340ms @cs=8
	//TimeTaker timer1("flow mud");

	// Iterate a few times
	for (s16 k = 0; k < 3; k++) {
		for (s16 z = mudflow_minpos; z <= mudflow_maxpos; z++)
		for (s16 x = mudflow_minpos; x <= mudflow_maxpos; x++) {
			// Invert coordinates every 2nd iteration
			if (k % 2 == 0) {
				x = mudflow_maxpos - (x - mudflow_minpos);
				z = mudflow_maxpos - (z - mudflow_minpos);
			}

			// Node position in 2d
			v2s16 p2d = v2s16(node_min.X, node_min.Z) + v2s16(x, z);

			v3s16 em = vm->m_area.getExtent();
			u32 i = vm->m_area.index(p2d.X, node_max.Y, p2d.Y);
			s16 y = node_max.Y;

			while (y >= node_min.Y) {

			for (;; y--) {
				MapNode *n = NULL;
				// Find mud
				for (; y >= node_min.Y; y--) {
					n = &vm->m_data[i];
					if (n->getContent() == c_dirt ||
							n->getContent() == c_dirt_with_grass ||
							n->getContent() == c_gravel)
						break;

					vm->m_area.add_y(em, i, -1);
				}

				// Stop if out of area
				//if(vmanip.m_area.contains(i) == false)
				if (y < node_min.Y)
					break;

				if (n->getContent() == c_dirt ||
						n->getContent() == c_dirt_with_grass) {
					// Make it exactly mud
					n->setContent(c_dirt);

					// Don't flow it if the stuff under it is not mud
					{
						u32 i2 = i;
						vm->m_area.add_y(em, i2, -1);
						// Cancel if out of area
						if (vm->m_area.contains(i2) == false)
							continue;
						MapNode *n2 = &vm->m_data[i2];
						if (n2->getContent() != c_dirt &&
								n2->getContent() != c_dirt_with_grass)
							continue;
					}
				}

				v3s16 dirs4[4] = {
					v3s16(0, 0, 1), // back
					v3s16(1, 0, 0), // right
					v3s16(0, 0, -1), // front
					v3s16(-1, 0, 0), // left
				};

				// Check that upper is air or doesn't exist.
				// Cancel dropping if upper keeps it in place
				u32 i3 = i;
				vm->m_area.add_y(em, i3, 1);
				if (vm->m_area.contains(i3) == true &&
						ndef->get(vm->m_data[i3]).walkable)
					continue;

				// Drop mud on side
				for(u32 di = 0; di < 4; di++) {
					v3s16 dirp = dirs4[di];
					u32 i2 = i;
					// Move to side
					vm->m_area.add_p(em, i2, dirp);
					// Fail if out of area
					if (vm->m_area.contains(i2) == false)
						continue;
					// Check that side is air
					MapNode *n2 = &vm->m_data[i2];
					if (ndef->get(*n2).walkable)
						continue;
					// Check that under side is air
					vm->m_area.add_y(em, i2, -1);
					if (vm->m_area.contains(i2) == false)
						continue;
					n2 = &vm->m_data[i2];
					if (ndef->get(*n2).walkable)
						continue;
					// Loop further down until not air
					bool dropped_to_unknown = false;
					do {
						vm->m_area.add_y(em, i2, -1);
						n2 = &vm->m_data[i2];
						// if out of known area
						if(vm->m_area.contains(i2) == false ||
								n2->getContent() == CONTENT_IGNORE) {
							dropped_to_unknown = true;
							break;
						}
					} while (ndef->get(*n2).walkable == false);
					// Loop one up so that we're in air
					vm->m_area.add_y(em, i2, 1);
					n2 = &vm->m_data[i2];

					bool old_is_water = (n->getContent() == c_water_source);
					// Move mud to new place
					if (!dropped_to_unknown) {
						*n2 = *n;
						// Set old place to be air (or water)
						if(old_is_water)
							*n = MapNode(c_water_source);
						else
							*n = MapNode(CONTENT_AIR);
					}

					// Done
					break;
				}
			}
			}
		}
	}
}
コード例 #26
0
ファイル: mg_decoration.cpp プロジェクト: maksimkurb/minetest
size_t Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
{
	PseudoRandom ps(blockseed + 53);
	int carea_size = nmax.X - nmin.X + 1;

	// Divide area into parts
	if (carea_size % sidelen) {
		errorstream << "Decoration::placeDeco: chunk size is not divisible by "
			"sidelen; setting sidelen to " << carea_size << std::endl;
		sidelen = carea_size;
	}

	s16 divlen = carea_size / sidelen;
	int area = sidelen * sidelen;

	for (s16 z0 = 0; z0 < divlen; z0++)
	for (s16 x0 = 0; x0 < divlen; x0++) {
		v2s16 p2d_center( // Center position of part of division
			nmin.X + sidelen / 2 + sidelen * x0,
			nmin.Z + sidelen / 2 + sidelen * z0
		);
		v2s16 p2d_min( // Minimum edge of part of division
			nmin.X + sidelen * x0,
			nmin.Z + sidelen * z0
		);
		v2s16 p2d_max( // Maximum edge of part of division
			nmin.X + sidelen + sidelen * x0 - 1,
			nmin.Z + sidelen + sidelen * z0 - 1
		);

		// Amount of decorations
		float nval = (flags & DECO_USE_NOISE) ?
			NoisePerlin2D(&np, p2d_center.X, p2d_center.Y, mapseed) :
			fill_ratio;
		u32 deco_count = area * MYMAX(nval, 0.f);

		for (u32 i = 0; i < deco_count; i++) {
			s16 x = ps.range(p2d_min.X, p2d_max.X);
			s16 z = ps.range(p2d_min.Y, p2d_max.Y);

			int mapindex = carea_size * (z - nmin.Z) + (x - nmin.X);

			s16 y = mg->heightmap ?
					mg->heightmap[mapindex] :
					mg->findGroundLevel(v2s16(x, z), nmin.Y, nmax.Y);

			if (y < nmin.Y || y > nmax.Y ||
				y < y_min  || y > y_max)
				continue;

			if (y + getHeight() >= mg->vm->m_area.MaxEdge.Y) {
				continue;
#if 0
				printf("Decoration at (%d %d %d) cut off\n", x, y, z);
				//add to queue
				JMutexAutoLock cutofflock(cutoff_mutex);
				cutoffs.push_back(CutoffData(x, y, z, height));
#endif
			}

			if (mg->biomemap) {
				std::set<u8>::iterator iter;

				if (!biomes.empty()) {
					iter = biomes.find(mg->biomemap[mapindex]);
					if (iter == biomes.end())
						continue;
				}
			}

			v3s16 pos(x, y, z);
			if (generate(mg->vm, &ps, pos))
				mg->gennotify.addEvent(GENNOTIFY_DECORATION, pos, index);
		}
	}

	return 0;
}
コード例 #27
0
ファイル: main.cpp プロジェクト: FessWolf/minetest
int main(int argc, char *argv[])
{
	int retval = 0;

	/*
		Initialization
	*/

	log_add_output_maxlev(&main_stderr_log_out, LMT_ACTION);
	log_add_output_all_levs(&main_dstream_no_stderr_log_out);

	log_register_thread("main");
	/*
		Parse command line
	*/

	// List all allowed options
	std::map<std::string, ValueSpec> allowed_options;
	allowed_options.insert(std::make_pair("help", ValueSpec(VALUETYPE_FLAG,
			_("Show allowed options"))));
	allowed_options.insert(std::make_pair("version", ValueSpec(VALUETYPE_FLAG,
			_("Show version information"))));
	allowed_options.insert(std::make_pair("config", ValueSpec(VALUETYPE_STRING,
			_("Load configuration from specified file"))));
	allowed_options.insert(std::make_pair("port", ValueSpec(VALUETYPE_STRING,
			_("Set network port (UDP)"))));
	allowed_options.insert(std::make_pair("disable-unittests", ValueSpec(VALUETYPE_FLAG,
			_("Disable unit tests"))));
	allowed_options.insert(std::make_pair("enable-unittests", ValueSpec(VALUETYPE_FLAG,
			_("Enable unit tests"))));
	allowed_options.insert(std::make_pair("map-dir", ValueSpec(VALUETYPE_STRING,
			_("Same as --world (deprecated)"))));
	allowed_options.insert(std::make_pair("world", ValueSpec(VALUETYPE_STRING,
			_("Set world path (implies local game) ('list' lists all)"))));
	allowed_options.insert(std::make_pair("worldname", ValueSpec(VALUETYPE_STRING,
			_("Set world by name (implies local game)"))));
	allowed_options.insert(std::make_pair("info", ValueSpec(VALUETYPE_FLAG,
			_("Print more information to console"))));
	allowed_options.insert(std::make_pair("verbose",  ValueSpec(VALUETYPE_FLAG,
			_("Print even more information to console"))));
	allowed_options.insert(std::make_pair("trace", ValueSpec(VALUETYPE_FLAG,
			_("Print enormous amounts of information to log and console"))));
	allowed_options.insert(std::make_pair("logfile", ValueSpec(VALUETYPE_STRING,
			_("Set logfile path ('' = no logging)"))));
	allowed_options.insert(std::make_pair("gameid", ValueSpec(VALUETYPE_STRING,
			_("Set gameid (\"--gameid list\" prints available ones)"))));
	allowed_options.insert(std::make_pair("migrate", ValueSpec(VALUETYPE_STRING,
			_("Migrate from current map backend to another (Only works when using minetestserver or with --server)"))));
#ifndef SERVER
	allowed_options.insert(std::make_pair("videomodes", ValueSpec(VALUETYPE_FLAG,
			_("Show available video modes"))));
	allowed_options.insert(std::make_pair("speedtests", ValueSpec(VALUETYPE_FLAG,
			_("Run speed tests"))));
	allowed_options.insert(std::make_pair("address", ValueSpec(VALUETYPE_STRING,
			_("Address to connect to. ('' = local game)"))));
	allowed_options.insert(std::make_pair("random-input", ValueSpec(VALUETYPE_FLAG,
			_("Enable random user input, for testing"))));
	allowed_options.insert(std::make_pair("server", ValueSpec(VALUETYPE_FLAG,
			_("Run dedicated server"))));
	allowed_options.insert(std::make_pair("name", ValueSpec(VALUETYPE_STRING,
			_("Set player name"))));
	allowed_options.insert(std::make_pair("password", ValueSpec(VALUETYPE_STRING,
			_("Set password"))));
	allowed_options.insert(std::make_pair("go", ValueSpec(VALUETYPE_FLAG,
			_("Disable main menu"))));
#endif

	Settings cmd_args;

	bool ret = cmd_args.parseCommandLine(argc, argv, allowed_options);

	if(ret == false || cmd_args.getFlag("help") || cmd_args.exists("nonopt1"))
	{
		dstream<<_("Allowed options:")<<std::endl;
		for(std::map<std::string, ValueSpec>::iterator
				i = allowed_options.begin();
				i != allowed_options.end(); ++i)
		{
			std::ostringstream os1(std::ios::binary);
			os1<<"  --"<<i->first;
			if(i->second.type == VALUETYPE_FLAG)
				{}
			else
				os1<<_(" <value>");
			dstream<<padStringRight(os1.str(), 24);

			if(i->second.help != NULL)
				dstream<<i->second.help;
			dstream<<std::endl;
		}

		return cmd_args.getFlag("help") ? 0 : 1;
	}

	if(cmd_args.getFlag("version"))
	{
#ifdef SERVER
		dstream<<"minetestserver "<<minetest_version_hash<<std::endl;
#else
		dstream<<"Minetest "<<minetest_version_hash<<std::endl;
		dstream<<"Using Irrlicht "<<IRRLICHT_SDK_VERSION<<std::endl;
#endif
		dstream<<"Build info: "<<minetest_build_info<<std::endl;
		return 0;
	}

	/*
		Low-level initialization
	*/

	// If trace is enabled, enable logging of certain things
	if(cmd_args.getFlag("trace")){
		dstream<<_("Enabling trace level debug output")<<std::endl;
		log_trace_level_enabled = true;
		dout_con_ptr = &verbosestream; // this is somewhat old crap
		socket_enable_debug_output = true; // socket doesn't use log.h
	}
	// In certain cases, output info level on stderr
	if(cmd_args.getFlag("info") || cmd_args.getFlag("verbose") ||
			cmd_args.getFlag("trace") || cmd_args.getFlag("speedtests"))
		log_add_output(&main_stderr_log_out, LMT_INFO);
	// In certain cases, output verbose level on stderr
	if(cmd_args.getFlag("verbose") || cmd_args.getFlag("trace"))
		log_add_output(&main_stderr_log_out, LMT_VERBOSE);

	porting::signal_handler_init();
	bool &kill = *porting::signal_handler_killstatus();

	porting::initializePaths();

	// Create user data directory
	fs::CreateDir(porting::path_user);

	infostream<<"path_share = "<<porting::path_share<<std::endl;
	infostream<<"path_user  = "******"gameid") && cmd_args.get("gameid") == "list")
	{
		std::set<std::string> gameids = getAvailableGameIds();
		for(std::set<std::string>::const_iterator i = gameids.begin();
				i != gameids.end(); i++)
			dstream<<(*i)<<std::endl;
		return 0;
	}

	// List worlds if requested
	if(cmd_args.exists("world") && cmd_args.get("world") == "list"){
		dstream<<_("Available worlds:")<<std::endl;
		std::vector<WorldSpec> worldspecs = getAvailableWorlds();
		print_worldspecs(worldspecs, dstream);
		return 0;
	}

	// Print startup message
	infostream<<PROJECT_NAME<<
			" "<<_("with")<<" SER_FMT_VER_HIGHEST_READ="<<(int)SER_FMT_VER_HIGHEST_READ
			<<", "<<minetest_build_info
			<<std::endl;

	/*
		Basic initialization
	*/

	// Initialize default settings
	set_default_settings(g_settings);

	// Initialize sockets
	sockets_init();
	atexit(sockets_cleanup);

	/*
		Read config file
	*/

	// Path of configuration file in use
	g_settings_path = "";

	if(cmd_args.exists("config"))
	{
		bool r = g_settings->readConfigFile(cmd_args.get("config").c_str());
		if(r == false)
		{
			errorstream<<"Could not read configuration from \""
					<<cmd_args.get("config")<<"\""<<std::endl;
			return 1;
		}
		g_settings_path = cmd_args.get("config");
	}
	else
	{
		std::vector<std::string> filenames;
		filenames.push_back(porting::path_user +
				DIR_DELIM + "minetest.conf");
		// Legacy configuration file location
		filenames.push_back(porting::path_user +
				DIR_DELIM + ".." + DIR_DELIM + "minetest.conf");
#if RUN_IN_PLACE
		// Try also from a lower level (to aid having the same configuration
		// for many RUN_IN_PLACE installs)
		filenames.push_back(porting::path_user +
				DIR_DELIM + ".." + DIR_DELIM + ".." + DIR_DELIM + "minetest.conf");
#endif

		for(u32 i=0; i<filenames.size(); i++)
		{
			bool r = g_settings->readConfigFile(filenames[i].c_str());
			if(r)
			{
				g_settings_path = filenames[i];
				break;
			}
		}

		// If no path found, use the first one (menu creates the file)
		if(g_settings_path == "")
			g_settings_path = filenames[0];
	}

	// Initialize debug streams
#define DEBUGFILE "debug.txt"
#if RUN_IN_PLACE
	std::string logfile = DEBUGFILE;
#else
	std::string logfile = porting::path_user+DIR_DELIM+DEBUGFILE;
#endif
	if(cmd_args.exists("logfile"))
		logfile = cmd_args.get("logfile");

	log_remove_output(&main_dstream_no_stderr_log_out);
	int loglevel = g_settings->getS32("debug_log_level");

	if (loglevel == 0) //no logging
		logfile = "";
	else if (loglevel > 0 && loglevel <= LMT_NUM_VALUES)
		log_add_output_maxlev(&main_dstream_no_stderr_log_out, (LogMessageLevel)(loglevel - 1));

	if(logfile != "")
		debugstreams_init(false, logfile.c_str());
	else
		debugstreams_init(false, NULL);

	infostream<<"logfile    = "<<logfile<<std::endl;

	// Initialize random seed
	srand(time(0));
	mysrand(time(0));

	// Initialize HTTP fetcher
	httpfetch_init(g_settings->getS32("curl_parallel_limit"));

	/*
		Run unit tests
	*/

	if((ENABLE_TESTS && cmd_args.getFlag("disable-unittests") == false)
			|| cmd_args.getFlag("enable-unittests") == true)
	{
		run_tests();
	}
#ifdef _MSC_VER
	init_gettext((porting::path_share + DIR_DELIM + "locale").c_str(),g_settings->get("language"),argc,argv);
#else
	init_gettext((porting::path_share + DIR_DELIM + "locale").c_str(),g_settings->get("language"));
#endif

	/*
		Game parameters
	*/

	// Port
	u16 port = 30000;
	if(cmd_args.exists("port"))
		port = cmd_args.getU16("port");
	else if(g_settings->exists("port"))
		port = g_settings->getU16("port");
	if(port == 0)
		port = 30000;

	// World directory
	std::string commanded_world = "";
	if(cmd_args.exists("world"))
		commanded_world = cmd_args.get("world");
	else if(cmd_args.exists("map-dir"))
		commanded_world = cmd_args.get("map-dir");
	else if(cmd_args.exists("nonopt0")) // First nameless argument
		commanded_world = cmd_args.get("nonopt0");
	else if(g_settings->exists("map-dir"))
		commanded_world = g_settings->get("map-dir");

	// World name
	std::string commanded_worldname = "";
	if(cmd_args.exists("worldname"))
		commanded_worldname = cmd_args.get("worldname");

	// Strip world.mt from commanded_world
	{
		std::string worldmt = "world.mt";
		if(commanded_world.size() > worldmt.size() &&
				commanded_world.substr(commanded_world.size()-worldmt.size())
				== worldmt){
			dstream<<_("Supplied world.mt file - stripping it off.")<<std::endl;
			commanded_world = commanded_world.substr(
					0, commanded_world.size()-worldmt.size());
		}
	}

	// If a world name was specified, convert it to a path
	if(commanded_worldname != ""){
		// Get information about available worlds
		std::vector<WorldSpec> worldspecs = getAvailableWorlds();
		bool found = false;
		for(u32 i=0; i<worldspecs.size(); i++){
			std::string name = worldspecs[i].name;
			if(name == commanded_worldname){
				if(commanded_world != ""){
					dstream<<_("--worldname takes precedence over previously "
							"selected world.")<<std::endl;
				}
				commanded_world = worldspecs[i].path;
				found = true;
				break;
			}
		}
		if(!found){
			dstream<<_("World")<<" '"<<commanded_worldname<<_("' not "
					"available. Available worlds:")<<std::endl;
			print_worldspecs(worldspecs, dstream);
			return 1;
		}
	}

	// Gamespec
	SubgameSpec commanded_gamespec;
	if(cmd_args.exists("gameid")){
		std::string gameid = cmd_args.get("gameid");
		commanded_gamespec = findSubgame(gameid);
		if(!commanded_gamespec.isValid()){
			errorstream<<"Game \""<<gameid<<"\" not found"<<std::endl;
			return 1;
		}
	}


	/*
		Run dedicated server if asked to or no other option
	*/
#ifdef SERVER
	bool run_dedicated_server = true;
#else
	bool run_dedicated_server = cmd_args.getFlag("server");
#endif
	g_settings->set("server_dedicated", run_dedicated_server ? "true" : "false");
	if(run_dedicated_server)
	{
		DSTACK("Dedicated server branch");
		// Create time getter if built with Irrlicht
#ifndef SERVER
		g_timegetter = new SimpleTimeGetter();
#endif

		// World directory
		std::string world_path;
		verbosestream<<_("Determining world path")<<std::endl;
		bool is_legacy_world = false;
		// If a world was commanded, use it
		if(commanded_world != ""){
			world_path = commanded_world;
			infostream<<"Using commanded world path ["<<world_path<<"]"
					<<std::endl;
		}
		// No world was specified; try to select it automatically
		else
		{
			// Get information about available worlds
			std::vector<WorldSpec> worldspecs = getAvailableWorlds();
			// If a world name was specified, select it
			if(commanded_worldname != ""){
				world_path = "";
				for(u32 i=0; i<worldspecs.size(); i++){
					std::string name = worldspecs[i].name;
					if(name == commanded_worldname){
						world_path = worldspecs[i].path;
						break;
					}
				}
				if(world_path == ""){
					dstream<<_("World")<<" '"<<commanded_worldname<<"' "<<_("not "
							"available. Available worlds:")<<std::endl;
					print_worldspecs(worldspecs, dstream);
					return 1;
				}
			}
			// If there is only a single world, use it
			if(worldspecs.size() == 1){
				world_path = worldspecs[0].path;
				dstream<<_("Automatically selecting world at")<<" ["
						<<world_path<<"]"<<std::endl;
			// If there are multiple worlds, list them
			} else if(worldspecs.size() > 1){
				dstream<<_("Multiple worlds are available.")<<std::endl;
				dstream<<_("Please select one using --worldname <name>"
						" or --world <path>")<<std::endl;
				print_worldspecs(worldspecs, dstream);
				return 1;
			// If there are no worlds, automatically create a new one
			} else {
				// This is the ultimate default world path
				world_path = porting::path_user + DIR_DELIM + "worlds" +
						DIR_DELIM + "world";
				infostream<<"Creating default world at ["
						<<world_path<<"]"<<std::endl;
			}
		}

		if(world_path == ""){
			errorstream<<"No world path specified or found."<<std::endl;
			return 1;
		}
		verbosestream<<_("Using world path")<<" ["<<world_path<<"]"<<std::endl;

		// We need a gamespec.
		SubgameSpec gamespec;
		verbosestream<<_("Determining gameid/gamespec")<<std::endl;
		// If world doesn't exist
		if(!getWorldExists(world_path))
		{
			// Try to take gamespec from command line
			if(commanded_gamespec.isValid()){
				gamespec = commanded_gamespec;
				infostream<<"Using commanded gameid ["<<gamespec.id<<"]"<<std::endl;
			}
			// Otherwise we will be using "minetest"
			else{
				gamespec = findSubgame(g_settings->get("default_game"));
				infostream<<"Using default gameid ["<<gamespec.id<<"]"<<std::endl;
			}
		}
		// World exists
		else
		{
			std::string world_gameid = getWorldGameId(world_path, is_legacy_world);
			// If commanded to use a gameid, do so
			if(commanded_gamespec.isValid()){
				gamespec = commanded_gamespec;
				if(commanded_gamespec.id != world_gameid){
					errorstream<<"WARNING: Using commanded gameid ["
							<<gamespec.id<<"]"<<" instead of world gameid ["
							<<world_gameid<<"]"<<std::endl;
				}
			} else{
				// If world contains an embedded game, use it;
				// Otherwise find world from local system.
				gamespec = findWorldSubgame(world_path);
				infostream<<"Using world gameid ["<<gamespec.id<<"]"<<std::endl;
			}
		}
		if(!gamespec.isValid()){
			errorstream<<"Subgame ["<<gamespec.id<<"] could not be found."
					<<std::endl;
			return 1;
		}
		verbosestream<<_("Using gameid")<<" ["<<gamespec.id<<"]"<<std::endl;

		// Bind address
		std::string bind_str = g_settings->get("bind_address");
		Address bind_addr(0,0,0,0, port);

		if (g_settings->getBool("ipv6_server")) {
			bind_addr.setAddress((IPv6AddressBytes*) NULL);
		}
		try {
			bind_addr.Resolve(bind_str.c_str());
		} catch (ResolveError &e) {
			infostream << "Resolving bind address \"" << bind_str
			           << "\" failed: " << e.what()
		        	   << " -- Listening on all addresses." << std::endl;
		}
		if(bind_addr.isIPv6() && !g_settings->getBool("enable_ipv6")) {
			errorstream << "Unable to listen on "
			            << bind_addr.serializeString()
				    << L" because IPv6 is disabled" << std::endl;
			return 1;
		}

		// Create server
		Server server(world_path, gamespec, false, bind_addr.isIPv6());

		// Database migration
		if (cmd_args.exists("migrate")) {
			std::string migrate_to = cmd_args.get("migrate");
			Settings world_mt;
			bool success = world_mt.readConfigFile((world_path + DIR_DELIM + "world.mt").c_str());
			if (!success) {
				errorstream << "Cannot read world.mt" << std::endl;
				return 1;
			}
			if (!world_mt.exists("backend")) {
				errorstream << "Please specify your current backend in world.mt file:"
					<< std::endl << "	backend = {sqlite3|leveldb|redis|dummy}" << std::endl;
				return 1;
			}
			std::string backend = world_mt.get("backend");
			Database *new_db;
			if (backend == migrate_to) {
				errorstream << "Cannot migrate: new backend is same as the old one" << std::endl;
				return 1;
			}
			if (migrate_to == "sqlite3")
				new_db = new Database_SQLite3(&(ServerMap&)server.getMap(), world_path);
			#if USE_LEVELDB
			else if (migrate_to == "leveldb")
				new_db = new Database_LevelDB(&(ServerMap&)server.getMap(), world_path);
			#endif
			#if USE_REDIS
			else if (migrate_to == "redis")
				new_db = new Database_Redis(&(ServerMap&)server.getMap(), world_path);
			#endif
			else {
				errorstream << "Migration to " << migrate_to << " is not supported" << std::endl;
				return 1;
			}

			std::list<v3s16> blocks;
			ServerMap &old_map = ((ServerMap&)server.getMap());
			old_map.listAllLoadableBlocks(blocks);
			int count = 0;
			new_db->beginSave();
			for (std::list<v3s16>::iterator i = blocks.begin(); i != blocks.end(); ++i) {
				MapBlock *block = old_map.loadBlock(*i);
				new_db->saveBlock(block);
				MapSector *sector = old_map.getSectorNoGenerate(v2s16(i->X, i->Z));
				sector->deleteBlock(block);
				++count;
				if (count % 500 == 0)
					actionstream << "Migrated " << count << " blocks "
						<< (100.0 * count / blocks.size()) << "% completed" << std::endl;
			}
			new_db->endSave();
			delete new_db;

			actionstream << "Successfully migrated " << count << " blocks" << std::endl;
			world_mt.set("backend", migrate_to);
			if(!world_mt.updateConfigFile((world_path + DIR_DELIM + "world.mt").c_str()))
				errorstream<<"Failed to update world.mt!"<<std::endl;
			else
				actionstream<<"world.mt updated"<<std::endl;

			return 0;
		}

		server.start(bind_addr);

		// Run server
		dedicated_server_loop(server, kill);

		return 0;
	}

#ifndef SERVER // Exclude from dedicated server build

	/*
		More parameters
	*/

	std::string address = g_settings->get("address");
	if(commanded_world != "")
		address = "";
	else if(cmd_args.exists("address"))
		address = cmd_args.get("address");

	std::string playername = g_settings->get("name");
	if(cmd_args.exists("name"))
		playername = cmd_args.get("name");

	bool skip_main_menu = cmd_args.getFlag("go");

	/*
		Device initialization
	*/

	// Resolution selection

	bool fullscreen = g_settings->getBool("fullscreen");
	u16 screenW = g_settings->getU16("screenW");
	u16 screenH = g_settings->getU16("screenH");

	// bpp, fsaa, vsync

	bool vsync = g_settings->getBool("vsync");
	u16 bits = g_settings->getU16("fullscreen_bpp");
	u16 fsaa = g_settings->getU16("fsaa");

	// Determine driver

	video::E_DRIVER_TYPE driverType;

	std::string driverstring = g_settings->get("video_driver");

	if(driverstring == "null")
		driverType = video::EDT_NULL;
	else if(driverstring == "software")
		driverType = video::EDT_SOFTWARE;
	else if(driverstring == "burningsvideo")
		driverType = video::EDT_BURNINGSVIDEO;
	else if(driverstring == "direct3d8")
		driverType = video::EDT_DIRECT3D8;
	else if(driverstring == "direct3d9")
		driverType = video::EDT_DIRECT3D9;
	else if(driverstring == "opengl")
		driverType = video::EDT_OPENGL;
#ifdef _IRR_COMPILE_WITH_OGLES1_
	else if(driverstring == "ogles1")
		driverType = video::EDT_OGLES1;
#endif
#ifdef _IRR_COMPILE_WITH_OGLES2_
	else if(driverstring == "ogles2")
		driverType = video::EDT_OGLES2;
#endif
	else
	{
		errorstream<<"WARNING: Invalid video_driver specified; defaulting "
				"to opengl"<<std::endl;
		driverType = video::EDT_OPENGL;
	}

	/*
		List video modes if requested
	*/

	MyEventReceiver receiver;

	if(cmd_args.getFlag("videomodes")){
		IrrlichtDevice *nulldevice;

		SIrrlichtCreationParameters params = SIrrlichtCreationParameters();
		params.DriverType    = video::EDT_NULL;
		params.WindowSize    = core::dimension2d<u32>(640, 480);
		params.Bits          = 24;
		params.AntiAlias     = fsaa;
		params.Fullscreen    = false;
		params.Stencilbuffer = false;
		params.Vsync         = vsync;
		params.EventReceiver = &receiver;
		params.HighPrecisionFPU = g_settings->getBool("high_precision_fpu");

		nulldevice = createDeviceEx(params);

		if(nulldevice == 0)
			return 1;

		dstream<<_("Available video modes (WxHxD):")<<std::endl;

		video::IVideoModeList *videomode_list =
				nulldevice->getVideoModeList();

		if(videomode_list == 0){
			nulldevice->drop();
			return 1;
		}

		s32 videomode_count = videomode_list->getVideoModeCount();
		core::dimension2d<u32> videomode_res;
		s32 videomode_depth;
		for (s32 i = 0; i < videomode_count; ++i){
			videomode_res = videomode_list->getVideoModeResolution(i);
			videomode_depth = videomode_list->getVideoModeDepth(i);
			dstream<<videomode_res.Width<<"x"<<videomode_res.Height
					<<"x"<<videomode_depth<<std::endl;
		}

		dstream<<_("Active video mode (WxHxD):")<<std::endl;
		videomode_res = videomode_list->getDesktopResolution();
		videomode_depth = videomode_list->getDesktopDepth();
		dstream<<videomode_res.Width<<"x"<<videomode_res.Height
				<<"x"<<videomode_depth<<std::endl;

		nulldevice->drop();

		return 0;
	}

	/*
		Create device and exit if creation failed
	*/

	IrrlichtDevice *device;

	SIrrlichtCreationParameters params = SIrrlichtCreationParameters();
	params.DriverType    = driverType;
	params.WindowSize    = core::dimension2d<u32>(screenW, screenH);
	params.Bits          = bits;
	params.AntiAlias     = fsaa;
	params.Fullscreen    = fullscreen;
	params.Stencilbuffer = false;
	params.Vsync         = vsync;
	params.EventReceiver = &receiver;
	params.HighPrecisionFPU = g_settings->getBool("high_precision_fpu");

	device = createDeviceEx(params);

	if (device == 0)
		return 1; // could not create selected driver.

	/*
		Continue initialization
	*/

	video::IVideoDriver* driver = device->getVideoDriver();

	/*
		This changes the minimum allowed number of vertices in a VBO.
		Default is 500.
	*/
	//driver->setMinHardwareBufferVertexCount(50);

	// Create time getter
	g_timegetter = new IrrlichtTimeGetter(device);

	// Create game callback for menus
	g_gamecallback = new MainGameCallback(device);

	/*
		Speed tests (done after irrlicht is loaded to get timer)
	*/
	if(cmd_args.getFlag("speedtests"))
	{
		dstream<<"Running speed tests"<<std::endl;
		SpeedTests();
		device->drop();
		return 0;
	}

	device->setResizable(true);

	bool random_input = g_settings->getBool("random_input")
			|| cmd_args.getFlag("random-input");
	InputHandler *input = NULL;
	if(random_input) {
		input = new RandomInputHandler();
	} else {
		input = new RealInputHandler(device, &receiver);
	}

	scene::ISceneManager* smgr = device->getSceneManager();

	guienv = device->getGUIEnvironment();
	gui::IGUISkin* skin = guienv->getSkin();
	std::string font_path = g_settings->get("font_path");
	gui::IGUIFont *font;
	#if USE_FREETYPE
	bool use_freetype = g_settings->getBool("freetype");
	if (use_freetype) {
		std::string fallback;
		if (is_yes(gettext("needs_fallback_font")))
			fallback = "fallback_";
		u16 font_size = g_settings->getU16(fallback + "font_size");
		font_path = g_settings->get(fallback + "font_path");
		u32 font_shadow = g_settings->getU16(fallback + "font_shadow");
		u32 font_shadow_alpha = g_settings->getU16(fallback + "font_shadow_alpha");
		font = gui::CGUITTFont::createTTFont(guienv, font_path.c_str(), font_size, true, true, font_shadow, font_shadow_alpha);
	} else {
		font = guienv->getFont(font_path.c_str());
	}
	#else
	font = guienv->getFont(font_path.c_str());
	#endif
	if(font)
		skin->setFont(font);
	else
		errorstream<<"WARNING: Font file was not found."
				" Using default font."<<std::endl;
	// If font was not found, this will get us one
	font = skin->getFont();
	assert(font);

	u32 text_height = font->getDimension(L"Hello, world!").Height;
	infostream<<"text_height="<<text_height<<std::endl;

	//skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,0,0,0));
	skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,255,255,255));
	//skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(0,0,0,0));
	//skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(0,0,0,0));
	skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255,0,0,0));
	skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255,0,0,0));
	skin->setColor(gui::EGDC_HIGH_LIGHT, video::SColor(255,70,100,50));
	skin->setColor(gui::EGDC_HIGH_LIGHT_TEXT, video::SColor(255,255,255,255));

#if (IRRLICHT_VERSION_MAJOR >= 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2
	// Irrlicht 1.8 input colours
	skin->setColor(gui::EGDC_EDITABLE, video::SColor(255,128,128,128));
	skin->setColor(gui::EGDC_FOCUSED_EDITABLE, video::SColor(255,96,134,49));
#endif


	// Create the menu clouds
	if (!g_menucloudsmgr)
		g_menucloudsmgr = smgr->createNewSceneManager();
	if (!g_menuclouds)
		g_menuclouds = new Clouds(g_menucloudsmgr->getRootSceneNode(),
			g_menucloudsmgr, -1, rand(), 100);
	g_menuclouds->update(v2f(0, 0), video::SColor(255,200,200,255));
	scene::ICameraSceneNode* camera;
	camera = g_menucloudsmgr->addCameraSceneNode(0,
				v3f(0,0,0), v3f(0, 60, 100));
	camera->setFarValue(10000);

	/*
		GUI stuff
	*/

	ChatBackend chat_backend;

	/*
		If an error occurs, this is set to something and the
		menu-game loop is restarted. It is then displayed before
		the menu.
	*/
	std::wstring error_message = L"";

	// The password entered during the menu screen,
	std::string password;

	bool first_loop = true;

	/*
		Menu-game loop
	*/
	while(device->run() && kill == false)
	{
		// Set the window caption
		wchar_t* text = wgettext("Main Menu");
		device->setWindowCaption((std::wstring(L"Minetest [")+text+L"]").c_str());
		delete[] text;

		// This is used for catching disconnects
		try
		{

			/*
				Clear everything from the GUIEnvironment
			*/
			guienv->clear();

			/*
				We need some kind of a root node to be able to add
				custom gui elements directly on the screen.
				Otherwise they won't be automatically drawn.
			*/
			guiroot = guienv->addStaticText(L"",
					core::rect<s32>(0, 0, 10000, 10000));

			SubgameSpec gamespec;
			WorldSpec worldspec;
			bool simple_singleplayer_mode = false;

			// These are set up based on the menu and other things
			std::string current_playername = "inv£lid";
			std::string current_password = "";
			std::string current_address = "does-not-exist";
			int current_port = 0;

			/*
				Out-of-game menu loop.

				Loop quits when menu returns proper parameters.
			*/
			while(kill == false)
			{
				// If skip_main_menu, only go through here once
				if(skip_main_menu && !first_loop){
					kill = true;
					break;
				}
				first_loop = false;

				// Cursor can be non-visible when coming from the game
				device->getCursorControl()->setVisible(true);
				// Some stuff are left to scene manager when coming from the game
				// (map at least?)
				smgr->clear();

				// Initialize menu data
				MainMenuData menudata;
				menudata.address = address;
				menudata.name = playername;
				menudata.port = itos(port);
				menudata.errormessage = wide_to_narrow(error_message);
				error_message = L"";
				if(cmd_args.exists("password"))
					menudata.password = cmd_args.get("password");

				driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, g_settings->getBool("mip_map"));

				menudata.enable_public = g_settings->getBool("server_announce");

				std::vector<WorldSpec> worldspecs = getAvailableWorlds();

				// If a world was commanded, append and select it
				if(commanded_world != ""){

					std::string gameid = getWorldGameId(commanded_world, true);
					std::string name = _("[--world parameter]");
					if(gameid == ""){
						gameid = g_settings->get("default_game");
						name += " [new]";
					}
					//TODO find within worldspecs and set config
				}

				if(skip_main_menu == false)
				{
					video::IVideoDriver* driver = device->getVideoDriver();

					infostream<<"Waiting for other menus"<<std::endl;
					while(device->run() && kill == false)
					{
						if(noMenuActive())
							break;
						driver->beginScene(true, true,
								video::SColor(255,128,128,128));
						guienv->drawAll();
						driver->endScene();
						// On some computers framerate doesn't seem to be
						// automatically limited
						sleep_ms(25);
					}
					infostream<<"Waited for other menus"<<std::endl;

					GUIEngine* temp = new GUIEngine(device, guiroot, &g_menumgr,smgr,&menudata,kill);

					delete temp;
					//once finished you'll never end up here
					smgr->clear();
				}

				if(menudata.errormessage != ""){
					error_message = narrow_to_wide(menudata.errormessage);
					continue;
				}

				//update worldspecs (necessary as new world may have been created)
				worldspecs = getAvailableWorlds();

				if (menudata.name == "")
					menudata.name = std::string("Guest") + itos(myrand_range(1000,9999));
				else
					playername = menudata.name;

				password = translatePassword(playername, narrow_to_wide(menudata.password));
				//infostream<<"Main: password hash: '"<<password<<"'"<<std::endl;

				address = menudata.address;
				int newport = stoi(menudata.port);
				if(newport != 0)
					port = newport;

				simple_singleplayer_mode = menudata.simple_singleplayer_mode;

				// Save settings
				g_settings->set("name", playername);

				if((menudata.selected_world >= 0) &&
						(menudata.selected_world < (int)worldspecs.size()))
					g_settings->set("selected_world_path",
							worldspecs[menudata.selected_world].path);

				// Break out of menu-game loop to shut down cleanly
				if(device->run() == false || kill == true)
					break;

				current_playername = playername;
				current_password = password;
				current_address = address;
				current_port = port;

				// If using simple singleplayer mode, override
				if(simple_singleplayer_mode){
					current_playername = "singleplayer";
					current_password = "";
					current_address = "";
					current_port = myrand_range(49152, 65535);
				}
				else if (address != "")
				{
					ServerListSpec server;
					server["name"] = menudata.servername;
					server["address"] = menudata.address;
					server["port"] = menudata.port;
					server["description"] = menudata.serverdescription;
					ServerList::insert(server);
				}

				// Set world path to selected one
				if ((menudata.selected_world >= 0) &&
					(menudata.selected_world < (int)worldspecs.size())) {
					worldspec = worldspecs[menudata.selected_world];
					infostream<<"Selected world: "<<worldspec.name
							<<" ["<<worldspec.path<<"]"<<std::endl;
				}

				// If local game
				if(current_address == "")
				{
					if(menudata.selected_world == -1){
						error_message = wgettext("No world selected and no address "
								"provided. Nothing to do.");
						errorstream<<wide_to_narrow(error_message)<<std::endl;
						continue;
					}
					// Load gamespec for required game
					gamespec = findWorldSubgame(worldspec.path);
					if(!gamespec.isValid() && !commanded_gamespec.isValid()){
						error_message = wgettext("Could not find or load game \"")
								+ narrow_to_wide(worldspec.gameid) + L"\"";
						errorstream<<wide_to_narrow(error_message)<<std::endl;
						continue;
					}
					if(commanded_gamespec.isValid() &&
							commanded_gamespec.id != worldspec.gameid){
						errorstream<<"WARNING: Overriding gamespec from \""
								<<worldspec.gameid<<"\" to \""
								<<commanded_gamespec.id<<"\""<<std::endl;
						gamespec = commanded_gamespec;
					}

					if(!gamespec.isValid()){
						error_message = wgettext("Invalid gamespec.");
						error_message += L" (world_gameid="
								+narrow_to_wide(worldspec.gameid)+L")";
						errorstream<<wide_to_narrow(error_message)<<std::endl;
						continue;
					}
				}

				// Continue to game
				break;
			}

			// Break out of menu-game loop to shut down cleanly
			if(device->run() == false || kill == true) {
				if(g_settings_path != "") {
					g_settings->updateConfigFile(
						g_settings_path.c_str());
				}
				break;
			}

			/*
				Run game
			*/
			the_game(
				kill,
				random_input,
				input,
				device,
				font,
				worldspec.path,
				current_playername,
				current_password,
				current_address,
				current_port,
				error_message,
				chat_backend,
				gamespec,
				simple_singleplayer_mode
			);
			smgr->clear();

		} //try
		catch(con::PeerNotFoundException &e)
		{
			error_message = wgettext("Connection error (timed out?)");
			errorstream<<wide_to_narrow(error_message)<<std::endl;
		}
#ifdef NDEBUG
		catch(std::exception &e)
		{
			std::string narrow_message = "Some exception: \"";
			narrow_message += e.what();
			narrow_message += "\"";
			errorstream<<narrow_message<<std::endl;
			error_message = narrow_to_wide(narrow_message);
		}
#endif

		// If no main menu, show error and exit
		if(skip_main_menu)
		{
			if(error_message != L""){
				verbosestream<<"error_message = "
						<<wide_to_narrow(error_message)<<std::endl;
				retval = 1;
			}
			break;
		}
	} // Menu-game loop


	g_menuclouds->drop();
	g_menucloudsmgr->drop();

	delete input;

	/*
		In the end, delete the Irrlicht device.
	*/
	device->drop();

#if USE_FREETYPE
	if (use_freetype)
		font->drop();
#endif

#endif // !SERVER

	// Update configuration file
	if(g_settings_path != "")
		g_settings->updateConfigFile(g_settings_path.c_str());

	// Print modified quicktune values
	{
		bool header_printed = false;
		std::vector<std::string> names = getQuicktuneNames();
		for(u32 i=0; i<names.size(); i++){
			QuicktuneValue val = getQuicktuneValue(names[i]);
			if(!val.modified)
				continue;
			if(!header_printed){
				dstream<<"Modified quicktune values:"<<std::endl;
				header_printed = true;
			}
			dstream<<names[i]<<" = "<<val.getString()<<std::endl;
		}
	}

	// Stop httpfetch thread (if started)
	httpfetch_cleanup();

	END_DEBUG_EXCEPTION_HANDLER(errorstream)

	debugstreams_deinit();

	return retval;
}
コード例 #28
0
ファイル: mapgen_v6.cpp プロジェクト: 4aiman/Magichet-stable
void MapgenV6::makeChunk(BlockMakeData *data)
{
	// Pre-conditions
	assert(data->vmanip);
	assert(data->nodedef);
	assert(data->blockpos_requested.X >= data->blockpos_min.X &&
		   data->blockpos_requested.Y >= data->blockpos_min.Y &&
		   data->blockpos_requested.Z >= data->blockpos_min.Z);
	assert(data->blockpos_requested.X <= data->blockpos_max.X &&
		   data->blockpos_requested.Y <= data->blockpos_max.Y &&
		   data->blockpos_requested.Z <= data->blockpos_max.Z);

	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_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_desert_stone;
			dp.c_moss   = c_desert_stone;
			dp.c_stair  = c_desert_stone;

			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;
}
コード例 #29
0
ファイル: mapgen.cpp プロジェクト: Nate-Devv/freeminer
void Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) {
	PseudoRandom ps(blockseed + 53);
	int carea_size = nmax.X - nmin.X + 1;

	// Divide area into parts
	if (carea_size % sidelen) {
		errorstream << "Decoration::placeDeco: chunk size is not divisible by "
			"sidelen; setting sidelen to " << carea_size << std::endl;
		sidelen = carea_size;
	}

	s16 divlen = carea_size / sidelen;
	int area = sidelen * sidelen;

	for (s16 z0 = 0; z0 < divlen; z0++)
	for (s16 x0 = 0; x0 < divlen; x0++) {
		v2s16 p2d_center( // Center position of part of division
			nmin.X + sidelen / 2 + sidelen * x0,
			nmin.Z + sidelen / 2 + sidelen * z0
		);
		v2s16 p2d_min( // Minimum edge of part of division
			nmin.X + sidelen * x0,
			nmin.Z + sidelen * z0
		);
		v2s16 p2d_max( // Maximum edge of part of division
			nmin.X + sidelen + sidelen * x0 - 1,
			nmin.Z + sidelen + sidelen * z0 - 1
		);

		// Amount of decorations
		float nval = np ?
			NoisePerlin2D(np, p2d_center.X, p2d_center.Y, mapseed) :
			fill_ratio;
		u32 deco_count = area * MYMAX(nval, 0.f);

		for (u32 i = 0; i < deco_count; i++) {
			s16 x = ps.range(p2d_min.X, p2d_max.X);
			s16 z = ps.range(p2d_min.Y, p2d_max.Y);

			int mapindex = carea_size * (z - nmin.Z) + (x - nmin.X);

			s16 y = mg->heightmap ?
					mg->heightmap[mapindex] :
					mg->findGroundLevel(v2s16(x, z), nmin.Y, nmax.Y);

			if (y < nmin.Y || y > nmax.Y)
				continue;

			int height = getHeight();
			int max_y = nmax.Y;// + MAP_BLOCKSIZE - 1;
			if (y + 1 + height > max_y) {
				continue;
#if 0
				printf("Decoration at (%d %d %d) cut off\n", x, y, z);
				//add to queue
				JMutexAutoLock cutofflock(cutoff_mutex);
				cutoffs.push_back(CutoffData(x, y, z, height));
#endif
			}

			if (mg->biomemap) {
				std::set<u8>::iterator iter;

				if (biomes.size()) {
					iter = biomes.find(mg->biomemap[mapindex]);
					if (iter == biomes.end())
						continue;
				}
			}

			generate(mg, &ps, max_y, v3s16(x, y, z));
		}
	}
}
コード例 #30
0
ファイル: farmesh.cpp プロジェクト: Neear/minetest
void FarMesh::render()
{
	video::IVideoDriver* driver = SceneManager->getVideoDriver();

	/*if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_TRANSPARENT)
		return;*/
	if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_SOLID)
		return;
	/*if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_SKY_BOX)
		return;*/

	driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
	
	//const s16 grid_radius_i = 12;
	//const float grid_size = BS*50;
	const s16 grid_radius_i = m_render_range/MAP_BLOCKSIZE;
	const float grid_size = BS*MAP_BLOCKSIZE;
	const v2f grid_speed(-BS*0, 0);
	
	// Position of grid noise origin in world coordinates
	v2f world_grid_origin_pos_f(0,0);
	// Position of grid noise origin from the camera
	v2f grid_origin_from_camera_f = world_grid_origin_pos_f - m_camera_pos;
	// The center point of drawing in the noise
	v2f center_of_drawing_in_noise_f = -grid_origin_from_camera_f;
	// The integer center point of drawing in the noise
	v2s16 center_of_drawing_in_noise_i(
		MYROUND(center_of_drawing_in_noise_f.X / grid_size),
		MYROUND(center_of_drawing_in_noise_f.Y / grid_size)
	);
	// The world position of the integer center point of drawing in the noise
	v2f world_center_of_drawing_in_noise_f = v2f(
		center_of_drawing_in_noise_i.X * grid_size,
		center_of_drawing_in_noise_i.Y * grid_size
	) + world_grid_origin_pos_f;

	for(s16 zi=-grid_radius_i; zi<grid_radius_i; zi++)
	for(s16 xi=-grid_radius_i; xi<grid_radius_i; xi++)
	{
		/*// Don't draw very close to player
		s16 dd = 3;
		if(zi > -dd && zi < dd && xi > -dd && xi < dd)
			continue;*/

		v2s16 p_in_noise_i(
			xi+center_of_drawing_in_noise_i.X,
			zi+center_of_drawing_in_noise_i.Y
		);
		
		// If sector was drawn, don't draw it this way
		if(m_client->m_env.getClientMap().sectorWasDrawn(p_in_noise_i))
			continue;

		/*if((p_in_noise_i.X + p_in_noise_i.Y)%2==0)
			continue;*/
		/*if((p_in_noise_i.X/2 + p_in_noise_i.Y/2)%2==0)
			continue;*/

		v2f p0 = v2f(xi,zi)*grid_size + world_center_of_drawing_in_noise_f;
		
		/*double noise[4];
		double d = 100*BS;
		noise[0] = d*noise2d_perlin(
				(float)(p_in_noise_i.X+0)*grid_size/BS/100,
				(float)(p_in_noise_i.Y+0)*grid_size/BS/100,
				m_seed, 3, 0.5);
		
		noise[1] = d*noise2d_perlin(
				(float)(p_in_noise_i.X+0)*grid_size/BS/100,
				(float)(p_in_noise_i.Y+1)*grid_size/BS/100,
				m_seed, 3, 0.5);
		
		noise[2] = d*noise2d_perlin(
				(float)(p_in_noise_i.X+1)*grid_size/BS/100,
				(float)(p_in_noise_i.Y+1)*grid_size/BS/100,
				m_seed, 3, 0.5);
		
		noise[3] = d*noise2d_perlin(
				(float)(p_in_noise_i.X+1)*grid_size/BS/100,
				(float)(p_in_noise_i.Y+0)*grid_size/BS/100,
				m_seed, 3, 0.5);*/
		
		HeightPoint hps[5];
		hps[0] = ground_height(m_seed, v2s16(
				(p_in_noise_i.X+0)*grid_size/BS,
				(p_in_noise_i.Y+0)*grid_size/BS));
		hps[1] = ground_height(m_seed, v2s16(
				(p_in_noise_i.X+0)*grid_size/BS,
				(p_in_noise_i.Y+1)*grid_size/BS));
		hps[2] = ground_height(m_seed, v2s16(
				(p_in_noise_i.X+1)*grid_size/BS,
				(p_in_noise_i.Y+1)*grid_size/BS));
		hps[3] = ground_height(m_seed, v2s16(
				(p_in_noise_i.X+1)*grid_size/BS,
				(p_in_noise_i.Y+0)*grid_size/BS));
		v2s16 centerpoint(
				(p_in_noise_i.X+0)*grid_size/BS+MAP_BLOCKSIZE/2,
				(p_in_noise_i.Y+0)*grid_size/BS+MAP_BLOCKSIZE/2);
		hps[4] = ground_height(m_seed, centerpoint);
		
		float noise[5];
		float h_min = BS*65535;
		float h_max = -BS*65536;
		float ma_avg = 0;
		float h_avg = 0;
		u32 have_sand_count = 0;
		float tree_amount_avg = 0;
		for(u32 i=0; i<5; i++)
		{
			noise[i] = hps[i].gh + hps[i].ma;
			if(noise[i] < h_min)
				h_min = noise[i];
			if(noise[i] > h_max)
				h_max = noise[i];
			ma_avg += hps[i].ma;
			h_avg += noise[i];
			if(hps[i].have_sand)
				have_sand_count++;
			tree_amount_avg += hps[i].tree_amount;
		}
		ma_avg /= 5.0;
		h_avg /= 5.0;
		tree_amount_avg /= 5.0;

		float steepness = (h_max - h_min)/grid_size;
		
		float light_f = noise[0]+noise[1]-noise[2]-noise[3];
		light_f /= 100;
		if(light_f < -1.0) light_f = -1.0;
		if(light_f > 1.0) light_f = 1.0;
		//light_f += 1.0;
		//light_f /= 2.0;
		
		v2f p1 = p0 + v2f(1,1)*grid_size;
		
		bool ground_is_sand = false;
		bool ground_is_rock = false;
		bool ground_is_mud = false;
		video::SColor c;
		// Detect water
		if(h_avg < WATER_LEVEL*BS && h_max < (WATER_LEVEL+5)*BS)
		{
			//c = video::SColor(255,59,86,146);
			//c = video::SColor(255,82,120,204);
			c = video::SColor(255,74,105,170);

			/*// Set to water level
			for(u32 i=0; i<4; i++)
			{
				if(noise[i] < BS*WATER_LEVEL)
					noise[i] = BS*WATER_LEVEL;
			}*/
			light_f = 0;
		}
		// Steep cliffs
		else if(steepness > 2.0)
		{
			c = video::SColor(255,128,128,128);
			ground_is_rock = true;
		}
		// Basic ground
		else
		{
			if(ma_avg < 2.0*BS)
			{
				c = video::SColor(255,128,128,128);
				ground_is_rock = true;
			}
			else
			{
				if(h_avg <= 2.5*BS && have_sand_count >= 2)
				{
					c = video::SColor(255,210,194,156);
					ground_is_sand = true;
				}
				else
				{
					/*// Trees if there are over 0.01 trees per MapNode
					if(tree_amount_avg > 0.01)
						c = video::SColor(255,50,128,50);
					else
						c = video::SColor(255,107,134,51);*/
					c = video::SColor(255,107,134,51);
					ground_is_mud = true;
				}
			}
		}
		
		// Set to water level
		for(u32 i=0; i<4; i++)
		{
			if(noise[i] < BS*WATER_LEVEL)
				noise[i] = BS*WATER_LEVEL;
		}

		float b = m_brightness + light_f*0.1*m_brightness;
		if(b < 0) b = 0;
		if(b > 2) b = 2;
		
		c = video::SColor(255, b*c.getRed(), b*c.getGreen(), b*c.getBlue());
		
		driver->setMaterial(m_materials[0]);

		video::S3DVertex vertices[4] =
		{
			video::S3DVertex(p0.X,noise[0],p0.Y, 0,0,0, c, 0,1),
			video::S3DVertex(p0.X,noise[1],p1.Y, 0,0,0, c, 1,1),
			video::S3DVertex(p1.X,noise[2],p1.Y, 0,0,0, c, 1,0),
			video::S3DVertex(p1.X,noise[3],p0.Y, 0,0,0, c, 0,0),
		};
		u16 indices[] = {0,1,2,2,3,0};
		driver->drawVertexPrimitiveList(vertices, 4, indices, 2,
				video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);

		// Add some trees if appropriate
		if(tree_amount_avg >= 0.0065 && steepness < 1.4
				&& ground_is_mud == true)
		{
			driver->setMaterial(m_materials[1]);
			
			float b = m_brightness;
			c = video::SColor(255, b*255, b*255, b*255);
			
			{
				video::S3DVertex vertices[4] =
				{
					video::S3DVertex(p0.X,noise[0],p0.Y,
							0,0,0, c, 0,1),
					video::S3DVertex(p0.X,noise[0]+BS*MAP_BLOCKSIZE,p0.Y,
							0,0,0, c, 0,0),
					video::S3DVertex(p1.X,noise[2]+BS*MAP_BLOCKSIZE,p1.Y,
							0,0,0, c, 1,0),
					video::S3DVertex(p1.X,noise[2],p1.Y,
							0,0,0, c, 1,1),
				};
				u16 indices[] = {0,1,2,2,3,0};
				driver->drawVertexPrimitiveList(vertices, 4, indices, 2,
						video::EVT_STANDARD, scene::EPT_TRIANGLES,
						video::EIT_16BIT);
			}
			{
				video::S3DVertex vertices[4] =
				{
					video::S3DVertex(p1.X,noise[3],p0.Y,
							0,0,0, c, 0,1),
					video::S3DVertex(p1.X,noise[3]+BS*MAP_BLOCKSIZE,p0.Y,
							0,0,0, c, 0,0),
					video::S3DVertex(p0.X,noise[1]+BS*MAP_BLOCKSIZE,p1.Y,
							0,0,0, c, 1,0),
					video::S3DVertex(p0.X,noise[1],p1.Y,
							0,0,0, c, 1,1),
				};
				u16 indices[] = {0,1,2,2,3,0};
				driver->drawVertexPrimitiveList(vertices, 4, indices, 2,
						video::EVT_STANDARD, scene::EPT_TRIANGLES,
						video::EIT_16BIT);
			}
		}
	}

	//driver->clearZBuffer();
}