Пример #1
0
	void serialize(std::ostream &os, u16 protocol_version)
	{
		writeU8(os, 0); // version
		u16 count = m_item_definitions.size();
		writeU16(os, count);

		for (std::map<std::string, ItemDefinition *>::const_iterator
				it = m_item_definitions.begin();
				it != m_item_definitions.end(); ++it) {
			ItemDefinition *def = it->second;
			// Serialize ItemDefinition and write wrapped in a string
			std::ostringstream tmp_os(std::ios::binary);
			def->serialize(tmp_os, protocol_version);
			os << serializeString(tmp_os.str());
		}

		writeU16(os, m_aliases.size());

		for (StringMap::const_iterator
				it = m_aliases.begin();
				it != m_aliases.end(); ++it) {
			os << serializeString(it->first);
			os << serializeString(it->second);
		}
	}
Пример #2
0
void Client::interact(u8 action, const PointedThing& pointed)
{
	if(m_state != LC_Ready) {
		errorstream << "Client::interact() "
				"Canceled (not connected)"
				<< std::endl;
		return;
	}

	/*
		[0] u16 command
		[2] u8 action
		[3] u16 item
		[5] u32 length of the next item
		[9] serialized PointedThing
		actions:
		0: start digging (from undersurface) or use
		1: stop digging (all parameters ignored)
		2: digging completed
		3: place block or item (to abovesurface)
		4: use item
	*/

	NetworkPacket pkt(TOSERVER_INTERACT, 1 + 2 + 0);

	pkt << action;
	pkt << (u16)getPlayerItem();

	std::ostringstream tmp_os(std::ios::binary);
	pointed.serialize(tmp_os);

	pkt.putLongString(tmp_os.str());

	Send(&pkt);
}
Пример #3
0
void ItemDefinition::serialize(std::ostream &os) const
{
	writeU8(os, 1); // version
	writeU8(os, type);
	os<<serializeString(name);
	os<<serializeString(description);
	os<<serializeString(inventory_image);
	os<<serializeString(wield_image);
	writeV3F1000(os, wield_scale);
	writeS16(os, stack_max);
	writeU8(os, usable);
	writeU8(os, liquids_pointable);
	writeU8(os, eatable);
	std::string tool_capabilities_s = "";
	if(tool_capabilities){
		std::ostringstream tmp_os(std::ios::binary);
		tool_capabilities->serialize(tmp_os);
		tool_capabilities_s = tmp_os.str();
	}
	os<<serializeString(tool_capabilities_s);
	writeU16(os, groups.size());
	for(std::map<std::string, int>::const_iterator
			i = groups.begin(); i != groups.end(); i++){
		os<<serializeString(i->first);
		writeS16(os, i->second);
	}
}
Пример #4
0
void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const
{
    if(protocol_version <= 17)
        writeU8(os, 1); // version
    else
        writeU8(os, 2); // version
    writeU8(os, type);
    os<<serializeString(name);
    os<<serializeString(description);
    os<<serializeString(inventory_image);
    os<<serializeString(wield_image);
    writeV3F1000(os, wield_scale);
    writeS16(os, stack_max);
    writeU8(os, usable);
    writeU8(os, liquids_pointable);
    std::string tool_capabilities_s = "";
    if(tool_capabilities) {
        std::ostringstream tmp_os(std::ios::binary);
        tool_capabilities->serialize(tmp_os, protocol_version);
        tool_capabilities_s = tmp_os.str();
    }
    os<<serializeString(tool_capabilities_s);
    writeU16(os, groups.size());
    for(std::map<std::string, int>::const_iterator
            i = groups.begin(); i != groups.end(); i++) {
        os<<serializeString(i->first);
        writeS16(os, i->second);
    }
    os<<serializeString(node_placement_prediction);
    if(protocol_version > 17) {
        //serializeSimpleSoundSpec(sound_place, os);
        os<<serializeString(sound_place.name);
        writeF1000(os, sound_place.gain);
    }
}
Пример #5
0
	virtual void serialize(std::ostream &os) const
	{
		writeU8(os, 0); // version
		u16 count = m_craft_definitions.size();
		writeU16(os, count);
		for(std::vector<CraftDefinition*>::const_iterator
				i = m_craft_definitions.begin();
				i != m_craft_definitions.end(); i++){
			CraftDefinition *def = *i;
			// Serialize wrapped in a string
			std::ostringstream tmp_os(std::ios::binary);
			def->serialize(tmp_os);
			os<<serializeString(tmp_os.str());
		}
	}
Пример #6
0
bool FileCache::load_sha1(const std::string &sha1_raw, std::ostream &os)
{
	std::ostringstream tmp_os(std::ios_base::binary);
	if(!load(hex_encode(sha1_raw), tmp_os))
		return false;
	SHA1 sha1;
	sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
	unsigned char *digest = sha1.getDigest();
	std::string sha1_real_raw((char*)digest, 20);
	free(digest);
	if(sha1_real_raw != sha1_raw){
		verbosestream<<"FileCache["<<m_dir<<"]: filename "<<sha1_real_raw
				<<" mismatches actual checksum"<<std::endl;
		return false;
	}
	os<<tmp_os.str();
	return true;
}
Пример #7
0
	void serialize(std::ostream &os)
	{
		u16 count = 0;
		std::ostringstream tmp_os(std::ios::binary);
		for(u16 i=0; i<=MAX_CONTENT; i++)
		{
			if(i == CONTENT_IGNORE || i == CONTENT_AIR)
				continue;
			ContentFeatures *f = &m_content_features[i];
			if(f->name == "")
				continue;
			writeU16(tmp_os, i);
			f->serialize(tmp_os);
			count++;
		}
		writeU16(os, count);
		os<<serializeLongString(tmp_os.str());
	}
Пример #8
0
void Client::interact(u8 action, const PointedThing& pointed)
{
	if(m_state != LC_Ready) {
		errorstream << "Client::interact() "
				"Canceled (not connected)"
				<< std::endl;
		return;
	}

	LocalPlayer *myplayer = m_env.getLocalPlayer();
	if (myplayer == NULL)
		return;

	/*
		[0] u16 command
		[2] u8 action
		[3] u16 item
		[5] u32 length of the next item (plen)
		[9] serialized PointedThing
		[9 + plen] player position information
		actions:
		0: start digging (from undersurface) or use
		1: stop digging (all parameters ignored)
		2: digging completed
		3: place block or item (to abovesurface)
		4: use item
		5: perform secondary action of item
	*/

	NetworkPacket pkt(TOSERVER_INTERACT, 1 + 2 + 0);

	pkt << action;
	pkt << (u16)getPlayerItem();

	std::ostringstream tmp_os(std::ios::binary);
	pointed.serialize(tmp_os);

	pkt.putLongString(tmp_os.str());

	writePlayerPos(myplayer, &m_env.getClientMap(), &pkt);

	Send(&pkt);
}
Пример #9
0
void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const
{
	// protocol_version >= 36
	u8 version = 5;
	writeU8(os, version);
	writeU8(os, type);
	os << serializeString(name);
	os << serializeString(description);
	os << serializeString(inventory_image);
	os << serializeString(wield_image);
	writeV3F1000(os, wield_scale);
	writeS16(os, stack_max);
	writeU8(os, usable);
	writeU8(os, liquids_pointable);
	std::string tool_capabilities_s;
	if(tool_capabilities){
		std::ostringstream tmp_os(std::ios::binary);
		tool_capabilities->serialize(tmp_os, protocol_version);
		tool_capabilities_s = tmp_os.str();
	}
	os << serializeString(tool_capabilities_s);
	writeU16(os, groups.size());
	for (const auto &group : groups) {
		os << serializeString(group.first);
		writeS16(os, group.second);
	}
	os << serializeString(node_placement_prediction);
	os << serializeString(sound_place.name);
	writeF1000(os, sound_place.gain);
	writeF1000(os, range);
	os << serializeString(sound_place_failed.name);
	writeF1000(os, sound_place_failed.gain);
	os << serializeString(palette_image);
	writeARGB8(os, color);

	writeF1000(os, sound_place.pitch);
	writeF1000(os, sound_place_failed.pitch);
	os << serializeString(inventory_overlay);
	os << serializeString(wield_overlay);
}
Пример #10
0
void ClientMediaDownloader::initialStep(Client *client)
{
	// Check media cache
	m_uncached_count = m_files.size();
	for (std::map<std::string, FileStatus*>::iterator
			it = m_files.begin();
			it != m_files.end(); ++it) {
		std::string name = it->first;
		FileStatus *filestatus = it->second;
		const std::string &sha1 = filestatus->sha1;

		std::ostringstream tmp_os(std::ios_base::binary);
		bool found_in_cache = m_media_cache.load(hex_encode(sha1), tmp_os);

		// If found in cache, try to load it from there
		if (found_in_cache) {
			bool success = checkAndLoad(name, sha1,
					tmp_os.str(), true, client);
			if (success) {
				filestatus->received = true;
				m_uncached_count--;
			}
		}
	}

	assert(m_uncached_received_count == 0);

	// Create the media cache dir if we are likely to write to it
	if (m_uncached_count != 0) {
		bool did = fs::CreateAllDirs(getMediaCacheDir());
		if (!did) {
			errorstream << "Client: "
				<< "Could not create media cache directory: "
				<< getMediaCacheDir()
				<< std::endl;
		}
	}

	// If we found all files in the cache, report this fact to the server.
	// If the server reported no remote servers, immediately start
	// conventional transfers. Note: if cURL support is not compiled in,
	// m_remotes is always empty, so "!USE_CURL" is redundant but may
	// reduce the size of the compiled code
	if (!USE_CURL || m_uncached_count == 0 || m_remotes.empty()) {
		startConventionalTransfers(client);
	}
	else {
		// Otherwise start off by requesting each server's sha1 set

		// This is the first time we use httpfetch, so alloc a caller ID
		m_httpfetch_caller = httpfetch_caller_alloc();
		m_httpfetch_timeout = g_settings->getS32("curl_timeout");

		// Set the active fetch limit to curl_parallel_limit or 84,
		// whichever is greater. This gives us some leeway so that
		// inefficiencies in communicating with the httpfetch thread
		// don't slow down fetches too much. (We still want some limit
		// so that when the first remote server returns its hash set,
		// not all files are requested from that server immediately.)
		// One such inefficiency is that ClientMediaDownloader::step()
		// is only called a couple times per second, while httpfetch
		// might return responses much faster than that.
		// Note that httpfetch strictly enforces curl_parallel_limit
		// but at no inter-thread communication cost. This however
		// doesn't help with the aforementioned inefficiencies.
		// The signifance of 84 is that it is 2*6*9 in base 13.
		m_httpfetch_active_limit = g_settings->getS32("curl_parallel_limit");
		m_httpfetch_active_limit = MYMAX(m_httpfetch_active_limit, 84);

		// Write a list of hashes that we need. This will be POSTed
		// to the server using Content-Type: application/octet-stream
		std::string required_hash_set = serializeRequiredHashSet();

		// minor fixme: this loop ignores m_httpfetch_active_limit

		// another minor fixme, unlikely to matter in normal usage:
		// these index.mth fetches do (however) count against
		// m_httpfetch_active_limit when starting actual media file
		// requests, so if there are lots of remote servers that are
		// not responding, those will stall new media file transfers.

		for (u32 i = 0; i < m_remotes.size(); ++i) {
			assert(m_httpfetch_next_id == i);

			RemoteServerStatus *remote = m_remotes[i];
			actionstream << "Client: Contacting remote server \""
				<< remote->baseurl << "\"" << std::endl;

			HTTPFetchRequest fetchrequest;
			fetchrequest.url =
				remote->baseurl + MTHASHSET_FILE_NAME;
			fetchrequest.caller = m_httpfetch_caller;
			fetchrequest.request_id = m_httpfetch_next_id; // == i
			fetchrequest.timeout = m_httpfetch_timeout;
			fetchrequest.connect_timeout = m_httpfetch_timeout;
			fetchrequest.post_data = required_hash_set;
			fetchrequest.extra_headers.push_back(
				"Content-Type: application/octet-stream");
			httpfetch_async(fetchrequest);

			m_httpfetch_active++;
			m_httpfetch_next_id++;
			m_outstanding_hash_sets++;
		}
	}
}