+ if (s.size() != nodecount)
+ throw SerializationError(std::string(FUNCTION_NAME)
+ + ": not enough input data");
+ for (u32 i = 0; i < s.size(); i++) {
+ databuf_nodelist[i*ser_length + 2] = s[i];
+ }
+ }
+ } else { // All other versions (10 to 21)
+ u8 flags;
+ is.read((char*)&flags, 1);
+ is_underground = (flags & 0x01) ? true : false;
+ m_day_night_differs = (flags & 0x02) ? true : false;
+ if(version >= 18)
+ m_generated = (flags & 0x08) ? false : true;
+
+ // Uncompress data
+ std::ostringstream os(std::ios_base::binary);
+ decompress(is, os, version);
+ std::string s = os.str();
+ if (s.size() != nodecount * 3)
+ throw SerializationError(std::string(FUNCTION_NAME)
+ + ": decompress resulted in size other than nodecount*3");
+
+ // deserialize nodes from buffer
+ for (u32 i = 0; i < nodecount; i++) {
+ databuf_nodelist[i*ser_length] = s[i];
+ databuf_nodelist[i*ser_length + 1] = s[i+nodecount];
+ databuf_nodelist[i*ser_length + 2] = s[i+nodecount*2];
+ }
+
+ /*
+ NodeMetadata
+ */
+ if (version >= 14) {
+ // Ignore errors
+ try {
+ if (version <= 15) {
+ std::string data = deSerializeString(is);
+ std::istringstream iss(data, std::ios_base::binary);
+ content_nodemeta_deserialize_legacy(iss,
+ &m_node_metadata, &m_node_timers,
+ m_gamedef->idef());
+ } else {
+ //std::string data = deSerializeLongString(is);
+ std::ostringstream oss(std::ios_base::binary);
+ decompressZlib(is, oss);
+ std::istringstream iss(oss.str(), std::ios_base::binary);
+ content_nodemeta_deserialize_legacy(iss,
+ &m_node_metadata, &m_node_timers,
+ m_gamedef->idef());
+ }
+ } catch(SerializationError &e) {
+ warningstream<<"MapBlock::deSerialize(): Ignoring an error"
+ <<" while deserializing node metadata"<<std::endl;
+ }
+ }
+ }
+
+ // Deserialize node data
+ for (u32 i = 0; i < nodecount; i++) {
+ data[i].deSerialize(&databuf_nodelist[i * ser_length], version);
+ }
+
+ if (disk) {
+ /*
+ Versions up from 9 have block objects. (DEPRECATED)
+ */
+ if (version >= 9) {
+ u16 count = readU16(is);
+ // Not supported and length not known if count is not 0
+ if(count != 0){
+ warningstream<<"MapBlock::deSerialize_pre22(): "
+ <<"Ignoring stuff coming at and after MBOs"<<std::endl;
+ return;
+ }
+ }
+
+ /*
+ Versions up from 15 have static objects.
+ */
+ if (version >= 15)
+ m_static_objects.deSerialize(is);
+
+ // Timestamp
+ if (version >= 17) {
+ setTimestamp(readU32(is));
+ m_disk_timestamp = m_timestamp;
+ } else {
+ setTimestamp(BLOCK_TIMESTAMP_UNDEFINED);
+ }
+
+ // Dynamically re-set ids based on node names
+ NameIdMapping nimap;
+ // If supported, read node definition id mapping
+ if (version >= 21) {
+ nimap.deSerialize(is);
+ // Else set the legacy mapping
+ } else {
+ content_mapnode_get_name_id_mapping(&nimap);
+ }
+ correctBlockNodeIds(&nimap, data, m_gamedef);
+ }
+
+
+ // Legacy data changes
+ // This code has to convert from pre-22 to post-22 format.
+ INodeDefManager *nodedef = m_gamedef->ndef();
+ for(u32 i=0; i<nodecount; i++)
+ {
+ const ContentFeatures &f = nodedef->get(data[i].getContent());
+ // Mineral
+ if(nodedef->getId("default:stone") == data[i].getContent()
+ && data[i].getParam1() == 1)
+ {
+ data[i].setContent(nodedef->getId("default:stone_with_coal"));
+ data[i].setParam1(0);
+ }
+ else if(nodedef->getId("default:stone") == data[i].getContent()
+ && data[i].getParam1() == 2)
+ {
+ data[i].setContent(nodedef->getId("default:stone_with_iron"));
+ data[i].setParam1(0);
+ }
+ // facedir_simple
+ if(f.legacy_facedir_simple)
+ {
+ data[i].setParam2(data[i].getParam1());
+ data[i].setParam1(0);
+ }
+ // wall_mounted
+ if(f.legacy_wallmounted)
+ {
+ u8 wallmounted_new_to_old[8] = {0x04, 0x08, 0x01, 0x02, 0x10, 0x20, 0, 0};
+ u8 dir_old_format = data[i].getParam2();
+ u8 dir_new_format = 0;
+ for(u8 j=0; j<8; j++)