void MapBlock::serialize(std::ostream &os, u8 version, bool disk) { if(!ser_ver_supported(version)) throw VersionMismatchException("ERROR: MapBlock format not supported"); if(data == NULL) { throw SerializationError("ERROR: Not writing dummy block."); } // Can't do this anymore; we have 16-bit dynamically allocated node IDs // in memory; conversion just won't work in this direction. if(version < 24) throw SerializationError("MapBlock::serialize: serialization to " "version < 24 not possible"); // 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; 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) { // Node timers m_node_timers.serialize(os); // Static objects m_static_objects.serialize(os); // Timestamp writeU32(os, getTimestamp()); // Write block-specific node definition id mapping nimap.serialize(os); } }
void MapBlock::serialize_pre22(std::ostream &os, u8 version, bool disk) { u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; MapNode *tmp_data = new MapNode[nodecount]; // Legacy data changes // This code has to change from post-22 to pre-22 format. INodeDefManager *nodedef = m_gamedef->ndef(); for(u32 i=0; i<nodecount; i++) { const ContentFeatures &f = nodedef->get(tmp_data[i].getContent()); // Mineral if(nodedef->getId("default:stone_with_coal") == tmp_data[i].getContent()) { tmp_data[i].setContent(nodedef->getId("default:stone")); tmp_data[i].setParam1(1); // MINERAL_COAL } else if(nodedef->getId("default:stone_with_iron") == tmp_data[i].getContent()) { tmp_data[i].setContent(nodedef->getId("default:stone")); tmp_data[i].setParam1(2); // MINERAL_IRON } // facedir_simple if(f.legacy_facedir_simple) { tmp_data[i].setParam1(tmp_data[i].getParam2()); tmp_data[i].setParam2(0); } // wall_mounted if(f.legacy_wallmounted) { u8 wallmounted_new_to_old[8] = {0x04, 0x08, 0x01, 0x02, 0x10, 0x20, 0, 0}; u8 dir_new_format = tmp_data[i].getParam2() & 7; // lowest 3 bits u8 dir_old_format = wallmounted_new_to_old[dir_new_format]; tmp_data[i].setParam2(dir_old_format); } } // Serialize nodes u32 ser_length = MapNode::serializedLength(version); SharedBuffer<u8> databuf_nodelist(nodecount * ser_length); for(u32 i=0; i<nodecount; i++) { tmp_data[i].serialize(&databuf_nodelist[i*ser_length], version); } delete[] tmp_data; // These have no compression if(version <= 3 || version == 5 || version == 6) { writeU8(os, is_underground); os.write((char*)*databuf_nodelist, databuf_nodelist.getSize()); } else if(version <= 10) { /* With compression. Compress the materials and the params separately. */ // First byte writeU8(os, is_underground); // Get and compress materials SharedBuffer<u8> materialdata(nodecount); for(u32 i=0; i<nodecount; i++) { materialdata[i] = databuf_nodelist[i*ser_length]; } compress(materialdata, os, version); // Get and compress lights SharedBuffer<u8> lightdata(nodecount); for(u32 i=0; i<nodecount; i++) { lightdata[i] = databuf_nodelist[i*ser_length+1]; } compress(lightdata, os, version); if(version >= 10) { // Get and compress param2 SharedBuffer<u8> param2data(nodecount); for(u32 i=0; i<nodecount; i++) { param2data[i] = databuf_nodelist[i*ser_length+2]; } compress(param2data, os, version); } } // All other versions (newest) else { // First byte u8 flags = 0; if(is_underground) flags |= 0x01; if(getDayNightDiff()) flags |= 0x02; if(m_lighting_expired) flags |= 0x04; if(version >= 18) { if(m_generated == false) flags |= 0x08; } writeU8(os, flags); /* Get data */ // Create buffer with different parameters sorted SharedBuffer<u8> databuf(nodecount*3); for(u32 i=0; i<nodecount; i++) { databuf[i] = databuf_nodelist[i*ser_length]; databuf[i+nodecount] = databuf_nodelist[i*ser_length+1]; databuf[i+nodecount*2] = databuf_nodelist[i*ser_length+2]; } /* Compress data to output stream */ compress(databuf, os, version); /* NodeMetadata */ if(version >= 14) { if(version <= 15) { try{ std::ostringstream oss(std::ios_base::binary); m_node_metadata->serialize(oss); os<<serializeString(oss.str()); } // This will happen if the string is longer than 65535 catch(SerializationError &e) { // Use an empty string os<<serializeString(""); } } else { std::ostringstream oss(std::ios_base::binary); m_node_metadata->serialize(oss); compressZlib(oss.str(), os); //os<<serializeLongString(oss.str()); } } } if(disk) { // Versions up from 9 have block objects. (DEPRECATED) if(version >= 9) { // count=0 writeU16(os, 0); } // Versions up from 15 have static objects. if(version >= 15) { m_static_objects.serialize(os); } // Timestamp if(version >= 17) { writeU32(os, getTimestamp()); } // Scan and write node definition id mapping if(version >= 21) { NameIdMapping nimap; getBlockNodeIdMapping_pre22(&nimap, data, m_gamedef->ndef()); nimap.serialize(os); } } }
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); } } }
void MapBlock::serialize(std::ostream &os, u8 version, bool disk) { if(!ser_ver_supported(version)) throw VersionMismatchException("ERROR: MapBlock format not supported"); if(data == NULL) { throw SerializationError("ERROR: Not writing dummy block."); } if(version <= 21) { serialize_pre22(os, version, disk); return; } // 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; 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 = 1; /*u8 content_width = (nimap.size() <= 255) ? 1 : 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 = 1; /*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) { // Static objects m_static_objects.serialize(os); // Timestamp writeU32(os, getTimestamp()); // Write block-specific node definition id mapping nimap.serialize(os); } }