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); } }
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); }
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); } }
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); } }
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()); } }
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; }
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()); }
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); }
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); }
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++; } } }