Example #1
0
s16 MapBlock::getGroundLevel(v2s16 p2d)
{
	auto lock = lock_shared_rec();
	if(isDummy())
		return -3;
	try
	{
		s16 y = MAP_BLOCKSIZE-1;
		for(; y>=0; y--)
		{
			MapNode n = getNodeRef(p2d.X, y, p2d.Y);
			if(m_gamedef->ndef()->get(n).walkable)
			{
				if(y == MAP_BLOCKSIZE-1)
					return -2;
				else
					return y;
			}
		}
		return -1;
	}
	catch(InvalidPositionException &e)
	{
		return -3;
	}
}
Example #2
0
void MapBlock::copyTo(VoxelManipulator &dst)
{
	auto lock = lock_shared_rec();
	v3s16 data_size(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE);
	VoxelArea data_area(v3s16(0,0,0), data_size - v3s16(1,1,1));

	// Copy from data to VoxelManipulator
	dst.copyFrom(data, data_area, v3s16(0,0,0),
			getPosRelative(), data_size);
}
Example #3
0
void MapBlock::actuallyUpdateDayNightDiff()
{
	INodeDefManager *nodemgr = m_gamedef->ndef();

	// Running this function un-expires m_day_night_differs
	m_day_night_differs_expired = false;

	if (data == NULL) {
		m_day_night_differs = false;
		return;
	}

	bool differs;

	/*
		Check if any lighting value differs
	*/
	auto lock = lock_shared_rec();
	for (u32 i = 0; i < MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; i++) {
		MapNode &n = data[i];

		differs = !n.isLightDayNightEq(nodemgr);
		if (differs)
			break;
	}

	/*
		If some lighting values differ, check if the whole thing is
		just air. If it is just air, differs = false
	*/
	if (differs) {
		bool only_air = true;
		for (u32 i = 0; i < MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; i++) {
			MapNode &n = data[i];
			if (n.getContent() != CONTENT_AIR) {
				only_air = false;
				break;
			}
		}
		if (only_air)
			differs = false;
	}

	// Set member variable
	m_day_night_differs = differs;
}
Example #4
0
void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
{
	auto lock = lock_shared_rec();
	if(!ser_ver_supported(version))
		throw VersionMismatchException("ERROR: MapBlock format not supported");

	if(data == NULL)
	{
		throw SerializationError("ERROR: Not writing dummy block.");
	}

	FATAL_ERROR_IF(version < SER_FMT_CLIENT_VER_LOWEST, "Serialize version error");

	// First byte
	u8 flags = 0;
	if(is_underground)
		flags |= 0x01;
	if(getDayNightDiff())
		flags |= 0x02;
	if(m_lighting_expired)
		flags |= 0x04;
	if(m_generated == false)
	{
		flags |= 0x08;
		infostream<<" serialize not generated block"<<std::endl;
	}

	writeU8(os, flags);

	/*
		Bulk node data
	*/
	NameIdMapping nimap;
	u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
	if(disk)
	{
		MapNode *tmp_nodes = new MapNode[nodecount];
		for(u32 i=0; i<nodecount; i++)
			tmp_nodes[i] = data[i];
		getBlockNodeIdMapping(&nimap, tmp_nodes, m_gamedef->ndef());

		u8 content_width = 2;
		u8 params_width = 2;
		writeU8(os, content_width);
		writeU8(os, params_width);
		MapNode::serializeBulk(os, version, tmp_nodes, nodecount,
				content_width, params_width, true);
		delete[] tmp_nodes;
	}
	else
	{
		u8 content_width = 2;
		u8 params_width = 2;
		writeU8(os, content_width);
		writeU8(os, params_width);
		MapNode::serializeBulk(os, version, data, nodecount,
				content_width, params_width, true);
	}

	/*
		Node metadata
	*/
	std::ostringstream oss(std::ios_base::binary);
	m_node_metadata.serialize(oss);
	compressZlib(oss.str(), os);

	/*
		Data that goes to disk, but not the network
	*/
	if(disk)
	{
		if(version <= 24){
			// Node timers
			m_node_timers.serialize(os, version);
		}

		// Static objects
		m_static_objects.serialize(os);

		// Timestamp
		writeU32(os, getTimestamp());

		// Write block-specific node definition id mapping
		nimap.serialize(os);

		if(version >= 25){
			// Node timers
			m_node_timers.serialize(os, version);
		}
	}
}
Example #5
0
void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
{
    DSTACK(__FUNCTION_NAME);

    bool is_transparent_pass = pass == scene::ESNRP_TRANSPARENT;

    std::string prefix;
    if(pass == scene::ESNRP_SOLID)
        prefix = "CM: solid: ";
    else
        prefix = "CM: transparent: ";

    //ScopeProfiler sp(g_profiler, "CM::renderMap() " + prefix, SPT_AVG);

    /*
    	Get time for measuring timeout.

    	Measuring time is very useful for long delays when the
    	machine is swapping a lot.
    */
    //int time1 = time(0);

    /*
    	Get animation parameters
    */
    float animation_time = m_client->getAnimationTime();
    int crack = m_client->getCrackLevel();
    u32 daynight_ratio = m_client->getEnv().getDayNightRatio();

    m_camera_mutex.Lock();
    v3f camera_position = m_camera_position;
    f32 camera_fov = m_camera_fov * 1.1;
    m_camera_mutex.Unlock();

    /*
    	Get all blocks and draw all visible ones
    */

    v3s16 cam_pos_nodes = floatToInt(camera_position, BS);

    u32 vertex_count = 0;
    u32 meshbuffer_count = 0;

    // For limiting number of mesh animations per frame
    u32 mesh_animate_count = 0;
    u32 mesh_animate_count_far = 0;

    // Blocks that were drawn and had a mesh
    u32 blocks_drawn = 0;
    // Blocks which had a corresponding meshbuffer for this pass
    u32 blocks_had_pass_meshbuf = 0;
    // Blocks from which stuff was actually drawn
    u32 blocks_without_stuff = 0;

    /*
    	Draw the selected MapBlocks
    */

    {
        //ScopeProfiler sp(g_profiler, prefix+"drawing blocks", SPT_AVG);

        MeshBufListList drawbufs;
        std::vector<MapBlock::mesh_type> used_meshes; //keep shared_ptr
        auto drawlist = m_drawlist.load();
        auto lock = drawlist->lock_shared_rec();
        used_meshes.reserve(drawlist->size());
        //g_profiler->add("CM::renderMap()cnt"+ prefix, drawlist->size());
        for(auto & ir : *drawlist) {
            auto block = ir.second;

            int mesh_step = getFarmeshStep(m_control, getNodeBlockPos(cam_pos_nodes), block->getPos());
            // If the mesh of the block happened to get deleted, ignore it
            auto mapBlockMesh = block->getMesh(mesh_step);
            if (!mapBlockMesh)
                continue;

            float d = 0.0;
            if(isBlockInSight(block->getPos(), camera_position,
                              m_camera_direction, camera_fov,
                              100000*BS, &d) == false)
            {
                continue;
            }

            used_meshes.emplace_back(mapBlockMesh);

            // Mesh animation
            {
                //JMutexAutoLock lock(block->mesh_mutex);

                mapBlockMesh->updateCameraOffset(m_camera_offset);

                // Pretty random but this should work somewhat nicely
                bool faraway = d >= BS*50;
                //bool faraway = d >= m_control.wanted_range * BS;
                if(mapBlockMesh->isAnimationForced() ||
                        !faraway ||
                        mesh_animate_count_far < (m_control.range_all ? 200 : 50))
                {
                    bool animated = mapBlockMesh->animate(
                                        faraway,
                                        animation_time,
                                        crack,
                                        daynight_ratio);
                    if(animated)
                        mesh_animate_count++;
                    if(animated && faraway)
                        mesh_animate_count_far++;
                }
                else
                {
                    mapBlockMesh->decreaseAnimationForceTimer();
                }
            }

            /*
            	Get the meshbuffers of the block
            */
            {
                //JMutexAutoLock lock(block->mesh_mutex);

                auto *mesh = mapBlockMesh->getMesh();
                if (!mesh)
                    continue;

                u32 c = mesh->getMeshBufferCount();
                for(u32 i=0; i<c; i++)
                {
                    scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);

                    buf->getMaterial().setFlag(video::EMF_TRILINEAR_FILTER, m_cache_trilinear_filter);
                    buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, m_cache_bilinear_filter);
                    buf->getMaterial().setFlag(video::EMF_ANISOTROPIC_FILTER, m_cache_anistropic_filter);

                    const video::SMaterial& material = buf->getMaterial();
                    video::IMaterialRenderer* rnd =
                        driver->getMaterialRenderer(material.MaterialType);
                    bool transparent = (rnd && rnd->isTransparent());
                    if(transparent == is_transparent_pass)
                    {
                        if(buf->getVertexCount() == 0)
                            errorstream<<"Block ["<<analyze_block(block)
                                       <<"] contains an empty meshbuf"<<std::endl;
                        drawbufs.add(buf);
                    }
                }
            }
        }

        std::vector<MeshBufList> &lists = drawbufs.lists;

        //int timecheck_counter = 0;
        for(std::vector<MeshBufList>::iterator i = lists.begin();
                i != lists.end(); ++i) {
#if 0
            timecheck_counter++;
            if(timecheck_counter > 50) {
                timecheck_counter = 0;
                int time2 = time(0);
                if(time2 > time1 + 4) {
                    infostream << "ClientMap::renderMap(): "
                               "Rendering takes ages, returning."
                               << std::endl;
                    return;
                }
            }
#endif

            MeshBufList &list = *i;

            driver->setMaterial(list.m);

            for(std::vector<scene::IMeshBuffer*>::iterator j = list.bufs.begin();
                    j != list.bufs.end(); ++j) {
                scene::IMeshBuffer *buf = *j;
                driver->drawMeshBuffer(buf);
                vertex_count += buf->getVertexCount();
                meshbuffer_count++;
            }

        }
    } // ScopeProfiler

    // Log only on solid pass because values are the same
    if(pass == scene::ESNRP_SOLID) {
        g_profiler->avg("CM: animated meshes", mesh_animate_count);
        g_profiler->avg("CM: animated meshes (far)", mesh_animate_count_far);
    }

    g_profiler->avg(prefix+"vertices drawn", vertex_count);
    if(blocks_had_pass_meshbuf != 0)
        g_profiler->avg(prefix+"meshbuffers per block",
                        (float)meshbuffer_count / (float)blocks_had_pass_meshbuf);
    if(blocks_drawn != 0)
        g_profiler->avg(prefix+"empty blocks (frac)",
                        (float)blocks_without_stuff / blocks_drawn);

    g_profiler->avg("CM: PrimitiveDrawn", driver->getPrimitiveCountDrawn());

    /*infostream<<"renderMap(): is_transparent_pass="******", rendered "<<vertex_count<<" vertices."<<std::endl;*/
}
Example #6
0
std::string PlayerSAO::getClientInitializationData(u16 protocol_version)
{
	std::ostringstream os(std::ios::binary);

	if (!m_player)
		return "";
	if(protocol_version >= 15)
	{
		writeU8(os, 1); // version
		os<<serializeString(m_player->getName()); // name
		writeU8(os, 1); // is_player
		writeS16(os, getId()); //id
		writeV3F1000(os, m_base_position + v3f(0,BS*1,0));
		writeF1000(os, m_yaw);
		writeS16(os, getHP());

		auto lock = lock_shared_rec();

		std::ostringstream msg_os(std::ios::binary);
		msg_os << serializeLongString(getPropertyPacket()); // message 1
		msg_os << serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
		msg_os << serializeLongString(gob_cmd_update_animation(
			m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop)); // 3
		for (UNORDERED_MAP<std::string, core::vector2d<v3f> >::const_iterator
				ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii) {
			msg_os << serializeLongString(gob_cmd_update_bone_position((*ii).first,
				(*ii).second.X, (*ii).second.Y)); // m_bone_position.size
		}
		msg_os << serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id,
			m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4
		msg_os << serializeLongString(gob_cmd_update_physics_override(m_physics_override_speed,
				m_physics_override_jump, m_physics_override_gravity, m_physics_override_sneak,
				m_physics_override_sneak_glitch)); // 5
		// (GENERIC_CMD_UPDATE_NAMETAG_ATTRIBUTES) : Deprecated, for backwards compatibility only.
		msg_os << serializeLongString(gob_cmd_update_nametag_attributes(m_prop.nametag_color)); // 6
		int message_count = 6 + m_bone_position.size();
		for (UNORDERED_SET<int>::const_iterator ii = m_attachment_child_ids.begin();
				ii != m_attachment_child_ids.end(); ++ii) {
			if (ServerActiveObject *obj = m_env->getActiveObject(*ii)) {
				message_count++;
				msg_os << serializeLongString(gob_cmd_update_infant(*ii, obj->getSendType(),
					obj->getClientInitializationData(protocol_version)));
			}
		}

		writeU8(os, message_count);
		os.write(msg_os.str().c_str(), msg_os.str().size());
	}
	else
	{
		writeU8(os, 0); // version
		os<<serializeString(m_player->getName()); // name
		writeU8(os, 1); // is_player
		writeV3F1000(os, m_base_position + v3f(0,BS*1,0));
		writeF1000(os, m_yaw);
		writeS16(os, getHP());
		writeU8(os, 2); // number of messages stuffed in here
		os<<serializeLongString(getPropertyPacket()); // message 1
		os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
	}

	// return result
	return os.str();
}
Example #7
0
std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version)
{
	std::ostringstream os(std::ios::binary);

	auto lock = lock_shared_rec();
	try {

	if(protocol_version >= 14)
	{
		writeU8(os, 1); // version
		os<<serializeString(""); // name
		writeU8(os, 0); // is_player
		writeS16(os, getId()); //id
		writeV3F1000(os, getBasePosition());
		writeF1000(os, m_yaw);
		writeS16(os, m_hp);

		std::ostringstream msg_os(std::ios::binary);
		msg_os << serializeLongString(getPropertyPacket()); // message 1
		msg_os << serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
		msg_os << serializeLongString(gob_cmd_update_animation(
			m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop)); // 3
		for (UNORDERED_MAP<std::string, core::vector2d<v3f> >::const_iterator
				ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii) {
			msg_os << serializeLongString(gob_cmd_update_bone_position((*ii).first,
					(*ii).second.X, (*ii).second.Y)); // m_bone_position.size
		}
		msg_os << serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id,
			m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4
		int message_count = 4 + m_bone_position.size();
		for (UNORDERED_SET<int>::const_iterator ii = m_attachment_child_ids.begin();
				(ii != m_attachment_child_ids.end()); ++ii) {
			if (ServerActiveObject *obj = m_env->getActiveObject(*ii)) {
				message_count++;
				msg_os << serializeLongString(gob_cmd_update_infant(*ii, obj->getSendType(),
					obj->getClientInitializationData(protocol_version)));
			}
		}

		writeU8(os, message_count);
		os.write(msg_os.str().c_str(), msg_os.str().size());
	}
	else
	{
		writeU8(os, 0); // version
		os<<serializeString(""); // name
		writeU8(os, 0); // is_player
		writeV3F1000(os, getBasePosition());
		writeF1000(os, m_yaw);
		writeS16(os, m_hp);
		writeU8(os, 2); // number of messages stuffed in here
		os<<serializeLongString(getPropertyPacket()); // message 1
		os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
	}

	} catch (std::exception &e){
		errorstream << "Catn serialize object id="<<getId()<< " pos="<< getBasePosition() << std::endl;
		return "";
	}

	// return result
	return os.str();
}