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) { 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::deSerialize(std::istream &is, u8 version, bool disk) { if(!ser_ver_supported(version)) throw VersionMismatchException("ERROR: MapBlock format not supported"); TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())<<std::endl); m_day_night_differs_expired = false; if(version <= 21) { deSerialize_pre22(is, version, disk); return; } u8 flags = readU8(is); is_underground = (flags & 0x01) ? true : false; m_day_night_differs = (flags & 0x02) ? true : false; m_lighting_expired = (flags & 0x04) ? true : false; m_generated = (flags & 0x08) ? false : true; /* Bulk node data */ TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos()) <<": Bulk node data"<<std::endl); u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; u8 content_width = readU8(is); u8 params_width = readU8(is); if(content_width != 1 && content_width != 2) throw SerializationError("MapBlock::deSerialize(): invalid content_width"); if(params_width != 2) throw SerializationError("MapBlock::deSerialize(): invalid params_width"); MapNode::deSerializeBulk(is, version, data, nodecount, content_width, params_width, true); /* NodeMetadata */ TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos()) <<": Node metadata"<<std::endl); // Ignore errors try { std::ostringstream oss(std::ios_base::binary); decompressZlib(is, oss); std::istringstream iss(oss.str(), std::ios_base::binary); if(version >= 23) m_node_metadata.deSerialize(iss, m_gamedef); else content_nodemeta_deserialize_legacy(iss, &m_node_metadata, &m_node_timers, m_gamedef); } catch(SerializationError &e) { errorstream<<"WARNING: MapBlock::deSerialize(): Ignoring an error" <<" while deserializing node metadata at (" <<PP(getPos())<<": "<<e.what()<<std::endl; } /* Data that is only on disk */ if(disk) { // Node timers if(version == 23) { // Read unused zero readU8(is); } if(version == 24) { TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos()) <<": Node timers (ver==24)"<<std::endl); m_node_timers.deSerialize(is, version); } // Static objects TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos()) <<": Static objects"<<std::endl); m_static_objects.deSerialize(is); // Timestamp TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos()) <<": Timestamp"<<std::endl); setTimestamp(readU32(is)); m_disk_timestamp = m_timestamp; // Dynamically re-set ids based on node names TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos()) <<": NameIdMapping"<<std::endl); NameIdMapping nimap; nimap.deSerialize(is); correctBlockNodeIds(&nimap, data, m_gamedef); if(version >= 25) { TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos()) <<": Node timers (ver>=25)"<<std::endl); m_node_timers.deSerialize(is, version); }
void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk) { u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; // Initialize default flags is_underground = false; m_day_night_differs = false; m_lighting_expired = false; m_generated = true; // Make a temporary buffer u32 ser_length = MapNode::serializedLength(version); SharedBuffer<u8> databuf_nodelist(nodecount * ser_length); // These have no compression if(version <= 3 || version == 5 || version == 6) { char tmp; is.read(&tmp, 1); if(is.gcount() != 1) throw SerializationError ("MapBlock::deSerialize: no enough input data"); is_underground = tmp; is.read((char*)*databuf_nodelist, nodecount * ser_length); if(is.gcount() != nodecount * ser_length) throw SerializationError ("MapBlock::deSerialize: no enough input data"); } else if(version <= 10) { u8 t8; is.read((char*)&t8, 1); is_underground = t8; { // Uncompress and set material data std::ostringstream os(std::ios_base::binary); decompress(is, os, version); std::string s = os.str(); if(s.size() != nodecount) throw SerializationError ("MapBlock::deSerialize: invalid format"); for(u32 i=0; i<s.size(); i++) { databuf_nodelist[i*ser_length] = s[i]; } } { // Uncompress and set param data std::ostringstream os(std::ios_base::binary); decompress(is, os, version); std::string s = os.str(); if(s.size() != nodecount) throw SerializationError ("MapBlock::deSerialize: invalid format"); for(u32 i=0; i<s.size(); i++) { databuf_nodelist[i*ser_length + 1] = s[i]; } } if(version >= 10) { // Uncompress and set param2 data std::ostringstream os(std::ios_base::binary); decompress(is, os, version); std::string s = os.str(); if(s.size() != nodecount) throw SerializationError ("MapBlock::deSerialize: invalid format"); for(u32 i=0; i<s.size(); i++) { databuf_nodelist[i*ser_length + 2] = s[i]; } } } // All other versions (newest) else { u8 flags; is.read((char*)&flags, 1); is_underground = (flags & 0x01) ? true : false; m_day_night_differs = (flags & 0x02) ? true : false; m_lighting_expired = (flags & 0x04) ? 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 ("MapBlock::deSerialize: 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); m_node_metadata->deSerialize(iss, m_gamedef); } 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); m_node_metadata->deSerialize(iss, m_gamedef); } } catch(SerializationError &e) { errorstream<<"WARNING: 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){ errorstream<<"WARNING: 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++) { if((dir_old_format & wallmounted_new_to_old[j]) != 0) { dir_new_format = j; break; } } data[i].setParam2(dir_new_format); } } }
void RollbackAction::fromStream(std::istream &is) throw(SerializationError) { int c = is.get(); if(c != '['){ is.putback(c); throw SerializationError("RollbackAction: starting [ not found"); } std::string id; std::getline(is, id, ' '); if(id == "set_node") { c = is.get(); if(c != '('){ is.putback(c); throw SerializationError("RollbackAction: starting ( not found"); } // Position std::string px_raw; std::string py_raw; std::string pz_raw; std::getline(is, px_raw, ','); std::getline(is, py_raw, ','); std::getline(is, pz_raw, ')'); c = is.get(); if(c != ' '){ is.putback(c); throw SerializationError("RollbackAction: after-p ' ' not found"); } v3s16 loaded_p(stoi(px_raw), stoi(py_raw), stoi(pz_raw)); // Old node std::string old_name; try{ old_name = deSerializeJsonString(is); }catch(SerializationError &e){ errorstream<<"Serialization error in RollbackAction::fromStream(): " <<"old_name: "<<e.what()<<std::endl; throw e; } c = is.get(); if(c != ' '){ is.putback(c); throw SerializationError("RollbackAction: after-old_name ' ' not found"); } std::string old_p1_raw; std::string old_p2_raw; std::getline(is, old_p1_raw, ' '); std::getline(is, old_p2_raw, ' '); int old_p1 = stoi(old_p1_raw); int old_p2 = stoi(old_p2_raw); std::string old_meta; try{ old_meta = deSerializeJsonString(is); }catch(SerializationError &e){ errorstream<<"Serialization error in RollbackAction::fromStream(): " <<"old_meta: "<<e.what()<<std::endl; throw e; } c = is.get(); if(c != ' '){ is.putback(c); throw SerializationError("RollbackAction: after-old_meta ' ' not found"); } // New node std::string new_name; try{ new_name = deSerializeJsonString(is); }catch(SerializationError &e){ errorstream<<"Serialization error in RollbackAction::fromStream(): " <<"new_name: "<<e.what()<<std::endl; throw e; } c = is.get(); if(c != ' '){ is.putback(c); throw SerializationError("RollbackAction: after-new_name ' ' not found"); } std::string new_p1_raw; std::string new_p2_raw; std::getline(is, new_p1_raw, ' '); std::getline(is, new_p2_raw, ' '); int new_p1 = stoi(new_p1_raw); int new_p2 = stoi(new_p2_raw); std::string new_meta; try{ new_meta = deSerializeJsonString(is); }catch(SerializationError &e){ errorstream<<"Serialization error in RollbackAction::fromStream(): " <<"new_meta: "<<e.what()<<std::endl; throw e; } c = is.get(); if(c != ']'){ is.putback(c); throw SerializationError("RollbackAction: after-new_meta ] not found"); } // Set values type = TYPE_SET_NODE; p = loaded_p; n_old.name = old_name; n_old.param1 = old_p1; n_old.param2 = old_p2; n_old.meta = old_meta; n_new.name = new_name; n_new.param1 = new_p1; n_new.param2 = new_p2; n_new.meta = new_meta; } else if(id == "modify_inventory_stack") { // Location std::string location; try{ location = deSerializeJsonString(is); }catch(SerializationError &e){ errorstream<<"Serialization error in RollbackAction::fromStream(): " <<"location: "<<e.what()<<std::endl; throw e; } c = is.get(); if(c != ' '){ is.putback(c); throw SerializationError("RollbackAction: after-loc ' ' not found"); } // List std::string listname; try{ listname = deSerializeJsonString(is); }catch(SerializationError &e){ errorstream<<"Serialization error in RollbackAction::fromStream(): " <<"listname: "<<e.what()<<std::endl; throw e; } c = is.get(); if(c != ' '){ is.putback(c); throw SerializationError("RollbackAction: after-list ' ' not found"); } // Index std::string index_raw; std::getline(is, index_raw, ' '); // add/remove std::string addremove; std::getline(is, addremove, ' '); if(addremove != "add" && addremove != "remove"){ throw SerializationError("RollbackAction: addremove is not add or remove"); } // Itemstring std::string stack; try{ stack = deSerializeJsonString(is); }catch(SerializationError &e){ errorstream<<"Serialization error in RollbackAction::fromStream(): " <<"stack: "<<e.what()<<std::endl; throw e; } // Set values type = TYPE_MODIFY_INVENTORY_STACK; inventory_location = location; inventory_list = listname; inventory_index = stoi(index_raw); inventory_add = (addremove == "add"); inventory_stack = stack; } else { throw SerializationError("RollbackAction: Unknown id"); } }
void MapBlockObjectList::update(std::istream &is, u8 version, scene::ISceneManager *smgr, u32 daynight_ratio) { JMutexAutoLock lock(m_mutex); /* Collect all existing ids to a set. As things are updated, they are removed from this. All remaining ones are deleted. */ core::map<s16, bool> ids_to_delete; for(core::map<s16, MapBlockObject*>::Iterator i = m_objects.getIterator(); i.atEnd() == false; i++) { ids_to_delete.insert(i.getNode()->getKey(), true); } u8 buf[6]; is.read((char*)buf, 2); u16 count = readU16(buf); for(u16 i=0; i<count; i++) { // Read id is.read((char*)buf, 2); s16 id = readS16(buf); // Read position // stored as x1000/BS v3s16 is.read((char*)buf, 6); v3s16 pos_i = readV3S16(buf); v3f pos((f32)pos_i.X/1000*BS, (f32)pos_i.Y/1000*BS, (f32)pos_i.Z/1000*BS); // Read typeId is.read((char*)buf, 2); u16 type_id = readU16(buf); bool create_new = false; // Find an object with the id core::map<s16, MapBlockObject*>::Node *n; n = m_objects.find(id); // If no entry is found for id if(n == NULL) { // Insert dummy pointer node m_objects.insert(id, NULL); // Get node n = m_objects.find(id); // A new object will be created at this node create_new = true; } // If type_id differs else if(n->getValue()->getTypeId() != type_id) { // Delete old object delete n->getValue(); // A new object will be created at this node create_new = true; } MapBlockObject *obj = NULL; if(create_new) { /*dstream<<"MapBlockObjectList adding new object" " id="<<id <<std::endl;*/ if(type_id == MAPBLOCKOBJECT_TYPE_SIGN) { obj = new SignObject(m_block, id, pos); } else if(type_id == MAPBLOCKOBJECT_TYPE_RAT) { obj = new RatObject(m_block, id, pos); } else if(type_id == MAPBLOCKOBJECT_TYPE_ITEM) { obj = new ItemObject(m_block, id, pos); } else { // This is fatal because we cannot know the length // of the object's data throw SerializationError ("MapBlockObjectList::update(): Unknown MapBlockObject type"); } if(smgr != NULL) //obj->addToScene(smgr, daynight_ratio); obj->addToScene(smgr); n->setValue(obj); } else { obj = n->getValue(); obj->updatePos(pos); /*if(daynight_ratio != m_last_update_daynight_ratio) { obj->removeFromScene(); obj->addToScene(smgr, daynight_ratio); }*/ } // Now there is an object in obj. // Update it. obj->update(is, version); obj->setBlockChanged(); /* Update light on client */ if(smgr != NULL) { u8 light = LIGHT_MAX; try{ v3s16 relpos_i = floatToInt(obj->m_pos, BS); MapNode n = m_block->getNodeParent(relpos_i); light = n.getLightBlend(daynight_ratio); } catch(InvalidPositionException &e) {} obj->updateLight(light); } // Remove from deletion list if(ids_to_delete.find(id) != NULL) ids_to_delete.remove(id); } // Delete all objects whose ids_to_delete remain in ids_to_delete for(core::map<s16, bool>::Iterator i = ids_to_delete.getIterator(); i.atEnd() == false; i++) { s16 id = i.getNode()->getKey(); /*dstream<<"MapBlockObjectList deleting object" " id="<<id <<std::endl;*/ MapBlockObject *obj = m_objects[id]; obj->removeFromScene(); delete obj; m_objects.remove(id); } m_last_update_daynight_ratio = daynight_ratio; }
void CraftDefinitionToolRepair::deSerializeBody(std::istream &is, int version) { if(version != 1) throw SerializationError( "unsupported CraftDefinitionToolRepair version"); additional_wear = readF1000(is); }
void MapBlock::serialize(std::ostream &os, u8 version, bool disk) { if(!ser_ver_supported(version)) throw VersionMismatchException("ERROR: MapBlock format not supported"); if (!data) throw SerializationError("ERROR: Not writing dummy block."); FATAL_ERROR_IF(version < SER_FMT_VER_LOWEST_WRITE, "Serialisation version error"); // First byte u8 flags = 0; if(is_underground) flags |= 0x01; if(getDayNightDiff()) flags |= 0x02; if(m_generated == false) flags |= 0x08; writeU8(os, flags); if (version >= 27) { writeU16(os, m_lighting_complete); } /* Bulk node data */ NameIdMapping nimap; 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, version, disk); 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); } } }
//// Serialization of old ContentFeatures formats void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) const { if (protocol_version == 13) { writeU8(os, 5); // version os<<serializeString(name); writeU16(os, groups.size()); for (ItemGroupList::const_iterator i = groups.begin(); i != groups.end(); i++) { os<<serializeString(i->first); writeS16(os, i->second); } writeU8(os, drawtype); writeF1000(os, visual_scale); writeU8(os, 6); for (u32 i = 0; i < 6; i++) tiledef[i].serialize(os, protocol_version); //CF_SPECIAL_COUNT = 2 before cf ver. 7 and protocol ver. 24 writeU8(os, 2); for (u32 i = 0; i < 2; i++) tiledef_special[i].serialize(os, protocol_version); writeU8(os, alpha); writeU8(os, post_effect_color.getAlpha()); writeU8(os, post_effect_color.getRed()); writeU8(os, post_effect_color.getGreen()); writeU8(os, post_effect_color.getBlue()); writeU8(os, param_type); writeU8(os, param_type_2); writeU8(os, is_ground_content); writeU8(os, light_propagates); writeU8(os, sunlight_propagates); writeU8(os, walkable); writeU8(os, pointable); writeU8(os, diggable); writeU8(os, climbable); writeU8(os, buildable_to); os<<serializeString(""); // legacy: used to be metadata_name writeU8(os, liquid_type); os<<serializeString(liquid_alternative_flowing); os<<serializeString(liquid_alternative_source); writeU8(os, liquid_viscosity); writeU8(os, light_source); writeU32(os, damage_per_second); node_box.serialize(os, protocol_version); selection_box.serialize(os, protocol_version); writeU8(os, legacy_facedir_simple); writeU8(os, legacy_wallmounted); serializeSimpleSoundSpec(sound_footstep, os); serializeSimpleSoundSpec(sound_dig, os); serializeSimpleSoundSpec(sound_dug, os); } else if (protocol_version > 13 && protocol_version < 24) { writeU8(os, 6); // version os<<serializeString(name); writeU16(os, groups.size()); for (ItemGroupList::const_iterator i = groups.begin(); i != groups.end(); i++) { os<<serializeString(i->first); writeS16(os, i->second); } writeU8(os, drawtype); writeF1000(os, visual_scale); writeU8(os, 6); for (u32 i = 0; i < 6; i++) tiledef[i].serialize(os, protocol_version); //CF_SPECIAL_COUNT = 2 before cf ver. 7 and protocol ver. 24 writeU8(os, 2); for (u32 i = 0; i < 2; i++) tiledef_special[i].serialize(os, protocol_version); writeU8(os, alpha); writeU8(os, post_effect_color.getAlpha()); writeU8(os, post_effect_color.getRed()); writeU8(os, post_effect_color.getGreen()); writeU8(os, post_effect_color.getBlue()); writeU8(os, param_type); writeU8(os, param_type_2); writeU8(os, is_ground_content); writeU8(os, light_propagates); writeU8(os, sunlight_propagates); writeU8(os, walkable); writeU8(os, pointable); writeU8(os, diggable); writeU8(os, climbable); writeU8(os, buildable_to); os<<serializeString(""); // legacy: used to be metadata_name writeU8(os, liquid_type); os<<serializeString(liquid_alternative_flowing); os<<serializeString(liquid_alternative_source); writeU8(os, liquid_viscosity); writeU8(os, liquid_renewable); writeU8(os, light_source); writeU32(os, damage_per_second); node_box.serialize(os, protocol_version); selection_box.serialize(os, protocol_version); writeU8(os, legacy_facedir_simple); writeU8(os, legacy_wallmounted); serializeSimpleSoundSpec(sound_footstep, os); serializeSimpleSoundSpec(sound_dig, os); serializeSimpleSoundSpec(sound_dug, os); writeU8(os, rightclickable); writeU8(os, drowning); writeU8(os, leveled); writeU8(os, liquid_range); } else throw SerializationError("ContentFeatures::serialize(): " "Unsupported version requested"); }
MapBlock* Database_LevelDB::loadBlock(v3s16 blockpos) { v2s16 p2d(blockpos.X, blockpos.Z); std::string datastr; leveldb::Status s = m_database->Get(leveldb::ReadOptions(), i64tos(getBlockAsInteger(blockpos)), &datastr); if (datastr.length() == 0 && s.ok()) { errorstream << "Blank block data in database (datastr.length() == 0) (" << blockpos.X << "," << blockpos.Y << "," << blockpos.Z << ")" << std::endl; if (g_settings->getBool("ignore_world_load_errors")) { errorstream << "Ignoring block load error. Duck and cover! " << "(ignore_world_load_errors)" << std::endl; } else { throw SerializationError("Blank block data in database"); } return NULL; } if (s.ok()) { /* Make sure sector is loaded */ MapSector *sector = srvmap->createSector(p2d); try { std::istringstream is(datastr, std::ios_base::binary); u8 version = SER_FMT_VER_INVALID; is.read((char *)&version, 1); if (is.fail()) throw SerializationError("ServerMap::loadBlock(): Failed" " to read MapBlock version"); MapBlock *block = NULL; bool created_new = false; block = sector->getBlockNoCreateNoEx(blockpos.Y); if (block == NULL) { block = sector->createBlankBlockNoInsert(blockpos.Y); created_new = true; } // Read basic data block->deSerialize(is, version, true); // If it's a new block, insert it to the map if (created_new) sector->insertBlock(block); /* Save blocks loaded in old format in new format */ //if(version < SER_FMT_VER_HIGHEST || save_after_load) // Only save if asked to; no need to update version //if(save_after_load) // saveBlock(block); // We just loaded it from, so it's up-to-date. block->resetModified(); } catch (SerializationError &e) { errorstream << "Invalid block data in database" << " (" << blockpos.X << "," << blockpos.Y << "," << blockpos.Z << ") (SerializationError): " << e.what() << std::endl; // TODO: Block should be marked as invalid in memory so that it is // not touched but the game can run if (g_settings->getBool("ignore_world_load_errors")) { errorstream << "Ignoring block load error. Duck and cover! " << "(ignore_world_load_errors)" << std::endl; } else { throw SerializationError("Invalid block data in database"); //assert(0); } } return srvmap->getBlockNoCreateNoEx(blockpos); // should not be using this here } return NULL; }
void Circuit::load() { unsigned long element_id; unsigned long version = 0; std::istringstream in(std::ios_base::binary); m_database = new KeyValueStorage(m_savedir, "circuit"); m_virtual_database = new KeyValueStorage(m_savedir, "circuit_virtual"); std::ifstream input_elements_func((m_savedir + DIR_DELIM + elements_func_file).c_str(), std::ios_base::binary); if(input_elements_func.good()) { input_elements_func.read(reinterpret_cast<char*>(&version), sizeof(version)); m_circuit_elements_states.deSerialize(input_elements_func); } #if USE_LEVELDB // Filling list with empty virtual elements auto virtual_it = m_virtual_database->new_iterator(); std::map <unsigned long, std::list <CircuitElementVirtual>::iterator> id_to_virtual_pointer; for(virtual_it->SeekToFirst(); virtual_it->Valid(); virtual_it->Next()) { element_id = stoi(virtual_it->key().ToString()); id_to_virtual_pointer[element_id] = m_virtual_elements.insert(m_virtual_elements.begin(), CircuitElementVirtual(element_id)); if(element_id + 1 > m_max_virtual_id) { m_max_virtual_id = element_id + 1; } } // Filling list with empty elements auto it = m_database->new_iterator(); std::map <unsigned long, std::list <CircuitElement>::iterator> id_to_pointer; for(it->SeekToFirst(); it->Valid(); it->Next()) { element_id = stoi(it->key().ToString()); id_to_pointer[element_id] = m_elements.insert(m_elements.begin(), CircuitElement(element_id)); if(element_id + 1 > m_max_id) { m_max_id = element_id + 1; } } // Loading states of elements std::ifstream input_elements_states((m_savedir + DIR_DELIM + elements_states_file).c_str()); if(input_elements_states.good()) { for(unsigned long i = 0; i < m_elements.size(); ++i) { input_elements_states.read(reinterpret_cast<char*>(&element_id), sizeof(element_id)); if(id_to_pointer.find(element_id) != id_to_pointer.end()) { id_to_pointer[element_id]->deSerializeState(input_elements_states); } else { throw SerializationError(static_cast<std::string>("File \"") + elements_states_file + "\" seems to be corrupted."); } } } // Loading elements data for(it->SeekToFirst(); it->Valid(); it->Next()) { in.str(it->value().ToString()); element_id = stoi(it->key().ToString()); std::list <CircuitElement>::iterator current_element = id_to_pointer[element_id]; current_element->deSerialize(in, id_to_virtual_pointer); current_element->setFunc(m_circuit_elements_states.getFunc(current_element->getFuncId()), current_element->getFuncId()); m_pos_to_iterator[current_element->getPos()] = current_element; } delete it; // Loading virtual elements data for(virtual_it->SeekToFirst(); virtual_it->Valid(); virtual_it->Next()) { in.str(virtual_it->value().ToString()); element_id = stoi(virtual_it->key().ToString()); std::list <CircuitElementVirtual>::iterator current_element = id_to_virtual_pointer[element_id]; current_element->deSerialize(in, current_element, id_to_pointer); } delete virtual_it; #endif }
void ContentFeatures::deSerialize(std::istream &is) { // version detection int version = readU8(is); if (version < 12) throw SerializationError("unsupported ContentFeatures version"); // general name = deSerializeString(is); groups.clear(); u32 groups_size = readU16(is); for (u32 i = 0; i < groups_size; i++) { std::string name = deSerializeString(is); int value = readS16(is); groups[name] = value; } param_type = (enum ContentParamType) readU8(is); param_type_2 = (enum ContentParamType2) readU8(is); // visual drawtype = (enum NodeDrawType) readU8(is); mesh = deSerializeString(is); visual_scale = readF1000(is); if (readU8(is) != 6) throw SerializationError("unsupported tile count"); for (TileDef &td : tiledef) td.deSerialize(is, version, drawtype); for (TileDef &td : tiledef_overlay) td.deSerialize(is, version, drawtype); if (readU8(is) != CF_SPECIAL_COUNT) throw SerializationError("unsupported CF_SPECIAL_COUNT"); for (TileDef &td : tiledef_special) td.deSerialize(is, version, drawtype); alpha = readU8(is); color.setRed(readU8(is)); color.setGreen(readU8(is)); color.setBlue(readU8(is)); palette_name = deSerializeString(is); waving = readU8(is); connect_sides = readU8(is); u16 connects_to_size = readU16(is); connects_to_ids.clear(); for (u16 i = 0; i < connects_to_size; i++) connects_to_ids.push_back(readU16(is)); post_effect_color.setAlpha(readU8(is)); post_effect_color.setRed(readU8(is)); post_effect_color.setGreen(readU8(is)); post_effect_color.setBlue(readU8(is)); leveled = readU8(is); // lighting-related light_propagates = readU8(is); sunlight_propagates = readU8(is); light_source = readU8(is); light_source = MYMIN(light_source, LIGHT_MAX); // map generation is_ground_content = readU8(is); // interaction walkable = readU8(is); pointable = readU8(is); diggable = readU8(is); climbable = readU8(is); buildable_to = readU8(is); rightclickable = readU8(is); damage_per_second = readU32(is); // liquid liquid_type = (enum LiquidType) readU8(is); liquid_alternative_flowing = deSerializeString(is); liquid_alternative_source = deSerializeString(is); liquid_viscosity = readU8(is); liquid_renewable = readU8(is); liquid_range = readU8(is); drowning = readU8(is); floodable = readU8(is); // node boxes node_box.deSerialize(is); selection_box.deSerialize(is); collision_box.deSerialize(is); // sounds deSerializeSimpleSoundSpec(sound_footstep, is, version); deSerializeSimpleSoundSpec(sound_dig, is, version); deSerializeSimpleSoundSpec(sound_dug, is, version); // read legacy properties legacy_facedir_simple = readU8(is); legacy_wallmounted = readU8(is); try { node_dig_prediction = deSerializeString(is); } catch(SerializationError &e) {}; }
void ContentFeatures::msgpack_unpack(msgpack::object o) { MsgpackPacket packet = o.as<MsgpackPacket>(); packet[CONTENTFEATURES_NAME].convert(&name); groups.clear(); packet[CONTENTFEATURES_GROUPS].convert(&groups); int drawtype_tmp; packet[CONTENTFEATURES_DRAWTYPE].convert(&drawtype_tmp); drawtype = (NodeDrawType)drawtype_tmp; packet[CONTENTFEATURES_VISUAL_SCALE].convert(&visual_scale); std::vector<TileDef> tiledef_received; packet[CONTENTFEATURES_TILEDEF].convert(&tiledef_received); if (tiledef_received.size() != 6) throw SerializationError("unsupported tile count"); for(size_t i = 0; i < 6; ++i) tiledef[i] = tiledef_received[i]; std::vector<TileDef> tiledef_special_received; packet[CONTENTFEATURES_TILEDEF_SPECIAL].convert(&tiledef_special_received); if(tiledef_special_received.size() != CF_SPECIAL_COUNT) throw SerializationError("unsupported CF_SPECIAL_COUNT"); for (size_t i = 0; i < CF_SPECIAL_COUNT; ++i) tiledef_special[i] = tiledef_special_received[i]; packet[CONTENTFEATURES_ALPHA].convert(&alpha); packet[CONTENTFEATURES_POST_EFFECT_COLOR].convert(&post_effect_color); int param_type_tmp; packet[CONTENTFEATURES_PARAM_TYPE].convert(¶m_type_tmp); param_type = (ContentParamType)param_type_tmp; packet[CONTENTFEATURES_PARAM_TYPE_2].convert(¶m_type_tmp); param_type_2 = (ContentParamType2)param_type_tmp; packet[CONTENTFEATURES_IS_GROUND_CONTENT].convert(&is_ground_content); packet[CONTENTFEATURES_LIGHT_PROPAGATES].convert(&light_propagates); packet[CONTENTFEATURES_SUNLIGHT_PROPAGATES].convert(&sunlight_propagates); packet[CONTENTFEATURES_WALKABLE].convert(&walkable); packet[CONTENTFEATURES_POINTABLE].convert(&pointable); packet[CONTENTFEATURES_DIGGABLE].convert(&diggable); packet[CONTENTFEATURES_CLIMBABLE].convert(&climbable); packet[CONTENTFEATURES_BUILDABLE_TO].convert(&buildable_to); int liquid_type_tmp; packet[CONTENTFEATURES_LIQUID_TYPE].convert(&liquid_type_tmp); liquid_type = (LiquidType)liquid_type_tmp; packet[CONTENTFEATURES_LIQUID_ALTERNATIVE_FLOWING].convert(&liquid_alternative_flowing); packet[CONTENTFEATURES_LIQUID_ALTERNATIVE_SOURCE].convert(&liquid_alternative_source); packet[CONTENTFEATURES_LIQUID_VISCOSITY].convert(&liquid_viscosity); packet[CONTENTFEATURES_LIGHT_SOURCE].convert(&light_source); packet[CONTENTFEATURES_DAMAGE_PER_SECOND].convert(&damage_per_second); packet[CONTENTFEATURES_NODE_BOX].convert(&node_box); packet[CONTENTFEATURES_SELECTION_BOX].convert(&selection_box); packet[CONTENTFEATURES_LEGACY_FACEDIR_SIMPLE].convert(&legacy_facedir_simple); packet[CONTENTFEATURES_LEGACY_WALLMOUNTED].convert(&legacy_wallmounted); packet[CONTENTFEATURES_SOUND_FOOTSTEP].convert(&sound_footstep); packet[CONTENTFEATURES_SOUND_DIG].convert(&sound_dig); packet[CONTENTFEATURES_SOUND_DUG].convert(&sound_dug); packet[CONTENTFEATURES_RIGHTCLICKABLE].convert(&rightclickable); packet[CONTENTFEATURES_DROWNING].convert(&drowning); packet[CONTENTFEATURES_LEVELED].convert(&leveled); packet[CONTENTFEATURES_WAVING].convert(&waving); packet[CONTENTFEATURES_MESH].convert(&mesh); packet[CONTENTFEATURES_COLLISION_BOX].convert(&collision_box); }
void RemotePlayer::deSerialize(std::istream &is, const std::string &playername, PlayerSAO *sao) { Settings args; if (!args.parseConfigLines(is, "PlayerArgsEnd")) { throw SerializationError("PlayerArgsEnd of player " + playername + " not found!"); } m_dirty = true; //args.getS32("version"); // Version field value not used const std::string &name = args.get("name"); strlcpy(m_name, name.c_str(), PLAYERNAME_SIZE); if (sao) { try { sao->setHPRaw(args.getS32("hp")); } catch(SettingNotFoundException &e) { sao->setHPRaw(PLAYER_MAX_HP_DEFAULT); } try { sao->setBasePosition(args.getV3F("position")); } catch (SettingNotFoundException &e) {} try { sao->setPitch(args.getFloat("pitch")); } catch (SettingNotFoundException &e) {} try { sao->setYaw(args.getFloat("yaw")); } catch (SettingNotFoundException &e) {} try { sao->setBreath(args.getS32("breath"), false); } catch (SettingNotFoundException &e) {} try { const std::string &extended_attributes = args.get("extended_attributes"); Json::Reader reader; Json::Value attr_root; reader.parse(extended_attributes, attr_root); const Json::Value::Members attr_list = attr_root.getMemberNames(); for (const auto &it : attr_list) { Json::Value attr_value = attr_root[it]; sao->setExtendedAttribute(it, attr_value.asString()); } } catch (SettingNotFoundException &e) {} } inventory.deSerialize(is); if (inventory.getList("craftpreview") == NULL) { // Convert players without craftpreview inventory.addList("craftpreview", 1); bool craftresult_is_preview = true; if(args.exists("craftresult_is_preview")) craftresult_is_preview = args.getBool("craftresult_is_preview"); if(craftresult_is_preview) { // Clear craftresult inventory.getList("craftresult")->changeItem(0, ItemStack()); } } }
void MapBlock::serialize(std::ostream &os, u8 version) { if(!ser_ver_supported(version)) throw VersionMismatchException("ERROR: MapBlock format not supported"); if(data == NULL) { throw SerializationError("ERROR: Not writing dummy block."); } // These have no compression if(version <= 3 || version == 5 || version == 6) { u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; u32 buflen = 1 + nodecount * MapNode::serializedLength(version); SharedBuffer<u8> dest(buflen); dest[0] = is_underground; for(u32 i=0; i<nodecount; i++) { u32 s = 1 + i * MapNode::serializedLength(version); data[i].serialize(&dest[s], version); } os.write((char*)*dest, dest.getSize()); } else if(version <= 10) { /* With compression. Compress the materials and the params separately. */ // First byte os.write((char*)&is_underground, 1); u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; // Get and compress materials SharedBuffer<u8> materialdata(nodecount); for(u32 i=0; i<nodecount; i++) { materialdata[i] = data[i].param0; } compress(materialdata, os, version); // Get and compress lights SharedBuffer<u8> lightdata(nodecount); for(u32 i=0; i<nodecount; i++) { lightdata[i] = data[i].param1; } compress(lightdata, os, version); if(version >= 10) { // Get and compress param2 SharedBuffer<u8> param2data(nodecount); for(u32 i=0; i<nodecount; i++) { param2data[i] = data[i].param2; } compress(param2data, os, version); } } // All other versions (newest) else { // First byte u8 flags = 0; if(is_underground) flags |= 0x01; if(m_day_night_differs) flags |= 0x02; if(m_lighting_expired) flags |= 0x04; if(version >= 18) { if(m_generated == false) flags |= 0x08; } os.write((char*)&flags, 1); u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; /* Get data */ // Serialize nodes SharedBuffer<u8> databuf_nodelist(nodecount*3); for(u32 i=0; i<nodecount; i++) { data[i].serialize(&databuf_nodelist[i*3], version); } // Create buffer with different parameters sorted SharedBuffer<u8> databuf(nodecount*3); for(u32 i=0; i<nodecount; i++) { databuf[i] = databuf_nodelist[i*3]; databuf[i+nodecount] = databuf_nodelist[i*3+1]; databuf[i+nodecount*2] = databuf_nodelist[i*3+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()); } } } }
void decompressZlib(std::istream &is, std::ostream &os) { z_stream z; const s32 bufsize = 16384; char input_buffer[bufsize]; char output_buffer[bufsize]; int status = 0; int ret; int bytes_read = 0; int input_buffer_len = 0; z.zalloc = Z_NULL; z.zfree = Z_NULL; z.opaque = Z_NULL; ret = inflateInit(&z); if(ret != Z_OK) throw SerializationError("dcompressZlib: inflateInit failed"); z.avail_in = 0; //dstream<<"initial fail="<<is.fail()<<" bad="<<is.bad()<<std::endl; for(;;) { z.next_out = (Bytef*)output_buffer; z.avail_out = bufsize; if(z.avail_in == 0) { z.next_in = (Bytef*)input_buffer; input_buffer_len = is.readsome(input_buffer, bufsize); z.avail_in = input_buffer_len; //dstream<<"read fail="<<is.fail()<<" bad="<<is.bad()<<std::endl; } if(z.avail_in == 0) { //dstream<<"z.avail_in == 0"<<std::endl; break; } //dstream<<"1 z.avail_in="<<z.avail_in<<std::endl; status = inflate(&z, Z_NO_FLUSH); //dstream<<"2 z.avail_in="<<z.avail_in<<std::endl; bytes_read += is.gcount() - z.avail_in; //dstream<<"bytes_read="<<bytes_read<<std::endl; if(status == Z_NEED_DICT || status == Z_DATA_ERROR || status == Z_MEM_ERROR) { zerr(status); throw SerializationError("decompressZlib: inflate failed"); } int count = bufsize - z.avail_out; //dstream<<"count="<<count<<std::endl; if(count) os.write(output_buffer, count); if(status == Z_STREAM_END) { //dstream<<"Z_STREAM_END"<<std::endl; //dstream<<"z.avail_in="<<z.avail_in<<std::endl; //dstream<<"fail="<<is.fail()<<" bad="<<is.bad()<<std::endl; // Unget all the data that inflate didn't take for(u32 i=0; i < z.avail_in; i++) { is.unget(); if(is.fail() || is.bad()) { dstream<<"unget #"<<i<<" failed"<<std::endl; dstream<<"fail="<<is.fail()<<" bad="<<is.bad()<<std::endl; throw SerializationError("decompressZlib: unget failed"); } } break; } } inflateEnd(&z); }
void MapBlock::deSerialize(std::istream &is, u8 version) { if(!ser_ver_supported(version)) throw VersionMismatchException("ERROR: MapBlock format not supported"); // These have no lighting info if(version <= 1) { setLightingExpired(true); } // These have no "generated" field if(version < 18) { m_generated = true; } // These have no compression if(version <= 3 || version == 5 || version == 6) { u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; char tmp; is.read(&tmp, 1); if(is.gcount() != 1) throw SerializationError ("MapBlock::deSerialize: no enough input data"); is_underground = tmp; for(u32 i=0; i<nodecount; i++) { s32 len = MapNode::serializedLength(version); SharedBuffer<u8> d(len); is.read((char*)*d, len); if(is.gcount() != len) throw SerializationError ("MapBlock::deSerialize: no enough input data"); data[i].deSerialize(*d, version); } } else if(version <= 10) { u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; u8 t8; is.read((char*)&t8, 1); is_underground = t8; { // Uncompress and set material data std::ostringstream os(std::ios_base::binary); decompress(is, os, version); std::string s = os.str(); if(s.size() != nodecount) throw SerializationError ("MapBlock::deSerialize: invalid format"); for(u32 i=0; i<s.size(); i++) { data[i].param0 = s[i]; } } { // Uncompress and set param data std::ostringstream os(std::ios_base::binary); decompress(is, os, version); std::string s = os.str(); if(s.size() != nodecount) throw SerializationError ("MapBlock::deSerialize: invalid format"); for(u32 i=0; i<s.size(); i++) { data[i].param1 = s[i]; } } if(version >= 10) { // Uncompress and set param2 data std::ostringstream os(std::ios_base::binary); decompress(is, os, version); std::string s = os.str(); if(s.size() != nodecount) throw SerializationError ("MapBlock::deSerialize: invalid format"); for(u32 i=0; i<s.size(); i++) { data[i].param2 = s[i]; } } } // All other versions (newest) else { u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; u8 flags; is.read((char*)&flags, 1); is_underground = (flags & 0x01) ? true : false; m_day_night_differs = (flags & 0x02) ? true : false; m_lighting_expired = (flags & 0x04) ? 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 ("MapBlock::deSerialize: decompress resulted in size" " other than nodecount*3"); // deserialize nodes from buffer for(u32 i=0; i<nodecount; i++) { u8 buf[3]; buf[0] = s[i]; buf[1] = s[i+nodecount]; buf[2] = s[i+nodecount*2]; data[i].deSerialize(buf, version); } /* NodeMetadata */ if(version >= 14) { // Ignore errors try{ if(version <= 15) { std::string data = deSerializeString(is); std::istringstream iss(data, std::ios_base::binary); m_node_metadata->deSerialize(iss, m_gamedef); } 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); m_node_metadata->deSerialize(iss, m_gamedef); } } catch(SerializationError &e) { errorstream<<"WARNING: MapBlock::deSerialize(): Ignoring an error" <<" while deserializing node metadata"<<std::endl; } } } }
MapBlock* Database_SQLite3::loadBlock(v3s16 blockpos) { v2s16 p2d(blockpos.X, blockpos.Z); verifyDatabase(); if(sqlite3_bind_int64(m_database_read, 1, getBlockAsInteger(blockpos)) != SQLITE_OK) infostream<<"WARNING: Could not bind block position for load: " <<sqlite3_errmsg(m_database)<<std::endl; if(sqlite3_step(m_database_read) == SQLITE_ROW) { /* Make sure sector is loaded */ MapSector *sector = srvmap->createSector(p2d); /* Load block */ const char * data = (const char *)sqlite3_column_blob(m_database_read, 0); size_t len = sqlite3_column_bytes(m_database_read, 0); std::string datastr(data, len); // srvmap->loadBlock(&datastr, blockpos, sector, false); try { std::istringstream is(datastr, std::ios_base::binary); u8 version = SER_FMT_VER_INVALID; is.read((char*)&version, 1); if(is.fail()) throw SerializationError("ServerMap::loadBlock(): Failed" " to read MapBlock version"); MapBlock *block = NULL; bool created_new = false; block = sector->getBlockNoCreateNoEx(blockpos.Y); if(block == NULL) { block = sector->createBlankBlockNoInsert(blockpos.Y); created_new = true; } // Read basic data block->deSerialize(is, version, true); // If it's a new block, insert it to the map if(created_new) sector->insertBlock(block); /* Save blocks loaded in old format in new format */ //if(version < SER_FMT_VER_HIGHEST || save_after_load) // Only save if asked to; no need to update version //if(save_after_load) // saveBlock(block); // We just loaded it from, so it's up-to-date. block->resetModified(); } catch(SerializationError &e) { errorstream<<"Invalid block data in database" <<" ("<<blockpos.X<<","<<blockpos.Y<<","<<blockpos.Z<<")" <<" (SerializationError): "<<e.what()<<std::endl; // TODO: Block should be marked as invalid in memory so that it is // not touched but the game can run if(g_settings->getBool("ignore_world_load_errors")){ errorstream<<"Ignoring block load error. Duck and cover! " <<"(ignore_world_load_errors)"<<std::endl; } else { throw SerializationError("Invalid block data in database"); //assert(0); } } sqlite3_step(m_database_read); // We should never get more than 1 row, so ok to reset sqlite3_reset(m_database_read); return srvmap->getBlockNoCreateNoEx(blockpos); // should not be using this here } sqlite3_reset(m_database_read); return(NULL); }
void ContentFeatures::deSerialize(std::istream &is) { int version = readU8(is); if(version != 7){ deSerializeOld(is, version); return; } name = deSerializeString(is); groups.clear(); u32 groups_size = readU16(is); for(u32 i = 0; i < groups_size; i++){ std::string name = deSerializeString(is); int value = readS16(is); groups[name] = value; } drawtype = (enum NodeDrawType)readU8(is); visual_scale = readF1000(is); if(readU8(is) != 6) throw SerializationError("unsupported tile count"); for(u32 i = 0; i < 6; i++) tiledef[i].deSerialize(is); if(readU8(is) != CF_SPECIAL_COUNT) throw SerializationError("unsupported CF_SPECIAL_COUNT"); for(u32 i = 0; i < CF_SPECIAL_COUNT; i++) tiledef_special[i].deSerialize(is); alpha = readU8(is); post_effect_color.setAlpha(readU8(is)); post_effect_color.setRed(readU8(is)); post_effect_color.setGreen(readU8(is)); post_effect_color.setBlue(readU8(is)); param_type = (enum ContentParamType)readU8(is); param_type_2 = (enum ContentParamType2)readU8(is); is_ground_content = readU8(is); light_propagates = readU8(is); sunlight_propagates = readU8(is); walkable = readU8(is); pointable = readU8(is); diggable = readU8(is); climbable = readU8(is); buildable_to = readU8(is); deSerializeString(is); // legacy: used to be metadata_name liquid_type = (enum LiquidType)readU8(is); liquid_alternative_flowing = deSerializeString(is); liquid_alternative_source = deSerializeString(is); liquid_viscosity = readU8(is); liquid_renewable = readU8(is); light_source = readU8(is); damage_per_second = readU32(is); node_box.deSerialize(is); selection_box.deSerialize(is); legacy_facedir_simple = readU8(is); legacy_wallmounted = readU8(is); deSerializeSimpleSoundSpec(sound_footstep, is); deSerializeSimpleSoundSpec(sound_dig, is); deSerializeSimpleSoundSpec(sound_dug, is); rightclickable = readU8(is); drowning = readU8(is); leveled = readU8(is); liquid_range = readU8(is); waving = readU8(is); // If you add anything here, insert it primarily inside the try-catch // block to not need to increase the version. try{ // Stuff below should be moved to correct place in a version that // otherwise changes the protocol version mesh = deSerializeString(is); collision_box.deSerialize(is); }catch(SerializationError &e) {}; }
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(m_day_night_differs) 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); } }
void ContentFeatures::deSerializeOld(std::istream &is, int version) { if(version == 5) // In PROTOCOL_VERSION 13 { name = deSerializeString(is); groups.clear(); u32 groups_size = readU16(is); for(u32 i=0; i<groups_size; i++){ std::string name = deSerializeString(is); int value = readS16(is); groups[name] = value; } drawtype = (enum NodeDrawType)readU8(is); visual_scale = readF1000(is); if(readU8(is) != 6) throw SerializationError("unsupported tile count"); for(u32 i=0; i<6; i++) tiledef[i].deSerialize(is); if(readU8(is) != CF_SPECIAL_COUNT) throw SerializationError("unsupported CF_SPECIAL_COUNT"); for(u32 i=0; i<CF_SPECIAL_COUNT; i++) tiledef_special[i].deSerialize(is); alpha = readU8(is); post_effect_color.setAlpha(readU8(is)); post_effect_color.setRed(readU8(is)); post_effect_color.setGreen(readU8(is)); post_effect_color.setBlue(readU8(is)); param_type = (enum ContentParamType)readU8(is); param_type_2 = (enum ContentParamType2)readU8(is); is_ground_content = readU8(is); light_propagates = readU8(is); sunlight_propagates = readU8(is); walkable = readU8(is); pointable = readU8(is); diggable = readU8(is); climbable = readU8(is); buildable_to = readU8(is); deSerializeString(is); // legacy: used to be metadata_name liquid_type = (enum LiquidType)readU8(is); liquid_alternative_flowing = deSerializeString(is); liquid_alternative_source = deSerializeString(is); liquid_viscosity = readU8(is); light_source = readU8(is); damage_per_second = readU32(is); node_box.deSerialize(is); selection_box.deSerialize(is); legacy_facedir_simple = readU8(is); legacy_wallmounted = readU8(is); deSerializeSimpleSoundSpec(sound_footstep, is); deSerializeSimpleSoundSpec(sound_dig, is); deSerializeSimpleSoundSpec(sound_dug, is); } else if (version == 6) { name = deSerializeString(is); groups.clear(); u32 groups_size = readU16(is); for(u32 i=0; i<groups_size; i++){ std::string name = deSerializeString(is); int value = readS16(is); groups[name] = value; } drawtype = (enum NodeDrawType)readU8(is); visual_scale = readF1000(is); if(readU8(is) != 6) throw SerializationError("unsupported tile count"); for(u32 i=0; i<6; i++) tiledef[i].deSerialize(is); // CF_SPECIAL_COUNT in version 6 = 2 if(readU8(is) != 2) throw SerializationError("unsupported CF_SPECIAL_COUNT"); for(u32 i=0; i<2; i++) tiledef_special[i].deSerialize(is); alpha = readU8(is); post_effect_color.setAlpha(readU8(is)); post_effect_color.setRed(readU8(is)); post_effect_color.setGreen(readU8(is)); post_effect_color.setBlue(readU8(is)); param_type = (enum ContentParamType)readU8(is); param_type_2 = (enum ContentParamType2)readU8(is); is_ground_content = readU8(is); light_propagates = readU8(is); sunlight_propagates = readU8(is); walkable = readU8(is); pointable = readU8(is); diggable = readU8(is); climbable = readU8(is); buildable_to = readU8(is); deSerializeString(is); // legacy: used to be metadata_name liquid_type = (enum LiquidType)readU8(is); liquid_alternative_flowing = deSerializeString(is); liquid_alternative_source = deSerializeString(is); liquid_viscosity = readU8(is); liquid_renewable = readU8(is); light_source = readU8(is); damage_per_second = readU32(is); node_box.deSerialize(is); selection_box.deSerialize(is); legacy_facedir_simple = readU8(is); legacy_wallmounted = readU8(is); deSerializeSimpleSoundSpec(sound_footstep, is); deSerializeSimpleSoundSpec(sound_dig, is); deSerializeSimpleSoundSpec(sound_dug, is); rightclickable = readU8(is); drowning = readU8(is); leveled = readU8(is); liquid_range = readU8(is); } else throw SerializationError("unsupported ContentFeatures version"); }
void RemotePlayer::deSerialize(std::istream &is, const std::string &playername, PlayerSAO *sao) { Settings args; if (!args.parseConfigLines(is, "PlayerArgsEnd")) { throw SerializationError("PlayerArgsEnd of player " + playername + " not found!"); } m_dirty = true; //args.getS32("version"); // Version field value not used const std::string &name = args.get("name"); strlcpy(m_name, name.c_str(), PLAYERNAME_SIZE); if (sao) { try { sao->setHPRaw(args.getS32("hp")); } catch(SettingNotFoundException &e) { sao->setHPRaw(PLAYER_MAX_HP_DEFAULT); } try { sao->setBasePosition(args.getV3F("position")); } catch (SettingNotFoundException &e) {} try { sao->setPitch(args.getFloat("pitch")); } catch (SettingNotFoundException &e) {} try { sao->setYaw(args.getFloat("yaw")); } catch (SettingNotFoundException &e) {} try { sao->setBreath(args.getS32("breath"), false); } catch (SettingNotFoundException &e) {} try { const std::string &extended_attributes = args.get("extended_attributes"); std::istringstream iss(extended_attributes); Json::CharReaderBuilder builder; builder.settings_["collectComments"] = false; std::string errs; Json::Value attr_root; Json::parseFromStream(builder, iss, &attr_root, &errs); const Json::Value::Members attr_list = attr_root.getMemberNames(); for (const auto &it : attr_list) { Json::Value attr_value = attr_root[it]; sao->getMeta().setString(it, attr_value.asString()); } sao->getMeta().setModified(false); } catch (SettingNotFoundException &e) {} } try { inventory.deSerialize(is); } catch (SerializationError &e) { errorstream << "Failed to deserialize player inventory. player_name=" << name << " " << e.what() << std::endl; } if (!inventory.getList("craftpreview") && inventory.getList("craftresult")) { // Convert players without craftpreview inventory.addList("craftpreview", 1); bool craftresult_is_preview = true; if(args.exists("craftresult_is_preview")) craftresult_is_preview = args.getBool("craftresult_is_preview"); if(craftresult_is_preview) { // Clear craftresult inventory.getList("craftresult")->changeItem(0, ItemStack()); } } }