From 06cdce1e1231fb5946ac9750f9b53b53c6f7e5f8 Mon Sep 17 00:00:00 2001
From: proller <proller@github.com>
Date: Fri, 2 Aug 2013 00:51:36 +0400
Subject: [PATCH] Weather backward compatibility

---
 src/client.cpp      |  9 +++++----
 src/clientserver.h  |  3 ++-
 src/main.cpp        |  2 +-
 src/map.cpp         |  8 ++++----
 src/mapblock.cpp    | 43 +++++++++++++++++++++++++++++++++----------
 src/mapblock.h      |  3 +++
 src/mapgen.cpp      |  4 ++--
 src/serialization.h |  8 +++++---
 src/server.cpp      |  9 +++++----
 src/server.h        |  2 +-
 src/test.cpp        |  4 ++--
 11 files changed, 63 insertions(+), 32 deletions(-)

diff --git a/src/client.cpp b/src/client.cpp
index e5ba14850..f9908ad2c 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -556,14 +556,14 @@ void Client::step(float dtime)
 	
 			// Send TOSERVER_INIT
 			// [0] u16 TOSERVER_INIT
-			// [2] u8 SER_FMT_VER_HIGHEST
+			// [2] u8 SER_FMT_VER_HIGHEST_READ
 			// [3] u8[20] player_name
 			// [23] u8[28] password (new in some version)
 			// [51] u16 minimum supported network protocol version (added sometime)
 			// [53] u16 maximum supported network protocol version (added later than the previous one)
 			SharedBuffer<u8> data(2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2+2);
 			writeU16(&data[0], TOSERVER_INIT);
-			writeU8(&data[2], SER_FMT_VER_HIGHEST);
+			writeU8(&data[2], SER_FMT_VER_HIGHEST_READ);
 
 			memset((char*)&data[3], 0, PLAYERNAME_SIZE);
 			snprintf((char*)&data[3], PLAYERNAME_SIZE, "%s", myplayer->getName());
@@ -1154,8 +1154,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
 		infostream<<"Client: TOCLIENT_INIT received with "
 				"deployed="<<((int)deployed&0xff)<<std::endl;
 
-		if(deployed < SER_FMT_VER_LOWEST
-				|| deployed > SER_FMT_VER_HIGHEST)
+		if(!ser_ver_supported(deployed))
 		{
 			infostream<<"Client: TOCLIENT_INIT: Server sent "
 					<<"unsupported ser_fmt_ver"<<std::endl;
@@ -1300,6 +1299,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
 			*/
 			//infostream<<"Updating"<<std::endl;
 			block->deSerialize(istr, ser_version, false);
+			block->deSerializeNetworkSpecific(istr);
 		}
 		else
 		{
@@ -1309,6 +1309,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
 			//infostream<<"Creating new"<<std::endl;
 			block = new MapBlock(&m_env.getMap(), p, this);
 			block->deSerialize(istr, ser_version, false);
+			block->deSerializeNetworkSpecific(istr);
 			sector->insertBlock(block);
 		}
 
diff --git a/src/clientserver.h b/src/clientserver.h
index f490508c2..264da5179 100644
--- a/src/clientserver.h
+++ b/src/clientserver.h
@@ -101,6 +101,7 @@ SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed);
 		range added to ItemDefinition
 		drowning, leveled and liquid_range added to ContentFeatures
 		stepheight and collideWithObjects added to object properties
+		version, heat and humidity transfer in MapBock
 */
 
 #define LATEST_PROTOCOL_VERSION 21
@@ -509,7 +510,7 @@ enum ToServerCommand
 		Sent first after connected.
 
 		[0] u16 TOSERVER_INIT
-		[2] u8 SER_FMT_VER_HIGHEST
+		[2] u8 SER_FMT_VER_HIGHEST_READ
 		[3] u8[20] player_name
 		[23] u8[28] password (new in some version)
 		[51] u16 minimum supported network protocol version (added sometime)
diff --git a/src/main.cpp b/src/main.cpp
index 716da57c3..b3aa9c92f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -893,7 +893,7 @@ int main(int argc, char *argv[])
 
 	// Print startup message
 	infostream<<PROJECT_NAME<<
-			" "<<_("with")<<" SER_FMT_VER_HIGHEST="<<(int)SER_FMT_VER_HIGHEST
+			" "<<_("with")<<" SER_FMT_VER_HIGHEST_READ="<<(int)SER_FMT_VER_HIGHEST_READ
 			<<", "<<BUILD_INFO
 			<<std::endl;
 	
diff --git a/src/map.cpp b/src/map.cpp
index 9c658ba3f..90cd498b7 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -3568,7 +3568,7 @@ void ServerMap::saveSectorMeta(ServerMapSector *sector)
 {
 	DSTACK(__FUNCTION_NAME);
 	// Format used for writing
-	u8 version = SER_FMT_VER_HIGHEST;
+	u8 version = SER_FMT_VER_HIGHEST_WRITE;
 	// Get destination
 	v2s16 pos = sector->getPos();
 	std::string dir = getSectorDir(pos);
@@ -3767,7 +3767,7 @@ void ServerMap::saveBlock(MapBlock *block)
 	}
 
 	// Format used for writing
-	u8 version = SER_FMT_VER_HIGHEST;
+	u8 version = SER_FMT_VER_HIGHEST_WRITE;
 	// Get destination
 	v3s16 p3d = block->getPos();
 
@@ -3875,7 +3875,7 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto
 			Save blocks loaded in old format in new format
 		*/
 
-		if(version < SER_FMT_VER_HIGHEST || save_after_load)
+		if(version < SER_FMT_VER_HIGHEST_WRITE || save_after_load)
 		{
 			saveBlock(block);
 
@@ -3942,7 +3942,7 @@ void ServerMap::loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool
 			Save blocks loaded in old format in new format
 		*/
 
-		//if(version < SER_FMT_VER_HIGHEST || save_after_load)
+		//if(version < SER_FMT_VER_HIGHEST_READ || save_after_load)
 		// Only save if asked to; no need to update version
 		if(save_after_load)
 			saveBlock(block);
diff --git a/src/mapblock.cpp b/src/mapblock.cpp
index bd2e19b41..617ba6584 100644
--- a/src/mapblock.cpp
+++ b/src/mapblock.cpp
@@ -636,11 +636,21 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
 			// Node timers
 			m_node_timers.serialize(os, version);
 		}
-	} else {
-		if(version >= 26){
-			writeF1000(os, heat);
-			writeF1000(os, humidity);
-		}
+	}
+}
+
+void MapBlock::serializeNetworkSpecific(std::ostream &os, u16 net_proto_version)
+{
+	if(data == NULL)
+	{
+		throw SerializationError("ERROR: Not writing dummy block.");
+	}
+
+	if(net_proto_version >= 21){
+		int version = 1;
+		writeU8(os, version);
+		writeF1000(os, heat);
+		writeF1000(os, humidity);
 	}
 }
 
@@ -743,17 +753,30 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
 					<<": Node timers (ver>=25)"<<std::endl);
 			m_node_timers.deSerialize(is, version);
 		}
-	} else {
-		if(version >= 26){
-			heat = readF1000(is);
-			humidity = readF1000(is);
-		}
 	}
 		
 	TRACESTREAM(<<"MapBlock::deSerialize "<<PP(getPos())
 			<<": Done."<<std::endl);
 }
 
+void MapBlock::deSerializeNetworkSpecific(std::istream &is)
+{
+	try {
+		int version = readU8(is);
+		//if(version != 1)
+		//	throw SerializationError("unsupported MapBlock version");
+		if(version >= 1) {
+			heat = readF1000(is);
+			humidity = readF1000(is);
+		}
+	}
+	catch(SerializationError &e)
+	{
+		errorstream<<"WARNING: MapBlock::deSerializeNetworkSpecific(): Ignoring an error"
+				<<": "<<e.what()<<std::endl;
+	}
+}
+
 /*
 	Legacy serialization
 */
diff --git a/src/mapblock.h b/src/mapblock.h
index 016841115..576122201 100644
--- a/src/mapblock.h
+++ b/src/mapblock.h
@@ -479,6 +479,9 @@ class MapBlock /*: public NodeContainer*/
 	// unknown blocks from id-name mapping to wndef
 	void deSerialize(std::istream &is, u8 version, bool disk);
 
+	void serializeNetworkSpecific(std::ostream &os, u16 net_proto_version);
+	void deSerializeNetworkSpecific(std::istream &is);
+
 private:
 	/*
 		Private methods
diff --git a/src/mapgen.cpp b/src/mapgen.cpp
index 6bc487331..d285129fb 100644
--- a/src/mapgen.cpp
+++ b/src/mapgen.cpp
@@ -691,7 +691,7 @@ bool DecoSchematic::loadSchematicFile() {
 
 	delete schematic;
 	schematic = new MapNode[nodecount];
-	MapNode::deSerializeBulk(is, SER_FMT_VER_HIGHEST, schematic,
+	MapNode::deSerializeBulk(is, SER_FMT_VER_HIGHEST_READ, schematic,
 				nodecount, 2, 2, true);
 				
 	return true;
@@ -738,7 +738,7 @@ void DecoSchematic::saveSchematicFile(INodeDefManager *ndef) {
 		os << serializeString(ndef->get(usednodes[i]).name); // node names
 		
 	// compressed bulk node data
-	MapNode::serializeBulk(os, SER_FMT_VER_HIGHEST, schematic,
+	MapNode::serializeBulk(os, SER_FMT_VER_HIGHEST_WRITE, schematic,
 				nodecount, 2, 2, true);
 }
 
diff --git a/src/serialization.h b/src/serialization.h
index 807b68e9d..86da31486 100644
--- a/src/serialization.h
+++ b/src/serialization.h
@@ -61,16 +61,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 	23: new node metadata format
 	24: 16-bit node ids and node timers (never released as stable)
 	25: Improved node timer format
-	26: MapBlocks contain heat and humidity
+	26: Never written; read the same as 25
 */
 // This represents an uninitialized or invalid format
 #define SER_FMT_VER_INVALID 255
 // Highest supported serialization version
-#define SER_FMT_VER_HIGHEST 26
+#define SER_FMT_VER_HIGHEST_READ 26
+// Saved on disk version
+#define SER_FMT_VER_HIGHEST_WRITE 25
 // Lowest supported serialization version
 #define SER_FMT_VER_LOWEST 0
 
-#define ser_ver_supported(v) (v >= SER_FMT_VER_LOWEST && v <= SER_FMT_VER_HIGHEST)
+#define ser_ver_supported(v) (v >= SER_FMT_VER_LOWEST && v <= SER_FMT_VER_HIGHEST_READ)
 
 /*
 	Misc. serialization functions
diff --git a/src/server.cpp b/src/server.cpp
index 6e31d288c..8c67846c5 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -1783,7 +1783,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 	if(command == TOSERVER_INIT)
 	{
 		// [0] u16 TOSERVER_INIT
-		// [2] u8 SER_FMT_VER_HIGHEST
+		// [2] u8 SER_FMT_VER_HIGHEST_READ
 		// [3] u8[20] player_name
 		// [23] u8[28] password <--- can be sent without this, from old versions
 
@@ -1796,7 +1796,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 		// First byte after command is maximum supported
 		// serialization version
 		u8 client_max = data[2];
-		u8 our_max = SER_FMT_VER_HIGHEST;
+		u8 our_max = SER_FMT_VER_HIGHEST_READ;
 		// Use the highest version supported by both
 		u8 deployed = std::min(client_max, our_max);
 		// If it's lower than the lowest supported, give up.
@@ -4079,7 +4079,7 @@ void Server::setBlockNotSent(v3s16 p)
 	}
 }
 
-void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver)
+void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
 {
 	DSTACK(__FUNCTION_NAME);
 
@@ -4112,6 +4112,7 @@ void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver)
 
 	std::ostringstream os(std::ios_base::binary);
 	block->serialize(os, ver, false);
+	block->serializeNetworkSpecific(os, net_proto_version);
 	std::string s = os.str();
 	SharedBuffer<u8> blockdata((u8*)s.c_str(), s.size());
 
@@ -4195,7 +4196,7 @@ void Server::SendBlocks(float dtime)
 
 		RemoteClient *client = getClient(q.peer_id);
 
-		SendBlockNoLock(q.peer_id, block, client->serialization_version);
+		SendBlockNoLock(q.peer_id, block, client->serialization_version, client->net_proto_version);
 
 		client->SentBlock(q.pos);
 
diff --git a/src/server.h b/src/server.h
index 65762d901..4d8d0ca67 100644
--- a/src/server.h
+++ b/src/server.h
@@ -603,7 +603,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 	void setBlockNotSent(v3s16 p);
 
 	// Environment and Connection must be locked when called
-	void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
+	void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version);
 
 	// Sends blocks to clients (locks env and con on its own)
 	void SendBlocks(float dtime);
diff --git a/src/test.cpp b/src/test.cpp
index 7753e1d5f..fa7a82428 100644
--- a/src/test.cpp
+++ b/src/test.cpp
@@ -612,7 +612,7 @@ struct TestCompress: public TestBase
 		fromdata[3]=1;
 		
 		std::ostringstream os(std::ios_base::binary);
-		compress(fromdata, os, SER_FMT_VER_HIGHEST);
+		compress(fromdata, os, SER_FMT_VER_HIGHEST_READ);
 
 		std::string str_out = os.str();
 		
@@ -627,7 +627,7 @@ struct TestCompress: public TestBase
 		std::istringstream is(str_out, std::ios_base::binary);
 		std::ostringstream os2(std::ios_base::binary);
 
-		decompress(is, os2, SER_FMT_VER_HIGHEST);
+		decompress(is, os2, SER_FMT_VER_HIGHEST_READ);
 		std::string str_out2 = os2.str();
 
 		infostream<<"decompress: ";
-- 
GitLab