예제 #1
0
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);
        }
    }
}
예제 #2
0
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);
        }
예제 #3
0
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);
		}
	}

}
예제 #4
0
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");
	}
}
예제 #5
0
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;
}
예제 #6
0
void CraftDefinitionToolRepair::deSerializeBody(std::istream &is, int version)
{
	if(version != 1) throw SerializationError(
			"unsupported CraftDefinitionToolRepair version");
	additional_wear = readF1000(is);
}
예제 #7
0
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);
		}
	}
}
예제 #8
0
//// 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");
}
예제 #9
0
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;
}
예제 #10
0
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
}
예제 #11
0
파일: nodedef.cpp 프로젝트: EXio4/minetest
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) {};
}
예제 #12
0
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(&param_type_tmp);
	param_type = (ContentParamType)param_type_tmp;
	packet[CONTENTFEATURES_PARAM_TYPE_2].convert(&param_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);
}
예제 #13
0
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());
		}
	}
}
예제 #14
0
파일: mapblock.cpp 프로젝트: Neear/minetest
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());
			}
		}
	}
}
예제 #15
0
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);
}
예제 #16
0
파일: mapblock.cpp 프로젝트: Neear/minetest
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;
			}
		}
	}
}
예제 #17
0
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);
}
예제 #18
0
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) {};
}
예제 #19
0
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);
	}
}
예제 #20
0
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");
}
예제 #21
0
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());
		}
	}
}